diff options
author | Brian Evans <grknight@gentoo.org> | 2020-10-02 15:24:06 -0400 |
---|---|---|
committer | Brian Evans <grknight@gentoo.org> | 2020-10-02 15:24:06 -0400 |
commit | 60dd5fd95847643eab04ce173f0774c9c584e795 (patch) | |
tree | 52299ac4e3c5c69df75997bfd7d62b71ef9e0089 /MLEB/UniversalLanguageSelector/resources/js | |
parent | Update Widgets to 1.35 (diff) | |
download | extensions-60dd5fd95847643eab04ce173f0774c9c584e795.tar.gz extensions-60dd5fd95847643eab04ce173f0774c9c584e795.tar.bz2 extensions-60dd5fd95847643eab04ce173f0774c9c584e795.zip |
Update MLEB to 2020.07
Signed-off-by: Brian Evans <grknight@gentoo.org>
Diffstat (limited to 'MLEB/UniversalLanguageSelector/resources/js')
14 files changed, 690 insertions, 277 deletions
diff --git a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.common.js b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.common.js index 3b1a6e37..1a22a35a 100644 --- a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.common.js +++ b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.common.js @@ -98,7 +98,7 @@ mw.hook( 'mw.uls.interface.language.change' ).fire( language, deferred ); // Delay is zero if event logging is not enabled - window.setTimeout( function () { + setTimeout( function () { deferred.resolve(); }, mw.config.get( 'wgULSEventLogging' ) * 500 ); diff --git a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.compactlinks.js b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.compactlinks.js index c2ecfb82..61d763ff 100644 --- a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.compactlinks.js +++ b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.compactlinks.js @@ -287,6 +287,7 @@ .text( element.textContent ); // This code is to support badges used in Wikimedia + // eslint-disable-next-line mediawiki/class-doc $languageLink.parent().addClass( element.parentNode.className ); }, onCancel: function () { @@ -317,7 +318,7 @@ // Load the ULS now. mw.loader.using( 'ext.uls.mediawiki' ).then( function () { self.createSelector( self.$trigger ); - self.$trigger.click(); + self.$trigger.trigger( 'click' ); } ); } ); }; diff --git a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.dialog.js b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.dialog.js new file mode 100644 index 00000000..737f6522 --- /dev/null +++ b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.dialog.js @@ -0,0 +1,205 @@ +/*! + * A simple dialog to be used inside ULS. + * + * @private + * @since 2020.01 + * + * Copyright (C) 2019-2020 Alolita Sharma, Amir Aharoni, Arun Ganesh, Brandon Harris, + * Niklas Laxström, Pau Giner, Santhosh Thottingal, Siebrand Mazeland and other + * contributors. See CREDITS for a list. + * + * UniversalLanguageSelector 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. + * + * @file + * @ingroup Extensions + * @licence GNU General Public Licence 2.0 or later + * @licence MIT License + */ + +( function () { + 'use strict'; + + var ULSDialog = function ( options ) { + var $dialog = options.container, + hasOverlay = options.hasOverlay, + $overlay, + // Source: https://github.com/ghosh/Micromodal/blob/master/lib/src/index.js#L4 + FOCUSABLE_NODES = [ + 'a[href]', + 'area[href]', + 'input:not([disabled]):not([type="hidden"]):not([aria-hidden])', + 'select:not([disabled]):not([aria-hidden])', + 'textarea:not([disabled]):not([aria-hidden])', + 'button:not([disabled]):not([aria-hidden])', + 'iframe', + 'object', + 'embed', + '[contenteditable]', + '[tabindex]:not([tabindex^="-"])' + ], + afterOpen = options.afterOpen, + afterClose = options.afterClose; + + function getFocusableNodes() { + return $dialog.find( FOCUSABLE_NODES.join( ', ' ) ); + } + + function isElementInDialog( targetElement ) { + return $dialog.get( 0 ).contains( targetElement ); + } + + function focusOverlay() { + if ( $overlay ) { + $overlay.get( 0 ).focus(); + } + } + + function focusFirstNodeOrOverlay( $focusableNodes ) { + if ( $focusableNodes === undefined ) { + $focusableNodes = getFocusableNodes(); + } + + if ( $focusableNodes.length ) { + $focusableNodes.get( 0 ).focus(); + } else { + focusOverlay(); + } + } + + function maintainFocus( event ) { + var $focusableNodes = getFocusableNodes(), + focusedItemIndex; + + if ( !hasOverlay ) { + // overlay is not present, so let tabbing flow as normal. + return; + } + + if ( !$focusableNodes.length ) { + // no focusable node in the dialog, focus on the overlay. + focusOverlay(); + return; + } + + if ( !isElementInDialog( document.activeElement ) ) { + focusFirstNodeOrOverlay( $focusableNodes ); + } else { + focusedItemIndex = $focusableNodes.index( document.activeElement ); + + if ( event.shiftKey && focusedItemIndex === 0 ) { + $focusableNodes.get( -1 ).focus(); + event.preventDefault(); + } else if ( !event.shiftKey && focusedItemIndex === $focusableNodes.length - 1 ) { + focusFirstNodeOrOverlay( $focusableNodes ); + event.preventDefault(); + } + } + } + + function handleFirstFocus( event ) { + if ( !hasOverlay ) { + // Overlay is not present, so let tabbing flow as normal. + return; + } + + if ( isElementInDialog( event.target ) ) { + return; + } + + focusFirstNodeOrOverlay(); + } + + function onKeydown( event ) { + switch ( event.key ) { + case 'Esc': + case 'Escape': + // eslint-disable-next-line no-use-before-define + close(); + event.preventDefault(); + break; + case 'Tab': + maintainFocus( event ); + break; + } + } + + function addEvents() { + $( document ) + .on( 'keydown', onKeydown ) + .on( 'focusin', handleFirstFocus ); + } + + function removeEvents() { + $( document ) + .off( 'keydown', onKeydown ) + .off( 'focusin', handleFirstFocus ); + } + + function showOverlay() { + if ( $overlay ) { + $overlay.show(); + $( document.body ).addClass( 'uls-no-overflow' ); + } + } + + function hideOverlay() { + if ( $overlay ) { + $overlay.hide(); + $( document.body ).removeClass( 'uls-no-overflow' ); + } + } + + function open() { + $dialog.show(); + addEvents(); + showOverlay(); + focusFirstNodeOrOverlay(); + if ( afterOpen ) { + afterOpen(); + } + } + + function close() { + $dialog.hide(); + removeEvents(); + hideOverlay(); + if ( afterClose ) { + afterClose(); + } + } + + function elem() { + return $dialog; + } + + function addOverlay() { + // Check if overlay is already there. + if ( !$overlay ) { + $overlay = $( '<div>' ) + .addClass( 'uls-overlay' ) + .prop( 'tabindex', '-1' ) + .on( 'click', close ) + .appendTo( document.body ); + } + } + + $dialog.addClass( 'uls-dialog' ); + + if ( hasOverlay ) { + addOverlay(); + } + + return { + open: open, + close: close, + elem: elem + }; + }; + + mw.uls = mw.uls || {}; + mw.uls.Dialog = ULSDialog; +}() ); diff --git a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.displaysettings.js b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.displaysettings.js index 7b28c7d7..9a1feab8 100644 --- a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.displaysettings.js +++ b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.displaysettings.js @@ -121,7 +121,7 @@ */ render: function () { this.$parent.$settingsPanel.empty(); - this.$webfonts = $( 'body' ).data( 'webfonts' ); + this.$webfonts = $( document.body ).data( 'webfonts' ); this.$parent.$settingsPanel.append( this.$template ); this.prepareLanguages(); this.prepareUIFonts(); @@ -185,7 +185,7 @@ var deferred = new $.Deferred(); $loginCta.html( parsedCta ); // The parsed CTA is HTML - $loginCta.find( 'a' ).click( function ( event ) { + $loginCta.find( 'a' ).on( 'click', function ( event ) { event.preventDefault(); // Because browsers navigate away when clicking a link, // we are overriding the normal click behavior to allow @@ -197,13 +197,13 @@ // if event logging is enabled, in can resole the promise // immediately to avoid extra delays. deferred.done( function () { - window.location.href = event.target.href; + location.href = event.target.href; } ); mw.hook( 'mw.uls.login.click' ).fire( deferred ); // Delay is zero if event logging is not enabled - window.setTimeout( function () { + setTimeout( function () { deferred.resolve(); }, mw.config.get( 'wgULSEventLogging' ) * 500 ); } ); @@ -301,7 +301,7 @@ $back = $( '<div>' ) .addClass( 'uls-icon-back' ); - $back.click( function () { + $back.on( 'click', function () { uls.hide(); displaySettings.$parent.show(); } ); @@ -312,11 +312,11 @@ uls.$menu.find( '.uls-search-wrapper' ).wrap( $wrap ); uls.$menu.find( '.uls-search-wrapper-wrapper' ).prepend( $back ); - if ( $( '.uls-settings-trigger' ).offset().left > $( window ).width() / 2 ) { - uls.$menu.removeClass( 'selector-left' ).addClass( 'selector-right' ); - } else { - uls.$menu.removeClass( 'selector-right' ).addClass( 'selector-left' ); - } + // Copy callout related classes from parent + // eslint-disable-next-line no-jquery/no-class-state + uls.$menu.toggleClass( 'selector-left', displaySettings.$parent.$window.hasClass( 'selector-left' ) ); + // eslint-disable-next-line no-jquery/no-class-state + uls.$menu.toggleClass( 'selector-right', displaySettings.$parent.$window.hasClass( 'selector-right' ) ); }, onVisible: function () { var $parent; @@ -324,6 +324,7 @@ this.$menu.find( '.uls-languagefilter' ) .prop( 'placeholder', $.i18n( 'ext-uls-display-settings-ui-language' ) ); + // eslint-disable-next-line no-jquery/no-class-state if ( !displaySettings.$parent.$window.hasClass( 'callout' ) ) { // Callout menus will have position rules. // Others use the default position. @@ -341,6 +342,7 @@ } // If the ULS is shown in the sidebar, // add a caret pointing to the icon + // eslint-disable-next-line no-jquery/no-class-state if ( displaySettings.$parent.$window.hasClass( 'callout' ) ) { this.$menu.addClass( 'callout callout--languageselection' ); } else { @@ -549,7 +551,7 @@ // Allow the webfonts library to finish loading setTimeout( function () { - displaySettings.$webfonts = $( 'body' ).data( 'webfonts' ); + displaySettings.$webfonts = $( document.body ).data( 'webfonts' ); mw.webfonts.preferences.enable(); @@ -557,6 +559,7 @@ displaySettings.prepareUIFonts(); displaySettings.i18n(); + // eslint-disable-next-line no-jquery/no-sizzle displaySettings.$webfonts.apply( $uiFontSelector.find( 'option:selected' ) ); displaySettings.$webfonts.refresh(); @@ -577,7 +580,7 @@ $uiFontSelector.on( 'change', function () { displaySettings.markDirty(); mw.webfonts.preferences.setFont( displaySettings.uiLanguage, - $( this ).find( 'option:selected' ).val() + $( this ).val() ); displaySettings.$webfonts.refresh(); } ); @@ -585,7 +588,7 @@ $contentFontSelector.on( 'change', function () { displaySettings.markDirty(); mw.webfonts.preferences.setFont( displaySettings.contentLanguage, - $( this ).find( 'option:selected' ).val() + $( this ).val() ); displaySettings.$webfonts.refresh(); } ); @@ -593,6 +596,7 @@ $tabButtons.on( 'click', function () { var $button = $( this ); + // eslint-disable-next-line no-jquery/no-class-state if ( $button.hasClass( 'mw-ui-pressed' ) ) { return; } @@ -600,6 +604,7 @@ displaySettings.$template.find( '.ext-uls-sub-panel' ).each( function () { var $subPanel = $( this ); + // eslint-disable-next-line no-jquery/no-class-state if ( $subPanel.hasClass( $button.attr( 'id' ) ) ) { $subPanel.removeClass( 'hide' ); } else { diff --git a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.eventlogger.js b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.eventlogger.js index 1c94f60c..a5f4a0be 100644 --- a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.eventlogger.js +++ b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.eventlogger.js @@ -1,6 +1,11 @@ /*! * ULS Event logger * + * See https://meta.wikimedia.org/wiki/Schema:UniversalLanguageSelector + * + * @private + * @since 2013.08 + * * Copyright (C) 2012-2013 Alolita Sharma, Amir Aharoni, Arun Ganesh, Brandon Harris, * Niklas Laxström, Pau Giner, Santhosh Thottingal, Siebrand Mazeland and other * contributors. See CREDITS for a list. @@ -21,229 +26,203 @@ 'use strict'; /** - * ULS Event logger - * See https://meta.wikimedia.org/wiki/Schema:UniversalLanguageSelector + * Try to emit an EventLogging event with schema 'UniversalLanguageSelector'. + * + * If EventLogging is not installed, this simply does nothing. * - * @since 2013.08 + * @param {Object} event Event action and optional fields */ - function ULSEventLogger() { - this.eventDefault = { + function log( event ) { + event = $.extend( { version: 1, token: mw.user.id(), contentLanguage: mw.config.get( 'wgContentLanguage' ), interfaceLanguage: mw.config.get( 'wgUserLanguage' ) + }, event ); + + mw.track( 'event.UniversalLanguageSelector', event ); + } + + /** + * Log language settings open + * + * @param {string} context Where it was opened from + */ + function ulsSettingsOpen( context ) { + log( { + action: 'settings-open', + context: context + } ); + } + + /** + * Log language revert + * + * @param {jQuery.Deferred} deferred + */ + function ulsLanguageRevert( deferred ) { + log( { action: 'ui-lang-revert' } ); + deferred.resolve(); + } + + /** + * Log IME disabling + * + * @param {string} context Where the setting was changed. + */ + function disableIME( context ) { + log( { action: 'ime-disable', context: context } ); + } + + /** + * Log IME enabling + * + * @param {string} context Where the setting was changed. + */ + function enableIME( context ) { + log( { action: 'ime-enable', context: context } ); + } + + /** + * Log IME change + * + * @param {string} inputMethod + */ + function changeIME( inputMethod ) { + log( { + action: 'ime-change', + inputMethod: inputMethod + } ); + } + + /** + * Log login link click in display settings. + * + * @param {jQuery.Deferred} deferred + */ + function loginClick( deferred ) { + log( { action: 'login-click' } ); + deferred.resolve(); + } + + /** + * Log when "More languages" item in IME menu is clicked. + */ + function imeMoreLanguages() { + log( { + action: 'more-languages-access', + context: 'ime' + } ); + } + + /** + * Log interface language change + * + * @param {string} language language code + * @param {jQuery.Deferred} deferred + */ + function interfaceLanguageChange( language, deferred ) { + var logParams = { + action: 'language-change', + context: 'interface', + interfaceLanguage: language }; - this.schemaDefault = 'UniversalLanguageSelector'; - this.listen(); + + log( logParams ); + deferred.resolve(); } - ULSEventLogger.prototype = { - /** - * Local wrapper for 'mw.eventLog.logEvent' - * - * @param {Object} event Event action and optional fields - * @param {string} schema The schema; 'UniversalLanguageSelector' is the default - * @return {jQuery.Promise} jQuery Promise object for the logging call - */ - log: function ( event, schema ) { - // FIXME: We need to create our own deferred for two reasons: - // - logEvent might not be executed immediately - // - we cannot reject a promise returned by it - // So we proxy the original promises status updates. - var deferred = $.Deferred(); - - schema = schema || this.schemaDefault; - - if ( schema === this.schemaDefault ) { - event = $.extend( {}, this.eventBase, event ); - } - - mw.eventLog.logEvent( schema, event ) - .done( deferred.resolve ) - .fail( deferred.reject ); - - return deferred.promise(); - }, - - /** - * Listen for event logging - */ - listen: function () { - // Register handlers for event logging triggers - mw.hook( 'mw.uls.settings.open' ).add( this.ulsSettingsOpen.bind( this ) ); - mw.hook( 'mw.uls.language.revert' ).add( this.ulsLanguageRevert.bind( this ) ); - mw.hook( 'mw.uls.ime.enable' ).add( this.enableIME.bind( this ) ); - mw.hook( 'mw.uls.ime.disable' ).add( this.disableIME.bind( this ) ); - mw.hook( 'mw.uls.ime.change' ).add( this.changeIME.bind( this ) ); - mw.hook( 'mw.uls.login.click' ).add( this.loginClick.bind( this ) ); - mw.hook( 'mw.uls.ime.morelanguages' ).add( this.imeMoreLanguages.bind( this ) ); - mw.hook( 'mw.uls.interface.morelanguages' ).add( this.interfaceMoreLanguages.bind( this ) ); - mw.hook( 'mw.uls.interface.language.change' ).add( this.interfaceLanguageChange.bind( this ) ); - mw.hook( 'mw.uls.font.change' ).add( this.fontChange.bind( this ) ); - mw.hook( 'mw.uls.webfonts.enable' ).add( this.enableWebfonts.bind( this ) ); - mw.hook( 'mw.uls.webfonts.disable' ).add( this.disableWebfonts.bind( this ) ); - - $( 'body' ).on( 'noresults.uls', '.uls-menu .uls-languagefilter', - this.noSearchResults.bind( this ) - ); - }, - - /** - * Log language settings open - * - * @param {string} context Where it was opened from - */ - ulsSettingsOpen: function ( context ) { - this.log( { - action: 'settings-open', - context: context - } ); - }, - - /** - * Log language revert - * - * @param {jQuery.Deferred} deferred - */ - ulsLanguageRevert: function ( deferred ) { - this.log( { action: 'ui-lang-revert' } ).always( deferred.resolve() ); - }, - - /** - * Log IME disabling - * - * @param {string} context Where the setting was changed. - */ - disableIME: function ( context ) { - this.log( { action: 'ime-disable', context: context } ); - }, - - /** - * Log IME enabling - * - * @param {string} context Where the setting was changed. - */ - enableIME: function ( context ) { - this.log( { action: 'ime-enable', context: context } ); - }, - - /** - * Log IME change - * - * @param {string} inputMethod - */ - changeIME: function ( inputMethod ) { - this.log( { - action: 'ime-change', - inputMethod: inputMethod - } ); - }, - - /** - * Log login link click in display settings. - * - * @param {jQuery.Deferred} deferred - */ - loginClick: function ( deferred ) { - this.log( { action: 'login-click' } ).always( deferred.resolve ); - }, - - /** - * More languages item in IME menu is clicked - */ - imeMoreLanguages: function () { - this.log( { - action: 'more-languages-access', - context: 'ime' - } ); - }, - - /** - * Log interface language change - * - * @param {string} language language code - * @param {jQuery.Deferred} deferred - */ - interfaceLanguageChange: function ( language, deferred ) { - var logParams = { - action: 'language-change', - context: 'interface', - interfaceLanguage: language - }; - - this.log( logParams ).always( deferred.resolve ); - }, - - /** - * More languages in display settings is clicked - */ - interfaceMoreLanguages: function () { - this.log( { - action: 'more-languages-access', - context: 'interface' - } ); - }, - - /** - * Log font preference changes - * - * @param {string} context Either 'interface' or 'content' - * @param {string} language - * @param {string} font - */ - fontChange: function ( context, language, font ) { - var logParams = { - action: 'font-change', - context: context - }; - - if ( context === 'interface' ) { - $.extend( logParams, { - interfaceFont: font, - // Override in case the user changed the ui language but hasn't applied it yet - interfaceLanguage: language - } ); - } else { - logParams.contentFont = font; - } - - this.log( logParams ); - }, - - /** - * Log webfonts disabling - * - * @param {string} context Where the setting was changed. - */ - disableWebfonts: function ( context ) { - this.log( { action: 'webfonts-disable', context: context } ); - }, - - /** - * Log webfonts enabling - * - * @param {string} context Where the setting was changed. - */ - enableWebfonts: function ( context ) { - this.log( { action: 'webfonts-enable', context: context } ); - }, - - /** - * Log search strings which produce no search results. - * - * @param {jQuery.event} event The original event - * @param {Object} data Information about the failed search - */ - noSearchResults: function ( event, data ) { - this.log( { - action: 'no-search-results', - context: data.query, - ulsPurpose: data.ulsPurpose, - title: mw.config.get( 'wgPageName' ) - } ); + /** + * More languages in display settings is clicked + */ + function interfaceMoreLanguages() { + log( { + action: 'more-languages-access', + context: 'interface' + } ); + } + + /** + * Log font preference changes + * + * @param {string} context Either 'interface' or 'content' + * @param {string} language + * @param {string} font + */ + function fontChange( context, language, font ) { + var logParams = { + action: 'font-change', + context: context + }; + + if ( context === 'interface' ) { + logParams.interfaceFont = font; + // Override in case the user changed the ui language but hasn't applied it yet + logParams.interfaceLanguage = language; + } else { + logParams.contentFont = font; } - }; - mw.uls = mw.uls || {}; - mw.uls.eventlogger = new ULSEventLogger(); + log( logParams ); + } + + /** + * Log webfonts disabling + * + * @param {string} context Where the setting was changed. + */ + function disableWebfonts( context ) { + log( { action: 'webfonts-disable', context: context } ); + } + + /** + * Log webfonts enabling + * + * @param {string} context Where the setting was changed. + */ + function enableWebfonts( context ) { + log( { action: 'webfonts-enable', context: context } ); + } + + /** + * Log search strings which produce no search results. + * + * @param {jQuery.event} event The original event + * @param {Object} data Information about the failed search + */ + function noSearchResults( event, data ) { + log( { + action: 'no-search-results', + context: data.query, + ulsPurpose: data.ulsPurpose, + title: mw.config.get( 'wgPageName' ) + } ); + } + + /** + * Start listening for event logging + */ + function listen() { + // Register handlers for event logging triggers + mw.hook( 'mw.uls.settings.open' ).add( ulsSettingsOpen ); + mw.hook( 'mw.uls.language.revert' ).add( ulsLanguageRevert ); + mw.hook( 'mw.uls.ime.enable' ).add( enableIME ); + mw.hook( 'mw.uls.ime.disable' ).add( disableIME ); + mw.hook( 'mw.uls.ime.change' ).add( changeIME ); + mw.hook( 'mw.uls.login.click' ).add( loginClick ); + mw.hook( 'mw.uls.ime.morelanguages' ).add( imeMoreLanguages ); + mw.hook( 'mw.uls.interface.morelanguages' ).add( interfaceMoreLanguages ); + mw.hook( 'mw.uls.interface.language.change' ).add( interfaceLanguageChange ); + mw.hook( 'mw.uls.font.change' ).add( fontChange ); + mw.hook( 'mw.uls.webfonts.enable' ).add( enableWebfonts ); + mw.hook( 'mw.uls.webfonts.disable' ).add( disableWebfonts ); + + $( document.body ).on( + 'noresults.uls', + '.uls-menu .uls-languagefilter', + noSearchResults + ); + } + + listen(); }() ); diff --git a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.ime.js b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.ime.js index 117777c7..e0f50283 100644 --- a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.ime.js +++ b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.ime.js @@ -150,7 +150,7 @@ defaultModule: 'input', onClose: function () { // on close of input settings, keep focus in input area. - imeselector.$element.focus(); + imeselector.$element.trigger( 'focus' ); }, top: imeselector.$element.offset().top } ); @@ -226,7 +226,7 @@ var imeSelectors = mw.config.get( 'wgULSImeSelectors' ).join( ', ' ); mw.ime.init(); - $( 'body' ).on( 'focus.ime', imeSelectors, function () { + $( document.body ).on( 'focus.ime', imeSelectors, function () { mw.ime.handleFocus( $( this ) ); } ); }; @@ -235,7 +235,7 @@ * Loads necessary dependencies, checks input for validity and * adds the ime menu for elements that should have it. * - * @param {jquery.Element} $input + * @param {jQuery} $input * @since 2013.11 */ mw.ime.handleFocus = function ( $input ) { @@ -272,7 +272,7 @@ /** * Just adds ime menu to any input element. * - * @param {jquery.Element} $input + * @param {jQuery} $input * @since 2013.11 */ mw.ime.addIme = function ( $input ) { @@ -291,7 +291,7 @@ $ulsTrigger.uls( { onSelect: function ( language ) { $input.data( 'imeselector' ).selectLanguage( language ); - $input.focus(); + $input.trigger( 'focus' ); }, languages: mw.ime.getLanguagesWithIME(), ulsPurpose: 'ime-selector', @@ -308,7 +308,7 @@ title: $.i18n( 'ext-uls-ime-help' ) } ) .addClass( 'ime-perime-help' ) - .click( function ( event ) { + .on( 'click', function ( event ) { event.stopPropagation(); } ); } diff --git a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.inputsettings.js b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.inputsettings.js index f3d47733..099e2a1a 100644 --- a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.inputsettings.js +++ b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.inputsettings.js @@ -80,11 +80,11 @@ */ render: function () { var $enabledOnly, - webfonts = $( 'body' ).data( 'webfonts' ); + webfonts = $( document.body ).data( 'webfonts' ); this.dirty = false; this.$parent.$settingsPanel.empty(); - this.$imes = $( 'body' ).data( 'ime' ); + this.$imes = $( document.body ).data( 'ime' ); this.$parent.$settingsPanel.append( this.$template ); $enabledOnly = this.$template.find( '.enabled-only' ); if ( $.ime.preferences.isEnabled() ) { @@ -173,7 +173,8 @@ $imeLabel = $( '<label>' ).attr( 'for', imeId ); - $inputMethodItem = $( '<input type="radio">' ).attr( { + $inputMethodItem = $( '<input>' ).attr( { + type: 'radio', name: 'ime', id: imeId, value: imeId @@ -306,7 +307,7 @@ $button.on( 'click', buttonHandler( $button ) ); if ( language === selectedImeLanguage ) { - $button.click(); + $button.trigger( 'click' ); } } @@ -339,7 +340,7 @@ .i18n() .text( ' ' ); - $back.click( function () { + $back.on( 'click', function () { uls.hide(); inputSettings.$parent.show(); } ); @@ -350,11 +351,11 @@ uls.$menu.find( '.uls-search-wrapper' ).wrap( $wrap ); uls.$menu.find( '.uls-search-wrapper-wrapper' ).prepend( $back ); - if ( $( '.uls-settings-trigger' ).offset().left > $( window ).width() / 2 ) { - uls.$menu.removeClass( 'selector-left' ).addClass( 'selector-right' ); - } else { - uls.$menu.removeClass( 'selector-right' ).addClass( 'selector-left' ); - } + // Copy callout related classes from parent + // eslint-disable-next-line no-jquery/no-class-state + uls.$menu.toggleClass( 'selector-left', inputSettings.$parent.$window.hasClass( 'selector-left' ) ); + // eslint-disable-next-line no-jquery/no-class-state + uls.$menu.toggleClass( 'selector-right', inputSettings.$parent.$window.hasClass( 'selector-right' ) ); }, onVisible: function () { var $parent; @@ -362,6 +363,7 @@ this.$menu.find( '.uls-languagefilter' ) .prop( 'placeholder', $.i18n( 'ext-uls-input-settings-ui-language' ) ); + // eslint-disable-next-line no-jquery/no-class-state if ( !inputSettings.$parent.$window.hasClass( 'callout' ) ) { // callout menus will have position rules. others use // default position @@ -378,6 +380,7 @@ this.$menu.css( 'top', $parent.css( 'top' ) ); } + // eslint-disable-next-line no-jquery/no-class-state if ( inputSettings.$parent.$window.hasClass( 'callout' ) ) { this.$menu.addClass( 'callout callout--languageselection' ); } else { diff --git a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.interface.js b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.interface.js index f6043623..9004b4d5 100644 --- a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.interface.js +++ b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.interface.js @@ -79,7 +79,7 @@ }; } $.extend( displaySettingsOptions, uls.position() ); - $displaySettings.languagesettings( displaySettingsOptions ).click(); + $displaySettings.languagesettings( displaySettingsOptions ).trigger( 'click' ); } ); } @@ -104,7 +104,7 @@ }, top: position.top, left: position.left - } ).click(); + } ).trigger( 'click' ); } ); } @@ -140,15 +140,15 @@ // if the mouse is over the tooltip, do not hide $( '.uls-tipsy' ).on( 'mouseover', function () { - window.clearTimeout( tipsyTimer ); + clearTimeout( tipsyTimer ); } ).on( 'mouseout', function () { - tipsyTimer = window.setTimeout( hideTipsy, timeout ); + tipsyTimer = setTimeout( hideTipsy, timeout ); } ); // hide the tooltip when clicked on it $( '.uls-tipsy' ).on( 'click', hideTipsy ); - tipsyTimer = window.setTimeout( hideTipsy, timeout ); + tipsyTimer = setTimeout( hideTipsy, timeout ); } // remove any existing popups @@ -162,7 +162,7 @@ ulsPopupPosition = 'after'; } // Reverse for RTL - if ( $( 'html' ).prop( 'dir' ) === 'rtl' ) { + if ( $( document.documentElement ).prop( 'dir' ) === 'rtl' ) { ulsPopupPosition = ( ulsPopupPosition === 'after' ) ? 'before' : 'after'; } } else { @@ -182,7 +182,7 @@ .text( previousAutonym ) .prop( { href: '', - 'class': 'uls-prevlang-link', + class: 'uls-prevlang-link', lang: previousLang, // We could get dir from uls.data, // but we are trying to avoid loading it @@ -201,7 +201,7 @@ mw.hook( 'mw.uls.language.revert' ).fire( deferred ); // Delay is zero if event logging is not enabled - window.setTimeout( function () { + setTimeout( function () { deferred.resolve(); }, mw.config.get( 'wgULSEventLogging' ) * 500 ); } ); @@ -212,14 +212,16 @@ messageKey = 'ext-uls-undo-language-tooltip-text'; } + // Message keys listed above + // eslint-disable-next-line mediawiki/msg-doc return $( '<p>' ).append( mw.message( messageKey, $link ).parseDom() ); }() ) } ); - ulsPopup.$element.appendTo( 'body' ); + ulsPopup.$element.appendTo( document.body ); // The interlanguage position needs some time to settle down - window.setTimeout( function () { + setTimeout( function () { // Show the tipsy tooltip on page load. showTipsy( 6000 ); }, 700 ); @@ -227,6 +229,7 @@ // manually show the tooltip $ulsTrigger.on( 'mouseover', function () { // show only if the ULS panel is not shown + // eslint-disable-next-line no-jquery/no-sizzle if ( !$( '.uls-menu:visible' ).length ) { showTipsy( 3000 ); } @@ -293,7 +296,6 @@ if ( ulsTriggerOffset.left > $( window ).width() / 2 ) { this.left = ulsTriggerOffset.left - this.$window.width() - caretRadius; this.$window.removeClass( 'selector-left' ).addClass( 'selector-right' ); - } else { this.left = ulsTriggerOffset.left + ulsTriggerWidth + caretRadius; this.$window.removeClass( 'selector-right' ).addClass( 'selector-left' ); @@ -311,7 +313,7 @@ }; mw.loader.using( mw.uls.languageSettingsModules, function () { - $ulsTrigger.languagesettings( languageSettingsOptions ).click(); + $ulsTrigger.languagesettings( languageSettingsOptions ).trigger( 'click' ); } ); e.stopPropagation(); @@ -372,7 +374,7 @@ // Allow styles to apply first and position to work by // delaying the activation after them. - window.setTimeout( function () { + setTimeout( function () { $ulsTrigger.trigger( 'click', eventParams ); }, 0 ); } ); @@ -432,9 +434,9 @@ function initIme() { var imeSelector = mw.config.get( 'wgULSImeSelectors' ).join( ', ' ); - $( 'body' ).on( 'focus.imeinit', imeSelector, function () { + $( document.body ).on( 'focus.imeinit', imeSelector, function () { var $input = $( this ); - $( 'body' ).off( '.imeinit' ); + $( document.body ).off( '.imeinit' ); mw.loader.using( 'ext.uls.ime', function () { mw.ime.setup(); mw.ime.handleFocus( $input ); diff --git a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.languagesettings.js b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.languagesettings.js index 177a40e3..467f361b 100644 --- a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.languagesettings.js +++ b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.languagesettings.js @@ -68,7 +68,7 @@ constructor: LanguageSettings, init: function () { - $( 'body' ).append( this.$window ); + $( document.body ).append( this.$window ); this.hide(); }, @@ -81,7 +81,7 @@ this.$window.find( 'button.uls-settings-apply' ) .on( 'click', mw.hook( 'mw.uls.settings.apply' ).fire.bind( this ) ); // Hide the window when clicked outside - $( 'html' ).click( this.hide.bind( this ) ); + $( document.documentElement ).on( 'click', this.hide.bind( this ) ); // ... but when clicked on window do not hide. this.$window.on( 'click', function ( event ) { @@ -136,6 +136,9 @@ .addClass( 'settings-text' ) .attr( 'data-i18n', module.descriptionI18n ); $settingsLink = $( '<button>' ) + // The following classes are used here: + // * display-settings-block + // * input-settings-block .addClass( moduleName + '-settings-block menu-section' ) .prop( 'id', moduleName + '-panel-trigger' ) .data( 'module', module ) @@ -154,6 +157,7 @@ var $this = $( this ); $this.data( 'module' ).render(); + // eslint-disable-next-line no-jquery/no-sizzle if ( languageSettings.$window.is( ':visible' ) ) { languageSettings.$window.scrollIntoView(); } @@ -189,18 +193,18 @@ this.initialized = true; } // Close other modal windows which listen to click events outside them - $( 'html' ).click(); + $( document.documentElement ).trigger( 'click' ); this.i18n(); // Every time we show this window, make sure the current // settings panels is up-to-date. So just click on active menu item. - this.$window.find( '.settings-menu-items > .active' ).click(); + this.$window.find( '.settings-menu-items > .active' ).trigger( 'click' ); this.shown = true; this.$window.show(); this.visible(); this.$window.scrollIntoView(); // For keyboard navigation, put the focus on an element inside the dialog - this.$window.find( '.menu-section.active' ).focus(); + this.$window.find( '.menu-section.active' ).trigger( 'focus' ); }, /** diff --git a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.preferences.js b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.preferences.js index 0569fab4..0afc40b2 100644 --- a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.preferences.js +++ b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.preferences.js @@ -102,7 +102,7 @@ * Set the preference * * @param {string} key - * @param {mixed} value + * @param {Mixed} value */ set: function ( key, value ) { this.preferences[ key ] = value; @@ -126,7 +126,7 @@ save: function ( callback ) { var ulsPreferences = this; - callback = callback || $.noop; + callback = callback || function () {}; if ( this.isAnon ) { // Anonymous user. Save preferences in local storage preferenceStore().set( this.preferenceName, this.preferences ); @@ -147,10 +147,10 @@ mw.uls = mw.uls || {}; mw.uls.preferences = function () { - var data = $( 'body' ).data( 'preferences' ); + var data = $( document.body ).data( 'preferences' ); if ( !data ) { - $( 'body' ).data( 'preferences', ( data = new ULSPreferences() ) ); + $( document.body ).data( 'preferences', ( data = new ULSPreferences() ) ); } return data; }; diff --git a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.setlang.js b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.setlang.js new file mode 100644 index 00000000..c26a01ee --- /dev/null +++ b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.setlang.js @@ -0,0 +1,149 @@ +/*! + * Loaded when setlang query paramter is set on the page. + * + * @private + * @since 2020.01 + * + * Copyright (C) 2019-2020 Alolita Sharma, Amir Aharoni, Arun Ganesh, Brandon Harris, + * Niklas Laxström, Pau Giner, Santhosh Thottingal, Siebrand Mazeland and other + * contributors. See CREDITS for a list. + * + * UniversalLanguageSelector 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. + * + * @file + * @ingroup Extensions + * @licence GNU General Public Licence 2.0 or later + * @licence MIT License + */ + +( function () { + 'use strict'; + var $cancelBtn, $acceptBtn; + + function getHeading( languageName ) { + return $( '<h4>' ).text( + mw.msg( 'ext-uls-setlang-heading', languageName ) + ); + } + + function getMessage( languageName, languageCode ) { + return $( '<p>' ).html( + mw.message( + 'ext-uls-setlang-message', + languageName, + languageCode + ).parse() + ); + } + + function getButtons() { + $cancelBtn = $( '<button>' ) + .addClass( 'mw-ui-button uls-setlang-cancel' ) + .text( mw.msg( 'ext-uls-setlang-cancel' ) ); + + $acceptBtn = $( '<button>' ) + .addClass( 'mw-ui-button mw-ui-progressive active uls-setlang-apply' ) + .text( mw.msg( 'ext-uls-setlang-accept' ) ); + + return $( '<div>' ) + .addClass( 'language-setlang-buttons' ) + .append( + $cancelBtn, + $acceptBtn + ); + } + + function toggleLoading( $btnSubmit, isLoading ) { + $btnSubmit + .text( mw.msg( isLoading ? 'ext-uls-setlang-loading' : 'ext-uls-setlang-accept' ) ) + .prop( 'disabled', isLoading ); + } + + /** + * @return {string} + */ + function currentUrlWithoutSetLang() { + var uri = new mw.Uri(); + delete uri.query.setlang; + return uri.toString(); + } + + function removeSetLangFromHistory() { + if ( 'setlang' in mw.Uri().query ) { + history.replaceState( null, 'no-setlang-url', currentUrlWithoutSetLang() ); + } + } + + function updateLanguage( langCode ) { + var api = new mw.Api(); + return api.postWithToken( 'csrf', { + action: 'ulssetlang', + languagecode: langCode, + formatversion: 2 + } ).done( function () { + location.replace( currentUrlWithoutSetLang() ); + } ).fail( function ( code, result ) { + var apiErrorInfo = result.error && result.error.info || + mw.msg( 'ext-uls-setlang-unknown-error' ); + mw.notify( + mw.msg( 'ext-uls-setlang-error', apiErrorInfo ), + { + type: 'error', + tag: 'uls-setlang-error' + } + ); + } ); + } + + function createSetLangDialog( languageName, languageCode ) { + return $( '<div>' ) + .addClass( 'uls-setlang-dialog' ) + .append( + getHeading( languageName ), + getMessage( languageName, languageCode ), + getButtons() + ).appendTo( document.body ); + } + + function addSetLangDialogEvents( ulsDialog ) { + $acceptBtn.on( 'click', function () { + toggleLoading( $acceptBtn, true ); + updateLanguage( mw.config.get( 'wgULSSetLangCode' ) ).fail( function () { + toggleLoading( $acceptBtn, false ); + } ); + } ); + + $cancelBtn.on( 'click', function () { + ulsDialog.close(); + } ); + } + + $( function () { + var setLangCode = mw.config.get( 'wgULSSetLangCode' ), + setLangName = mw.config.get( 'wgULSSetLangName' ), + currentLangCode = mw.config.get( 'wgULSCurrentLangCode' ), + $ulsDialog, ulsSetLangDialog; + + if ( currentLangCode === setLangCode ) { + removeSetLangFromHistory(); + return; + } + + // Setup and show the dialog + $ulsDialog = createSetLangDialog( setLangName, setLangCode ); + ulsSetLangDialog = new mw.uls.Dialog( { + container: $ulsDialog, + hasOverlay: true, + afterClose: removeSetLangFromHistory + } ); + + addSetLangDialogEvents( ulsSetLangDialog ); + + setTimeout( ulsSetLangDialog.open ); + } ); + +}() ); diff --git a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.webfonts.js b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.webfonts.js index 1a303568..cf942772 100644 --- a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.webfonts.js +++ b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.webfonts.js @@ -72,7 +72,7 @@ // MediaWiki specific overrides for jquery.webfonts $.extend( $.fn.webfonts.defaults, { repository: mediawikiFontRepository, - fontStack: $( 'body' ).css( 'font-family' ).split( /, /g ), + fontStack: $( document.body ).css( 'font-family' ).split( /, /g ), /** * Returns a suitable font from font repository based * on the given language and html classes and user preference. @@ -127,7 +127,7 @@ // This is important because webfonts behavior depends on the font-family // property values set by stylesheets. setTimeout( function () { - $( 'body' ).webfonts(); + $( document.body ).webfonts(); }, 0 ); }; diff --git a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.webfonts.mobile.js b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.webfonts.mobile.js index bf3bb800..aeb3e838 100644 --- a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.webfonts.mobile.js +++ b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.webfonts.mobile.js @@ -32,7 +32,7 @@ // MediaWiki specific overrides for jquery.webfonts $.extend( $.fn.webfonts.defaults, { repository: mediawikiFontRepository, - fontStack: $( 'body' ).css( 'font-family' ).split( /, /g ), + fontStack: $( document.body ).css( 'font-family' ).split( /, /g ), fontSelector: function ( repository, language ) { var font = repository.defaultFont( language ); @@ -45,7 +45,7 @@ } } ); - $( 'body' ).webfonts(); + $( document.body ).webfonts(); } ); }() ); diff --git a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.webfonts.repository.js b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.webfonts.repository.js index a6b50377..a3bab6ed 100644 --- a/MLEB/UniversalLanguageSelector/resources/js/ext.uls.webfonts.repository.js +++ b/MLEB/UniversalLanguageSelector/resources/js/ext.uls.webfonts.repository.js @@ -34,6 +34,11 @@ "East Syriac Adiabene", "SertoUrhoy" ], + "ban-bali": [ + "Vimala", + "Kadiri", + "Pustaka Bali" + ], "bbc": [ "system", "Pangururan" @@ -71,13 +76,20 @@ ], "ckb": [ "system", + "Amiri", "Lateef", - "Scheherazade", - "Amiri" + "Scheherazade" ], "cr": [ "OskiEast" ], + "cu": [ + "system", + "Fedorovsk", + "Menaion", + "Monomakh", + "Ponomar" + ], "cy": [ "system", "ComicNeue", @@ -185,6 +197,11 @@ "ComicNeue", "OpenDyslexic" ], + "id-bali": [ + "Vimala", + "Kadiri", + "Pustaka Bali" + ], "ii": [ "Nuosu SIL" ], @@ -207,6 +224,11 @@ "jv-java": [ "Tuladha Jejeg" ], + "kaw-bali": [ + "Vimala", + "Kadiri", + "Pustaka Bali" + ], "kbg": [ "Jomolhari" ], @@ -261,6 +283,11 @@ "ComicNeue", "OpenDyslexic" ], + "ms-bali": [ + "Vimala", + "Kadiri", + "Pustaka Bali" + ], "muk": [ "Jomolhari" ], @@ -307,6 +334,16 @@ "system", "OpenDyslexic" ], + "sa-bali": [ + "Vimala", + "Kadiri", + "Pustaka Bali" + ], + "sas-bali": [ + "Vimala", + "Kadiri", + "Pustaka Bali" + ], "saz": [ "Pagul" ], @@ -467,6 +504,10 @@ "woff": "EstrangeloEdessa/SyrCOMEdessa.woff?c4484", "woff2": "EstrangeloEdessa/SyrCOMEdessa.woff2?3e525" }, + "Fedorovsk": { + "woff": "Fedorovsk/FedorovskUnicode.woff?1659d", + "woff2": "Fedorovsk/FedorovskUnicode.woff2?245e3" + }, "FreeFont-Thaana": { "woff": "FreeFontThana/FreeFont-Thaana.woff?0f06e", "woff2": "FreeFontThana/FreeFont-Thaana.woff2?ad021", @@ -552,6 +593,10 @@ "woff": "Junicode/Junicode-Italic.woff?c458b", "woff2": "Junicode/Junicode-Italic.woff2?3fe39" }, + "Kadiri": { + "woff": "Kadiri/Kadiri.woff?1b711", + "woff2": "Kadiri/Kadiri.woff2?a266a" + }, "KhmerOS": { "woff": "KhmerOS/KhmerOS.woff?2ef9e", "woff2": "KhmerOS/KhmerOS.woff2?34973" @@ -589,10 +634,18 @@ "woff": "LinuxLibertine/LinLibertine_RIah.woff?1c058", "woff2": "LinuxLibertine/LinLibertine_RIah.woff2?4e887" }, + "Menaion": { + "woff": "Menaion/MenaionUnicode.woff?50cc6", + "woff2": "Menaion/MenaionUnicode.woff2?da37b" + }, "Miriam CLM": { "woff": "MiriamCLM/MiriamCLM-Book.woff?28216", "woff2": "MiriamCLM/MiriamCLM-Book.woff2?f3942" }, + "Monomakh": { + "woff": "Monomakh/MonomakhUnicode.woff?0a8b3", + "woff2": "Monomakh/MonomakhUnicode.woff2?ee286" + }, "Myanmar3": { "woff": "Myanmar3/Myanmar3.woff?60817", "woff2": "Myanmar3/Myanmar3.woff2?2b586" @@ -684,8 +737,8 @@ "woff2": "OskiEast/oskieitalic.woff2?2745f" }, "Padauk": { - "woff": "Padauk/Padauk-Regular.woff?544be", - "woff2": "Padauk/Padauk-Regular.woff2?97419" + "woff": "Padauk/Padauk-Regular.woff?e67df", + "woff2": "Padauk/Padauk-Regular.woff2?a9b3f" }, "Pagul": { "woff": "Pagul/Pagul.woff?4d3bf", @@ -707,6 +760,14 @@ "woff": "Phetsarath/Phetsarath-Bold.woff?8c43d", "woff2": "Phetsarath/Phetsarath-Bold.woff2?2d5a1" }, + "Ponomar": { + "woff": "Ponomar/PonomarUnicode.woff?05ed0", + "woff2": "Ponomar/PonomarUnicode.woff2?ea5c5" + }, + "Pustaka Bali": { + "woff": "PustakaBali/PustakaBali.woff?cb41e", + "woff2": "PustakaBali/PustakaBali.woff2?743c0" + }, "RailwaySans": { "woff": "RailwaySans/RailwaySans.woff?fda9a", "woff2": "RailwaySans/RailwaySans.woff2?a6c17" @@ -755,6 +816,10 @@ "woff": "UnifrakturMaguntia/UnifrakturMaguntia.woff?6ad8f", "woff2": "UnifrakturMaguntia/UnifrakturMaguntia.woff2?23272" }, + "Vimala": { + "woff": "Vimala/Vimala.woff?e387b", + "woff2": "Vimala/Vimala.woff2?70690" + }, "lklug": { "woff": "lklug/lklug.woff?57de7", "woff2": "lklug/lklug.woff2?7d2c4" |