From 4cbb2ca88a012cdf645cc730d09027e08f47ac9b Mon Sep 17 00:00:00 2001 From: Amire80 Date: Fri, 22 Jan 2016 19:06:49 +0200 Subject: [PATCH] Update jquery.ime from upstream * Digit fix in Southern Kurdish. * Rodali, Or-Lekhani and OdiScript layouts. * Major updates for VisualEditor integration by David Chan. Change-Id: Ia7301bddb79c1fbce2af7190494bdd7bdd909862 --- lib/jquery.ime/jquery.ime.js | 743 ++++++++++++------------ lib/jquery.ime/rules/as/as-rodali.js | 147 +++++ lib/jquery.ime/rules/or/or-OdiScript.js | 116 ++++ lib/jquery.ime/rules/or/or-lekhani.js | 11 +- lib/jquery.ime/rules/sdh/sdh-kbd.js | 2 +- lib/jquery.ime/rules/si/si-singlish.js | 2 +- lib/jquery.ime/rules/yo/yo-alt.js | 2 +- 7 files changed, 653 insertions(+), 370 deletions(-) create mode 100644 lib/jquery.ime/rules/as/as-rodali.js create mode 100644 lib/jquery.ime/rules/or/or-OdiScript.js diff --git a/lib/jquery.ime/jquery.ime.js b/lib/jquery.ime/jquery.ime.js index 8bb2d4f8..283c51c4 100644 --- a/lib/jquery.ime/jquery.ime.js +++ b/lib/jquery.ime/jquery.ime.js @@ -3,18 +3,51 @@ * Copyright (c) 2015 Santhosh Thottingal; Licensed GPL, MIT */ ( function ( $ ) { 'use strict'; + var TextEntryFactory, TextEntry, FormWidgetEntry, ContentEditableEntry, + defaultInputMethod; // rangy is defined in the rangy library /*global rangy */ + /** + * Just initializes an empty static object. + * Similar to initClass in https://www.mediawiki.org/wiki/OOjs + * + * @param {Function} fn + */ + function initClass( fn ) { + fn.static = fn.static || {}; + } + + /** + * Inheritance. Uses pattern similar to OOjs (https://www.mediawiki.org/wiki/OOjs). + * Extend prototype and static methods and properties of child constructor from + * a parent constructor. + * + * @param {Function} targetFn + * @param {Function} originFn + */ + function inheritClass( targetFn, originFn ) { + targetFn.parent = originFn; + targetFn.prototype = $.extend( {}, originFn.prototype ); + targetFn.prototype.constructor = originFn.constructor; + targetFn.static = $.extend( {}, originFn.static ); + } + /** * IME Class + * @class + * + * @constructor + * @param {HTMLElement} element Element on which to listen for events + * @param {TextEntry} textEntry Text entry object to use to get/set text * @param {Function} [options.helpHandler] Called for each input method row in the selector * @param {Object} options.helpHandler.imeSelector * @param {String} options.helpHandler.ime Id of the input method */ - function IME( element, options ) { + function IME( element, textEntry, options ) { this.$element = $( element ); + this.textEntry = textEntry; // This needs to be delayed here since extending language list happens at DOM ready $.ime.defaults.languages = arrayKeys( $.ime.languages ); this.options = $.extend( {}, $.ime.defaults, options ); @@ -127,7 +160,7 @@ */ keypress: function ( e ) { var altGr = false, - c, startPos, pos, endPos, divergingPos, input, replacement; + c, input, replacement; if ( !this.active ) { return true; @@ -160,24 +193,10 @@ c = String.fromCharCode( e.which ); - // Get the current caret position. The user may have selected text to overwrite, - // so get both the start and end position of the selection. If there is no selection, - // startPos and endPos will be equal. - pos = this.getCaretPosition( this.$element ); - startPos = pos[0]; - endPos = pos[1]; - - // Get the last few characters before the one the user just typed, + // Append the character being typed to the preceding few characters, // to provide context for the transliteration regexes. - // We need to append c because it hasn't been added to $this.val() yet - input = this.lastNChars( - this.$element.val() || this.$element.text(), - startPos, - this.inputmethod.maxKeyLength - ); - input += c; - - replacement = this.transliterate( input, this.context, altGr ); + input = this.textEntry.getTextBeforeSelection( this.inputmethod.maxKeyLength ); + replacement = this.transliterate( input + c, this.context, altGr ); // Update the context this.context += c; @@ -198,11 +217,7 @@ return true; } - // Drop a common prefix, if any - divergingPos = this.firstDivergence( input, replacement.output ); - input = input.substring( divergingPos ); - replacement.output = replacement.output.substring( divergingPos ); - replaceText( this.$element, replacement.output, startPos - input.length + 1, endPos ); + this.textEntry.replaceTextAtSelection( input.length, replacement.output ); e.stopPropagation(); @@ -332,121 +347,200 @@ return deferred.promise(); }, + }; - /** - * Returns an array [start, end] of the beginning - * and the end of the current selection in $element - * @returns {Array} - */ - getCaretPosition: function ( $element ) { - return getCaretPosition( $element ); - }, + /** + * TextEntry factory + * @class + * + * @constructor + */ + TextEntryFactory = function IMETextEntryFactory() { + this.TextEntryClasses = []; + }; - /** - * Set the caret position in the div. - * @param {jQuery} $element The content editable div element - * @param {Object} position An object with start and end properties. - * @return {Array} If the cursor could not be placed at given position, how - * many characters had to go back to place the cursor - */ - setCaretPosition: function ( $element, position ) { - return setCaretPosition( $element, position ); - }, + /* Inheritance */ - /** - * Find the point at which a and b diverge, i.e. the first position - * at which they don't have matching characters. - * - * @param a String - * @param b String - * @return Position at which a and b diverge, or -1 if a === b - */ - firstDivergence: function ( a, b ) { - return firstDivergence( a, b ); - }, + initClass( TextEntryFactory ); - /** - * Get the n characters in str that immediately precede pos - * Example: lastNChars( 'foobarbaz', 5, 2 ) === 'ba' - * - * @param str String to search in - * @param pos Position in str - * @param n Number of characters to go back from pos - * @return Substring of str, at most n characters long, immediately preceding pos - */ - lastNChars: function ( str, pos, n ) { - return lastNChars( str, pos, n ); + /* Methods */ + + /** + * Register a TextEntry class, with priority over previous registrations + * + * @param {TextEntry} Class to register + */ + TextEntryFactory.prototype.register = function ( TextEntryClass ) { + this.TextEntryClasses.unshift( TextEntryClass ); + }; + + /** + * Wrap an editable element with the appropriate TextEntry class + * + * @param {jQuery} $element The element to wrap + * @return {TextEntry|undefined} A TextEntry, or undefined if no match + */ + TextEntryFactory.prototype.wrap = function ( $element ) { + var i, len, TextEntryClass; + for ( i = 0, len = this.TextEntryClasses.length; i < len; i++ ) { + TextEntryClass = this.TextEntryClasses[ i ]; + if ( TextEntryClass.static.canWrap( $element ) ) { + return new TextEntryClass( $element ); + } + } + return undefined; + }; + + /* Initialization */ + + TextEntryFactory.static.singleton = new TextEntryFactory(); + + /** + * Generic text entry + * @class + * + * @abstract + */ + TextEntry = function IMETextEntry() { + }; + + /* Inheritance */ + + initClass( TextEntry ); + + /* Static methods */ + + /** + * Test whether can wrap this type of element + * + * @param {jQuery} $element The element to wrap + * @return {boolean} Whether the element can be wrapped + */ + TextEntry.static.canWrap = function () { + return false; + }; + + /* Abstract methods */ + + /** + * Get text immediately before the current selection start. + * + * This SHOULD return the empty string for non-collapsed selections. + * + * @param {number} maxLength Maximum number of chars (code units) to return + * @return {String} Up to maxLength of text + */ + TextEntry.prototype.getTextBeforeSelection = null; + + /** + * Replace the currently selected text and/or text before the selection + * + * @param {number} precedingCharCount Number of chars before selection to replace + * @param {String} newText Replacement text + */ + TextEntry.prototype.replaceTextAtSelection = null; + + /** + * TextEntry class for input/textarea widgets + * @class + * + * @constructor + * @param {jQuery} $element The element to wrap + */ + FormWidgetEntry = function IMEFormWidgetEntry( $element ) { + this.$element = $element; + }; + + /* Inheritance */ + + inheritClass( FormWidgetEntry, TextEntry ); + + /* Static methods */ + + /** + * @inheritdoc TextEntry + */ + FormWidgetEntry.static.canWrap = function ( $element ) { + return $element.is( 'input:not([type]), input[type=text], input[type=search], textarea' ) && + !$element.prop( 'readonly' ) && + !$element.prop( 'disabled' ) && + !$element.hasClass( 'noime' ); + }; + + /* Instance methods */ + + /** + * @inheritdoc TextEntry + */ + FormWidgetEntry.prototype.getTextBeforeSelection = function ( maxLength ) { + var pos = this.getCaretPosition(); + return this.$element.val().substring( + Math.max( 0, pos.start - maxLength ), + pos.start + ); + }; + + /** + * @inheritdoc TextEntry + */ + FormWidgetEntry.prototype.replaceTextAtSelection = function ( precedingCharCount, newText ) { + var selection, + length, + newLines, + start, + scrollTop, + pos, + element = this.$element.get( 0 ); + + if ( typeof element.selectionStart === 'number' && typeof element.selectionEnd === 'number' ) { + // IE9+ and all other browsers + start = element.selectionStart; + scrollTop = element.scrollTop; + + // Replace the whole text of the text area: + // text before + newText + text after. + // This could be made better if range selection worked on browsers. + // But for complex scripts, browsers place cursor in unexpected places + // and it's not possible to fix cursor programmatically. + // Ref Bug https://bugs.webkit.org/show_bug.cgi?id=66630 + element.value = element.value.substring( 0, start - precedingCharCount ) + + newText + + element.value.substring( element.selectionEnd, element.value.length ); + + // restore scroll + element.scrollTop = scrollTop; + // set selection + element.selectionStart = element.selectionEnd = start - precedingCharCount + newText.length; + } else { + // IE8 and lower + pos = this.getCaretPosition(); + selection = element.createTextRange(); + length = element.value.length; + // IE doesn't count \n when computing the offset, so we won't either + newLines = element.value.match( /\n/g ); + + if ( newLines ) { + length = length - newLines.length; + } + + selection.moveStart( 'character', pos.start - precedingCharCount ); + selection.moveEnd( 'character', pos.end - length ); + + selection.text = newText; + selection.collapse( false ); + selection.select(); } }; /** - * jQuery plugin ime - * @param {Object} option + * Get the current selection offsets inside the widget + * + * @return {Object} Offsets in chars (0 means first offset *or* no selection in widget) + * @return.start {number} Selection start + * @return.end {number} Selection end */ - $.fn.ime = function ( option ) { - return this.each( function () { - var data, - $this = $( this ), - options = typeof option === 'object' && option; - - // Some exclusions: IME shouldn't be applied to textareas with - // these properties. - if ( $this.prop( 'readonly' ) || - $this.prop( 'disabled' ) || - $this.hasClass( 'noime' ) ) { - return; - } - - data = $this.data( 'ime' ); - - if ( !data ) { - data = new IME( this, options ); - $this.data( 'ime', data ); - } - - if ( typeof option === 'string' ) { - data[option](); - } - } ); - }; - - $.ime = {}; - $.ime.inputmethods = {}; - $.ime.sources = {}; - $.ime.preferences = {}; - $.ime.languages = {}; - - var defaultInputMethod = { - contextLength: 0, - maxKeyLength: 1 - }; - - $.ime.register = function ( inputMethod ) { - $.ime.inputmethods[inputMethod.id] = $.extend( {}, defaultInputMethod, inputMethod ); - }; - - // default options - $.ime.defaults = { - imePath: '../', // Relative/Absolute path for the rules folder of jquery.ime - languages: [], // Languages to be used- by default all languages - helpHandler: null // Called for each ime option in the menu - }; - - /** - * private function for debugging - */ - function debug( $obj ) { - if ( window.console && window.console.log ) { - window.console.log( $obj ); - } - } - - /** - * Returns an array [start, end] of the beginning - * and the end of the current selection in $element - */ - function getCaretPosition( $element ) { - var el = $element.get( 0 ), + FormWidgetEntry.prototype.getCaretPosition = function () { + var el = this.$element.get( 0 ), start = 0, end = 0, normalizedValue, @@ -456,10 +550,6 @@ newLines, endRange; - if ( $element.is( '[contenteditable]' ) ) { - return getDivCaretPosition( el ); - } - if ( typeof el.selectionStart === 'number' && typeof el.selectionEnd === 'number' ) { start = el.selectionStart; end = el.selectionEnd; @@ -499,264 +589,189 @@ } } } + return { start: start, end: end }; + }; - return [start, end]; - } + TextEntryFactory.static.singleton.register( FormWidgetEntry ); /** - * Helper function to get an IE TextRange object for an element + * TextEntry class for ContentEditable + * @class + * + * @constructor + * @param {jQuery} $element The element to wrap */ - function rangeForElementIE( element ) { - var selection; + ContentEditableEntry = function IMEContentEditableEntry( $element ) { + this.$element = $element; + }; - if ( element.nodeName.toLowerCase() === 'input' ) { - selection = element.createTextRange(); - } else { - selection = document.body.createTextRange(); - selection.moveToElementText( element ); + /* Inheritance */ + + inheritClass( ContentEditableEntry, TextEntry ); + + /* Static methods */ + + /** + * @inheritdoc TextEntry + */ + ContentEditableEntry.static.canWrap = function ( $element ) { + return $element.is( '[contenteditable]' ) && !$element.hasClass( 'noime' ); + }; + + /* Instance methods */ + + /** + * @inheritdoc TextEntry + */ + ContentEditableEntry.prototype.getTextBeforeSelection = function ( maxLength ) { + var range = this.getSelectedRange(); + if ( !range || !range.collapsed || range.startContainer.nodeType !== Node.TEXT_NODE ) { + return ''; } + return range.startContainer.nodeValue.substring( + Math.max( 0, range.startOffset - maxLength ), + range.startOffset + ); + }; - return selection; - } - - function replaceText( $element, replacement, start, end ) { - var selection, - length, - newLines, - scrollTop, - range, - correction, - textNode, - element = $element.get( 0 ); - - if ( $element.is( '[contenteditable]' ) ) { - correction = setCaretPosition( $element, { - start: start, - end: end - } ); - - rangy.init(); - selection = rangy.getSelection(); - range = selection.getRangeAt( 0 ); - - if ( correction[0] > 0 ) { - replacement = selection.toString().substring( 0, correction[0] ) + replacement; - } - - textNode = document.createTextNode( replacement ); - range.deleteContents(); - range.insertNode( textNode ); - range.commonAncestorContainer.normalize(); - start = end = start + replacement.length - correction[0]; - setCaretPosition( $element, { - start: start, - end: end - } ); + /** + * @inheritdoc SelectionWrapper + */ + ContentEditableEntry.prototype.replaceTextAtSelection = function ( precedingCharCount, newText ) { + var range, textNode, textOffset, newOffset, newRange; + if ( !this.getSelectedRange() ) { return; } - if ( typeof element.selectionStart === 'number' && typeof element.selectionEnd === 'number' ) { - // IE9+ and all other browsers - scrollTop = element.scrollTop; + // Trigger any externally registered jQuery compositionstart event listeners. + // TODO: Try node.dispatchEvent( new CompositionEvent(...) ) so listeners not + // registered using jQuery will also get triggered, then fallback gracefully for + // browsers that do not support it. + this.$element.trigger( 'compositionstart' ); - // Replace the whole text of the text area: - // text before + replacement + text after. - // This could be made better if range selection worked on browsers. - // But for complex scripts, browsers place cursor in unexpected places - // and it's not possible to fix cursor programmatically. - // Ref Bug https://bugs.webkit.org/show_bug.cgi?id=66630 - element.value = element.value.substring( 0, start ) + - replacement + - element.value.substring( end, element.value.length ); + range = this.getSelectedRange(); - // restore scroll - element.scrollTop = scrollTop; - // set selection - element.selectionStart = element.selectionEnd = start + replacement.length; - } else { - // IE8 and lower - selection = rangeForElementIE(element); - length = element.value.length; - // IE doesn't count \n when computing the offset, so we won't either - newLines = element.value.match( /\n/g ); - - if ( newLines ) { - length = length - newLines.length; - } - - selection.moveStart( 'character', start ); - selection.moveEnd( 'character', end - length ); - - selection.text = replacement; - selection.collapse( false ); - selection.select(); + if ( !range.collapsed ) { + range.deleteContents(); } - } - function getDivCaretPosition( element ) { - var charIndex = 0, - start = 0, - end = 0, - foundStart = false, - foundEnd = false, - sel; + if ( range.startContainer.nodeType === Node.TEXT_NODE ) { + // Alter this text node's content and move the cursor + textNode = range.startContainer; + textOffset = range.startOffset; + textNode.nodeValue = + textNode.nodeValue.substr( 0, textOffset - precedingCharCount ) + + newText + + textNode.nodeValue.substr( textOffset ); + newOffset = textOffset - precedingCharCount + newText.length; + newRange = rangy.createRange(); + newRange.setStart( range.startContainer, newOffset ); + newRange.setEnd( range.startContainer, newOffset ); + rangy.getSelection().setSingleRange( newRange ); + } else { + // XXX assert precedingCharCount === 0 + // Insert a new text node with the new text + textNode = document.createTextNode( newText ); + range.startContainer.insertBefore( + textNode, + range.startContainer.childNodes[ range.startOffset ] + ); + newRange = rangy.createRange(); + newRange.setStart( textNode, textNode.length ); + newRange.setEnd( textNode, textNode.length ); + rangy.getSelection().setSingleRange( newRange ); + } + // Trigger any externally registered jQuery compositionend / input event listeners. + // TODO: Try node.dispatchEvent( new CompositionEvent(...) ) so listeners not + // registered using jQuery will also get triggered, then fallback gracefully for + // browsers that do not support it. + this.$element.trigger( 'compositionend' ); + this.$element.trigger( 'input' ); + }; + + /** + * Get the selection range inside the wrapped element, or null + * + * @return {Range|null} The selection range + */ + ContentEditableEntry.prototype.getSelectedRange = function () { + var sel, range; rangy.init(); sel = rangy.getSelection(); - - function traverseTextNodes( node, range ) { - var i, childNodesCount; - - if ( node.nodeType === Node.TEXT_NODE ) { - if ( !foundStart && node === range.startContainer ) { - start = charIndex + range.startOffset; - foundStart = true; - } - - if ( foundStart && node === range.endContainer ) { - end = charIndex + range.endOffset; - foundEnd = true; - } - - charIndex += node.length; - } else { - childNodesCount = node.childNodes.length; - - for ( i = 0; i < childNodesCount; ++i ) { - traverseTextNodes( node.childNodes[i], range ); - if ( foundEnd ) { - break; - } - } - } + if ( sel.rangeCount === 0 ) { + return null; } - - if ( sel.rangeCount ) { - traverseTextNodes( element, sel.getRangeAt( 0 ) ); + range = sel.getRangeAt( 0 ); + if ( !this.$element[ 0 ].contains( range.commonAncestorContainer ) ) { + return null; } + return range; + }; - return [ start, end ]; - } + TextEntryFactory.static.singleton.register( ContentEditableEntry ); - function setCaretPosition( $element, position ) { - var currentPosition, - startCorrection = 0, - endCorrection = 0, - element = $element[0]; - - setDivCaretPosition( element, position ); - currentPosition = getDivCaretPosition( element ); - // see Bug https://bugs.webkit.org/show_bug.cgi?id=66630 - while ( position.start !== currentPosition[0] ) { - position.start -= 1; // go back one more position. - if ( position.start < 0 ) { - // never go beyond 0 - break; - } - setDivCaretPosition( element, position ); - currentPosition = getDivCaretPosition( element ); - startCorrection += 1; - } - - while ( position.end !== currentPosition[1] ) { - position.end += 1; // go forward one more position. - setDivCaretPosition( element, position ); - currentPosition = getDivCaretPosition( element ); - endCorrection += 1; - if ( endCorrection > 10 ) { - // XXX avoid rare case of infinite loop here. - break; - } - } - - return [startCorrection, endCorrection]; - } + /* Exports */ /** - * Set the caret position in the div. - * @param {Element} element The content editable div element - * @param position + * jQuery plugin ime + * @param {Object} option */ - function setDivCaretPosition( element, position ) { - var nextCharIndex, - charIndex = 0, - range = rangy.createRange(), - foundStart = false, - foundEnd = false; + $.fn.ime = function ( option ) { + return this.each( function () { + var data, textEntry, + $this = $( this ), + options = typeof option === 'object' && option; - range.collapseToPoint( element, 0 ); - - function traverseTextNodes( node ) { - var i, len; - - if ( node.nodeType === 3 ) { - nextCharIndex = charIndex + node.length; - - if ( !foundStart && position.start >= charIndex && position.start <= nextCharIndex ) { - range.setStart( node, position.start - charIndex ); - foundStart = true; - } - - if ( foundStart && position.end >= charIndex && position.end <= nextCharIndex ) { - range.setEnd( node, position.end - charIndex ); - foundEnd = true; - } - - charIndex = nextCharIndex; - } else { - for ( i = 0, len = node.childNodes.length; i < len; ++i ) { - traverseTextNodes( node.childNodes[i] ); - if ( foundEnd ) { - rangy.getSelection().setSingleRange( range ); - break; - } + data = $this.data( 'ime' ); + if ( !data ) { + textEntry = TextEntryFactory.static.singleton.wrap( $this ); + if ( textEntry === undefined ) { + return; } + data = new IME( this, textEntry, options ); + $this.data( 'ime', data ); } - } - traverseTextNodes( element ); + if ( typeof option === 'string' ) { + data[option](); + } + } ); + }; - } + $.ime = {}; + $.ime.inputmethods = {}; + $.ime.sources = {}; + $.ime.preferences = {}; + $.ime.languages = {}; + + $.ime.textEntryFactory = TextEntryFactory.static.singleton; + $.ime.TextEntry = TextEntry; + $.ime.inheritClass = inheritClass; + + defaultInputMethod = { + contextLength: 0, + maxKeyLength: 1 + }; + + $.ime.register = function ( inputMethod ) { + $.ime.inputmethods[inputMethod.id] = $.extend( {}, defaultInputMethod, inputMethod ); + }; + + // default options + $.ime.defaults = { + imePath: '../', // Relative/Absolute path for the rules folder of jquery.ime + languages: [], // Languages to be used- by default all languages + helpHandler: null // Called for each ime option in the menu + }; /** - * Find the point at which a and b diverge, i.e. the first position - * at which they don't have matching characters. - * - * @param a String - * @param b String - * @return Position at which a and b diverge, or -1 if a === b + * private function for debugging */ - function firstDivergence( a, b ) { - var minLength, i; - - minLength = a.length < b.length ? a.length : b.length; - - for ( i = 0; i < minLength; i++ ) { - if ( a.charCodeAt( i ) !== b.charCodeAt( i ) ) { - return i; - } - } - - return -1; - } - - /** - * Get the n characters in str that immediately precede pos - * Example: lastNChars( 'foobarbaz', 5, 2 ) === 'ba' - * - * @param str String to search in - * @param pos Position in str - * @param n Number of characters to go back from pos - * @return Substring of str, at most n characters long, immediately preceding pos - */ - function lastNChars( str, pos, n ) { - if ( n === 0 ) { - return ''; - } else if ( pos <= n ) { - return str.substr( 0, pos ); - } else { - return str.substr( pos - n, n ); + function debug( $obj ) { + if ( window.console && window.console.log ) { + window.console.log( $obj ); } } @@ -1601,6 +1616,10 @@ name: 'ফনেটিক', source: 'rules/as/as-phonetic.js' }, + 'as-rodali': { + name: 'ৰ\'দালি', + source: 'rules/as/as-rodali.js' + }, 'as-transliteration': { name: 'প্ৰতিৰূপান্তৰণ', source: 'rules/as/as-transliteration.js' @@ -2015,6 +2034,10 @@ name: 'ଟ୍ରାନ୍ସଲିଟରେସନ', source: 'rules/or/or-transliteration.js' }, + 'or-OdiScript': { + name: 'ଓଡ଼ିସ୍କ୍ରିପ୍ଟ', + source: 'rules/or/or-OdiScript.js' + }, 'or-inscript': { name: 'ଇନସ୍କ୍ରିପ୍ଟ', source: 'rules/or/or-inscript.js' @@ -2435,7 +2458,7 @@ }, 'or': { autonym: 'ଓଡ଼ିଆ', - inputmethods: [ 'or-phonetic', 'or-transliteration', 'or-inscript', 'or-inscript2', 'or-lekhani' ] + inputmethods: [ 'or-phonetic', 'or-transliteration', 'or-inscript', 'or-inscript2', 'or-lekhani', 'or-OdiScript' ] }, 'pa': { autonym: 'ਪੰਜਾਬੀ', diff --git a/lib/jquery.ime/rules/as/as-rodali.js b/lib/jquery.ime/rules/as/as-rodali.js new file mode 100644 index 00000000..a26e6cd7 --- /dev/null +++ b/lib/jquery.ime/rules/as/as-rodali.js @@ -0,0 +1,147 @@ +( function ( $ ) { + 'use strict'; + + var asRodali = { + id: 'as-rodali', + name: 'ৰ\'দালি', + description: 'Rodali Keyboard', + date: '2015-07-26', + URL: 'http://github.com/wikimedia/jquery.ime', + author: 'Gunadeep Chetia, Subhashish Panigrahi', + license: 'GPLv3', + version: '1.0', + contextLength: 4, + maxKeyLength: 5, + patterns: [ + ['([ক-হড়ঢ়য়])্?ৰৰi','[^a`]', '$1ৃ'], + ['ৰৰi','[^a`]', 'ঋ'], + ['(([ক-হড়ঢ়ৰৱয়]))a','[^a`]', '$1'], + ['([ক-হড়ঢ়ৰৱয়])a','a', '$1া'], + ['([ক-হড়ঢ়ৰৱয়])i','[^a`]', '$1ি'], + ['([ক-হড়ঢ়ৰৱয়])(িi|েe)','[^a`]', '$1ী'], + ['([ক-হড়ঢ়ৰৱয়])u','[^a`]', '$1ু'], + ['([ক-হড়ঢ়ৰৱয়])ুu','[^a`]', '$1ূ'], + ['([ক-হড়ঢ়ৰৱয়])o','[^a`]', '$1ো'], + ['([ক-হড়ঢ়ৰৱয়])e','[^a`]', '$1ে'], + ['([ক-হড়ঢ়ৰৱয়])োi','[^a`]', '$1ৈ'], + ['([ক-হড়ঢ়ৰৱয়])োu','[^a`]', '$1ৌ'], + ['([কঙলষস])(k|K)','[^a`]','$1্ক'], + ['([গঙদল])(g)','[^a`]','$1্গ'], + ['([চশ])c','[^a`]','$1্চ'], + ['([জঞব])j','[^a`]','$1্জ'], + ['নj','[^a`]','ঞ্জ'], + ['([কটণনপলষস])T','[^a`]','$1্ট'], + ['([ডণনল])D','[^a`]','$1্ড'], + ['([গষহ])N','[^a`]','$1্ণ'], + ['([কতনপশসহ])t','[^a`]','$1্ত'], + ['([গদনব])d','[^a`]','$1্দ'], + ['([গঘণতধনপমশসহ])n','[^a`]','$1্ন'], + ['([পমলষস])p','[^a`]','$1্প'], + ['([মস])f', '[^a`]', '$1্ফ'], + ['([বমল])b','[^a`]','$1্ব'], + ['([কগঙটণতদধনমলশষসহ])m','[^a`]','$1্ম'], + ['([ক-ঘচ-ঝট-যলশ-হড়ঢ়য়])r','[^a`]','$1্ৰ'], + ['([কগপ-বমলশসহ])l','[^a`]','$1্ল'], + ['([কনপ])s','[^a`]','$1্স'], + ['([ক-হড়ঢ়য়])(w|b|v)','[^a`]','$1্ব'], + ['([ক-হড়ঢ়য়])y','[^a`]','$1্য'], + ['নc','[^a`]','ঞ্চ'], + ['ৰk','r','ৰ্ক'], + ['ৰg','r','ৰ্গ'], + ['ৰc','r','ৰ্চ'], + ['ৰj','r','ৰ্জ'], + ['ৰT','r','ৰ্ট'], + ['ৰD','r','ৰ্ড'], + ['ৰN','r','ৰ্ণ'], + ['ৰt','r','ৰ্ত'], + ['ৰd','r','ৰ্দ'], + ['ৰn','r','ৰ্ন'], + ['ৰp','r','ৰ্প'], + ['ৰf','r','ৰ্ফ'], + ['ৰb','r','ৰ্ব'], + ['ৰv','r','ৰ্ভ'], + ['ৰm','r','ৰ্ম'], + ['ৰz','r','ৰ্য'], + ['ৰl','r','ৰ্ল'], + ['ৰx','r','ৰ্শ'], + ['ৰS','r','ৰ্ষ'], + ['ৰs','r','ৰ্স'], + ['ৰh','r','ৰ্হ'], + ['ৰR','r','ৰ্ড়'], + ['ৰy','r','ৰ্য়'], + ['ত~','t','ৎ'], + ['অa','a', 'আ'], + ['কh','k', 'খ'], + ['গh','g', 'ঘ'], + ['ণg','N', 'ঙ'], + ['চh','c', 'ছ'], + ['জh','j', 'ঝ'], + ['নG','n', 'ঞ'], + ['টh','T', 'ঠ'], + ['ডh','D', 'ঢ'], + ['তh','t', 'থ'], + ['দh','d', 'ধ'], + ['পh','p', 'ফ'], + ['বh','b', 'ভ'], + ['সh','s', 'শ'], + ['ড়h','R', 'ঢ়'], + ['নg','n', 'ং'], + ['ওi','o', 'ঐ'], + ['ওu','o', 'ঔ'], + ['ইi','i', 'ঈ'], + ['উu','u', 'ঊ'], + ['([kK])', 'ক'], + ['g', 'গ'], + ['G', 'জ্ঞ'], + ['(c|C)', 'চ'], + ['(j|J)', 'জ'], + ['T', 'ট'], + ['D', 'ড'], + ['N', 'ণ'], + ['t', 'ত'], + ['d', 'দ'], + ['n', 'ন'], + ['(p|P)', 'প'], + ['f', 'ফ'], + ['(b|B)', 'ব'], + ['(v|V)', 'ৱ'], + ['(m|M)', 'ম'], + ['z|Z', 'য'], + ['r', 'ৰ'], + ['(l|L)', 'ল'], + ['S', 'ষ'], + ['s', 'স'], + ['h', 'হ'], + ['H', 'ঃ'], + ['R', 'ড়'], + ['(w|W)', 'ৱ'], + ['x', 'শ'], + ['X', 'ক্ষ'], + ['y', 'য়'], + ['a', 'অ'], + ['i', 'ই'], + ['u', 'উ'], + ['e', 'এ'], + ['o', 'ও'], + ['0', '০'], + ['1', '১'], + ['2', '২'], + ['3', '৩'], + ['4', '৪'], + ['5', '৫'], + ['6', '৬'], + ['7', '৭'], + ['8', '৮'], + ['9', '৯'], + ['<','ৃ'], + ['`', '্‌'], + ['\\^', 'ঁ'], + ['\\.', '।'], + ['~', '্'], + ['&', '°'], + ['\\*', '৺'] + ] + }; + + $.ime.register( asRodali ); +}( jQuery ) ); diff --git a/lib/jquery.ime/rules/or/or-OdiScript.js b/lib/jquery.ime/rules/or/or-OdiScript.js new file mode 100644 index 00000000..d4927b41 --- /dev/null +++ b/lib/jquery.ime/rules/or/or-OdiScript.js @@ -0,0 +1,116 @@ +( function ( $ ) { + 'use strict'; + + var orOdiScript = { + id: 'or-OdiScript', + name: 'ଓଡ଼ିସ୍କ୍ରିପ୍ଟ', + description: 'Odia OdiScript input method', + date: '2015-7-28', + URL: 'http://github.com/wikimedia/jquery.ime', + author: 'Manoj Sahukar and Subhashish Panigrahi', + license: 'GPLv3', + version: '1.0', + contextLength: 6, + maxKeyLength: 4, + patterns: [ + ['/([A-Za-z\\>_\\-\\!@#\\$\\^\\&\\%\\*\\~\\.\\|\\\\0-9])', '$1'], + ['\'([\'])','\"'], //'' to " + ['\"([\'])','\'\'\''], //''' + ['([କ-ହ]୍[କ-ହ])@@', 'ର୍\$1'], //reph + ['([କ-ହ])@@', 'ର୍\$1'], //reph + ['%%', 'ଙ୍କ' ], // Anka + ['"', 'ଁ' ], //chanda bindu + ['([ର])}', 'ର‍୍ୟ'], // special case: Ja phala (ର + ZWJ + ୍ୟ) + ['\\}', '୍ୟ' ], // Ja phala + ['୍\ ', '୍‌ '], // ending with halant+zwnj + ['{', 'ୃ' ], // Ru kara + ['େk', 'ୋ' ], // l= ekar, lk = okar + ['ାl', 'ୋ' ], // l= ekar, kl = okar + ['େp', 'ୈ' ], // + ['ୈk', 'ୌ' ], // + ['\\]', '୍ର'], // Ra phala + ['\\[', 'ଅ'], // Type ଅ + ['ଅk','ଆ'], // ଅ + ା = ଆ + ['ଓ##','ୱ'], + ['([ର])##', 'ର‍୍ୱ'], // special case ର + ZWJ + ୍ୱ + ['([କ-ହ])##', '$1୍ୱ'], // + ['ଦQ', 'ହ'], + ['([କନପସମ])Q', 'ତ୍\$1' ], + ['([ଖଥଧ])Q', '$1ି' ], + ['([ନସ])_', '$1୍ତ୍ର' ], //ନ୍ତ୍ର , ସ୍ତ୍ର + ['\\$', 'କ୍ଷ'], + ['\\&&','ଏବଂ'], + ['\\^', 'ଋ'], + ['\\|', 'ଞ'], + ['\\\\', 'ୟ'], + ['<', 'ଏ'], + ['>', 'ଐ'], + ['0', '୦'], + ['1', '୧'], + ['2', '୨'], + ['3', '୩'], + ['4', '୪'], + ['5', '୫'], + ['6', '୬'], + ['7', '୭'], + ['8', '୮'], + ['9', '୯'], + ['a', 'ମ'], + ['A', 'ଢ଼'], + ['b', 'ୁ'], + ['B', 'ଉ'], + ['c', 'ଜ'], + ['C', 'ଝ'], + ['d', '୍'], + ['D', '‌'], //zwnj + ['e', 'ନ'], + ['E', 'ଡ଼'], + ['f', 'ତ'], + ['F', 'ଥ'], + ['G', 'ଇ'], + ['g', 'ି'], + ['H', 'ଈ'], + ['h', 'ୀ'], + ['i', 'ଂ'], + ['I', 'ଠ'], + ['j', 'ର'], + ['J', 'ଣ'], + ['k', 'ା'], + ['K', 'ଶ'], + ['l', 'େ'], + ['L', 'ଷ'], + ['m', 'ଳ'], + ['M', 'ଲ'], + ['n', 'ୂ'], + ['N', 'ଊ'], + ['o', 'ହ'], + ['O', 'ଡ'], + ['p', 'ୈ'], + ['P', 'ଢ'], + ['q', 'ବ'], + ['r', 'ଦ'], + ['R', 'ଧ'], + ['s', 'କ'], + ['S', 'ଖ'], + ['t', 'ସ'], + ['T', 'ଓ'], + ['u', 'ଯ'], + ['U', 'ଟ'], + ['v', 'ଚ'], + ['V', 'ଛ'], + ['w', 'ପ'], + ['W', 'ଫ'], + ['x', 'ଗ'], + ['X', 'ଘ'], + ['y', 'ୌ'], + ['Y', 'ଔ'], + ['z', 'ଭ'], + ['Z', 'ଙ'], + ['`', '।'], + ['~', 'ଃ'], + + ] + }; + + $.ime.register( orOdiScript ); +}( jQuery ) ); diff --git a/lib/jquery.ime/rules/or/or-lekhani.js b/lib/jquery.ime/rules/or/or-lekhani.js index eb36675a..364890a9 100644 --- a/lib/jquery.ime/rules/or/or-lekhani.js +++ b/lib/jquery.ime/rules/or/or-lekhani.js @@ -7,7 +7,7 @@ description: 'Odia Lekhani phonetic input method', date: '2012-10-14', URL: 'http://github.com/wikimedia/jquery.ime', - author: 'Junaid P V and Subhashish Panigrahi', + author: 'Junaid P V, Subhashish Panigrahi and Jnanaranjan Sahu', license: 'GPLv3', version: '1.0', contextLength: 4, @@ -15,7 +15,7 @@ patterns: [ ['\\\\([A-Za-z\\>_~\\.0-9])', '\\\\', '$1'], - ['([(କ-ହୟୱଡ଼ଢ଼ଙ୍କଙ୍ଖଙ୍ଗଙ୍ଘଞ୍ଚଞ୍ଛଞ୍ଝଣ୍ଟଣ୍ଠଣ୍ଡଣ୍ଢନ୍ତନ୍ଥନ୍ଦନ୍ଧମ୍ପମ୍ଫମ୍ବମ୍ଭଞ୍ଜ])a', '$1ା'], + ['([କ-ହୟୱଡ଼ଢ଼ଙ୍କଙ୍ଖଙ୍ଗଙ୍ଘଞ୍ଚଞ୍ଛଞ୍ଝଣ୍ଟଣ୍ଠଣ୍ଡଣ୍ଢନ୍ତନ୍ଥନ୍ଦନ୍ଧମ୍ପମ୍ଫମ୍ବମ୍ଭଞ୍ଜ])a', '$1ା'], ['([କ-ଳଲନ୍ଧଥଡ଼ଢ଼ହୟୱରକ୍ଷଶସଷଙ୍କଙ୍ଖଙ୍ଗଙ୍ଘଞ୍ଚଞ୍ଛଞ୍ଝଣ୍ଟଣ୍ଠଣ୍ଡଣ୍ଢନ୍ତନ୍ଥନ୍ଦନ୍ଧମ୍ପମ୍ଫମ୍ବମ୍ଭଞ୍ଜ])i', '$1\u0b3f'], ['([କ-ହୟୱଡ଼ଢ଼ଙ୍କଙ୍ଖଙ୍ଗଙ୍ଘଞ୍ଚଞ୍ଛଞ୍ଝଣ୍ଟଣ୍ଠଣ୍ଡଣ୍ଢନ୍ତନ୍ଥନ୍ଦନ୍ଧମ୍ପମ୍ଫମ୍ବମ୍ଭଞ୍])I', '$1ୀ'], ['([କ-ହୟୱଡ଼ଢ଼ଙ୍କଙ୍ଖଙ୍ଗଙ୍ଘଞ୍ଚଞ୍ଛଞ୍ଝଣ୍ଟଣ୍ଠଣ୍ଡଣ୍ଢନ୍ତନ୍ଥନ୍ଦନ୍ଧମ୍ପମ୍ଫମ୍ବମ୍ଭଞ୍])u', '$1\u0b41'], @@ -31,13 +31,13 @@ ['([କ-ହୟୱ])(w|v)', '$1୍ୱ'], ['([କ-ହୟୱ])~', '$1\u200C'], - ['([କ-ହୟୱ])y', '$1୍ୟ'], // y + ['([କ-ହୱ])y', '$1୍ୟ'], // y ['z', '୍'], // halanta ['\\.', '।'], //purnacheda ['ଅa', 'ଆ'], ['ଏe', 'ଐ'], - ['(ଅu|ଓo|ଓO)', 'ଔ'], + ['(ଅu|O)', 'ଔ'], ['ଋR', 'ୠ'], // RR ['ଳl', 'ଌ'], // Ll ['ଌl', 'ୡ'], // Lll @@ -45,8 +45,6 @@ ['ଞ୍ଜh', 'ଞ୍ଝ'], // njh ['ଙ୍କh', 'ଙ୍ଖ'], // nkh ['ଙ୍ଗh', 'ଙ୍ଘ'], // ngh - ['ହm', 'ହ୍ମ'], // mh - ['ହn', 'ହ୍ନ'], // nh ['ମ୍ବh', 'ମ୍ଭ'], // mbh or nbh ['ଣ୍ଡai', 'ଣ୍ଡାଇ'], // NDai ['ଜ୍ଜh', 'ଜ୍ଝ'], // jjh @@ -67,7 +65,6 @@ ['ନD|ଣD', 'ଣ୍ଡ'], // nd ['ଣDh', 'ଣ୍ଢ'], //ndh ['ନdh', 'ନ୍ଧ'], // ndht - ['ଷT', '$1୍ଟ'], // ST ['ଟh', 'ଠ'], // Th ['ଡh', 'ଢ'], // Dh ['ତh', 'ଥ'], // th diff --git a/lib/jquery.ime/rules/sdh/sdh-kbd.js b/lib/jquery.ime/rules/sdh/sdh-kbd.js index e1b7c2f1..c76a14c3 100644 --- a/lib/jquery.ime/rules/sdh/sdh-kbd.js +++ b/lib/jquery.ime/rules/sdh/sdh-kbd.js @@ -17,7 +17,7 @@ ['3', '٣'], ['4', '٤'], ['5', '٥'], - ['6', '٦'], + ['6', '۶'], ['7', '٧'], ['8', '٨'], ['9', '٩'], diff --git a/lib/jquery.ime/rules/si/si-singlish.js b/lib/jquery.ime/rules/si/si-singlish.js index 8ba93b1d..d8720153 100644 --- a/lib/jquery.ime/rules/si/si-singlish.js +++ b/lib/jquery.ime/rules/si/si-singlish.js @@ -11,7 +11,7 @@ license: 'GPLv3', version: '1.0', contextLength: 5, - maxKeyLength: 2, + maxKeyLength: 5, patterns: [ //['ඬ්හ්a', 'ඳ'], // nndha ['ඬ්h', 'ඳ්'], // nndh diff --git a/lib/jquery.ime/rules/yo/yo-alt.js b/lib/jquery.ime/rules/yo/yo-alt.js index 2e8c41b7..b2724727 100644 --- a/lib/jquery.ime/rules/yo/yo-alt.js +++ b/lib/jquery.ime/rules/yo/yo-alt.js @@ -16,7 +16,7 @@ // Combining grave tone mark ['\\\\', '\u0340'], // Combining acute tone mark - ["/", '\u0341'] + ['/', '\u0341'] ] };