ilib
Version:
iLib is a cross-engine library of internationalization (i18n) classes written in pure JS
2 lines • 6.34 kB
JavaScript
// !data collation
var ilib=require("../index.js"),Utils=require("./Utils.js"),JSUtils=require("./JSUtils.js"),Locale=require("./Locale.js"),INumber=require("./INumber.js"),isPunct=require("./isPunct.js"),NormString=require("./NormString.js"),CodePointSource=require("./CodePointSource.js"),ElementIterator=require("./ElementIterator.js"),GlyphString=require("./GlyphString.js"),Collator=function(options){var sync=!0,loadParams=void 0,useNative=!0;if(this.locale=new Locale(ilib.getLocale()),this.caseFirst="upper",this.sensitivity="variant",this.level=4,this.usage="sort",this.reverse=!1,this.numeric=!1,this.style="default",this.ignorePunctuation=!1,options){if(options.locale&&(this.locale="string"==typeof options.locale?new Locale(options.locale):options.locale),options.sensitivity)switch(options.sensitivity){case"primary":case"base":this.sensitivity="base",this.level=1;break;case"secondary":case"accent":this.sensitivity="accent",this.level=2;break;case"tertiary":case"case":this.sensitivity="case",this.level=3;break;case"quaternary":case"variant":this.sensitivity="variant",this.level=4}void 0!==options.upperFirst&&(this.caseFirst=options.upperFirst?"upper":"lower"),void 0!==options.ignorePunctuation&&(this.ignorePunctuation=options.ignorePunctuation),void 0!==options.sync&&(sync=!!options.sync),loadParams=options.loadParams,void 0!==options.useNative&&(useNative=options.useNative),"sort"!==options.usage&&"search"!==options.usage||(this.usage=options.usage),"boolean"==typeof options.reverse&&(this.reverse=options.reverse),"boolean"==typeof options.numeric&&(this.numeric=options.numeric),"string"==typeof options.style&&(this.style=options.style)}else options={sync:!0};"sort"===this.usage&&(this.level=4),useNative&&"undefined"!=typeof Intl&&Intl?(this.collator=new Intl.Collator(this.locale.getSpec(),{sensitivity:this.sensitivity,caseFirst:this.caseFirst,ignorePunctuation:this.ignorePunctuation,numeric:this.numeric,usage:this.usage}),options&&"function"==typeof options.onLoad&&options.onLoad(this)):Utils.loadData({object:"Collator",locale:this.locale,name:"collation.json",replace:!0,sync:sync,loadParams:loadParams,callback:ilib.bind(this,function(collation){collation=collation||ilib.data.collation,this._initCollation(collation),this.ignorePunctuation?isPunct._init(sync,loadParams,ilib.bind(this,function(){this._init(options)})):this._init(options)})})};Collator.prototype={_init:function(options){this.numeric?new INumber("1",{sync:options.sync,loadParams:options.loadParams,onLoad:function(n){"function"==typeof options.onLoad&&options.onLoad(this)}}):"function"==typeof options.onLoad&&options.onLoad(this)},_pack:function(arr,offset){var value=0;if(arr){"number"==typeof arr&&(arr=[arr]);for(var i=0;i<this.level;i++){var thisLevel=void 0!==arr[i]?arr[i]:0;0===i&&(thisLevel+=offset),0<i&&(value<<=this.collation.bits[i]),2===i&&"lower"===this.caseFirst?value|=1-thisLevel:value|=thisLevel}}return value},_packRule:function(rule,offset){if(ilib.isArray(rule[0])){for(var ret=[],i=0;i<rule.length;i++)ret.push(this._pack(rule[i],offset));return ret}return[this._pack(rule,offset)]},_addChars:function(str,offset){for(var it=new GlyphString(str).charIterator();it.hasNext();){if("'"===(c=it.next()))for(var c="",x="";it.hasNext()&&"'"!==x;)c+=x,x=it.next();this.lastMap++,this.map[c]=this._packRule([this.lastMap],offset)}},_addRules:function(rules,start){var p,r;for(r in rules.map)r&&(this.map[r]=this._packRule(rules.map[r],start),p=("number"==typeof rules.map[r][0]?rules.map[r]:rules.map[r][0])[0],this.lastMap=Math.max(p+start,this.lastMap));if(void 0!==rules.ranges)for(var i=0;i<rules.ranges.length;i++){var range=rules.ranges[i];if(this.lastMap=range.start,"string"==typeof range.chars)this._addChars(range.chars,start);else for(var k=0;k<range.chars.length;k++)this._addChars(range.chars[k],start)}},_initCollation:function(rules){for(var rule=this.style;"string"==typeof rule;)rule=rules[rule];if(!rule)for(rule="default";"string"==typeof rule;)rule=rules[rule];if(rule){if(this.collation=rule,this.map={},this.lastMap=-1,this.keysize=this.collation.keysize[this.level-1],this.defaultRule=rules.default,void 0!==this.collation.inherit)for(var col,i=0;i<this.collation.inherit.length;i++)"this"!==this.collation.inherit&&rules[rule="object"==typeof(col=this.collation.inherit[i])?col.name:col]&&this._addRules(rules[rule],col.start||this.lastMap+1);this._addRules(this.collation,this.lastMap+1)}else this.map={}},_basicCompare:function(left,right){var lelements,relements,diff,l=left instanceof NormString?left:new NormString(left),r=right instanceof NormString?right:new NormString(right);if(this.numeric){var lvalue=new INumber(left,{locale:this.locale}),rvalue=new INumber(right,{locale:this.locale});if(!isNaN(lvalue.valueOf())&&!isNaN(rvalue.valueOf())){if(diff=lvalue.valueOf()-rvalue.valueOf())return diff;l=new NormString(left.substring(lvalue.parsed.length)),r=new NormString(right.substring(rvalue.parsed.length))}}for(lelements=new ElementIterator(new CodePointSource(l,this.ignorePunctuation),this.map,this.keysize),relements=new ElementIterator(new CodePointSource(r,this.ignorePunctuation),this.map,this.keysize);lelements.hasNext()&&relements.hasNext();)if(diff=lelements.next()-relements.next())return diff;return lelements.hasNext()||relements.hasNext()?lelements.hasNext()?1:-1:0},compare:function(left,right){return this.collator?this.collator.compare(left,right):(left=this._basicCompare(left,right),this.reverse?-left:left)},getComparator:function(){return this.collator?this.collator.compare:ilib.bind(this,this.compare)},sortKey:function(str){if(!str)return"";if(this.collator)return str;if(this.numeric)return v=new INumber(str,{locale:this.locale}),v=isNaN(v.valueOf())?"":v.valueOf().toString(16),JSUtils.pad(v,16);for(var element,v="string"==typeof str?new NormString(str):str,ret="",lelements=new ElementIterator(new CodePointSource(v,this.ignorePunctuation),this.map,this.keysize);lelements.hasNext();)element=lelements.next(),this.reverse&&(element=(1<<this.keysize)-element),ret+=JSUtils.pad(element.toString(16),this.keysize/4);return ret}},Collator.getAvailableStyles=function(locale){return["standard"]},Collator.getAvailableScripts=function(){return["Latn"]},Collator.prototype.getDefaultCollatorStyle=function(){return this.defaultRule},module.exports=Collator;