xrfragment-haxe/src/xrfragment/Query.hx

131 lines
4.3 KiB
Haxe
Raw Normal View History

2023-03-09 19:58:08 +01:00
package xrfragment;
@:expose // <- makes the class reachable from plain JavaScript
@:keep // <- avoids accidental removal by dead code elimination
2023-03-09 22:32:28 +01:00
//return untyped __js__("window.location.search");
2023-03-09 19:58:08 +01:00
#if js
var ok:Bool = js.Syntax.code('
// haxe workarounds
Array.prototype.contains = Array.prototype.includes
if (typeof Array.prototype.remove !== "function") {
Array.prototype.remove = function (item) {
const oldLength = this.length
let newLength = 0
for (let i = 0; i < oldLength; i++) {
const entry = this[i]
if (entry === item) {
let newLength = i++
while (i !== this.length) {
const entry = this[i]
if (entry !== item) this[newLength++] = entry
i++
}
this.length = newLength
for (let i = newLength; i < oldLength; i++) delete this[i]
return true
}
}
return false
}
}
');
#end
class Query {
private var str:String = "";
2023-03-21 17:57:54 +01:00
private var q:haxe.DynamicAccess<Dynamic> = {};
private var isProp:EReg = ~/^.*:[><=!]?/;
private var isExclude:EReg = ~/^-/;
2023-03-09 19:58:08 +01:00
public function new(str:String){
if( str != null ) this.parse(str);
}
public function toObject() : Dynamic {
return this.q;
}
2023-03-21 17:57:54 +01:00
public function expandAliases(token:String) : String {
// expand '.foo' to 'class:foo'
var classAlias = ~/^(-)?\./;
return classAlias.match(token) ? StringTools.replace(token,".","class:") : token;
2023-03-09 19:58:08 +01:00
}
2023-03-21 17:57:54 +01:00
@:keep
2023-03-09 19:58:08 +01:00
public function parse(str:String,recurse:Bool = false) : Dynamic {
var token = str.split(" ");
var q:haxe.DynamicAccess<Dynamic> = {};
2023-03-21 17:57:54 +01:00
function process(str,prefix = ""){
str = StringTools.trim(str);
var value:haxe.DynamicAccess<Dynamic> = {};
2023-03-09 19:58:08 +01:00
if( isProp.match(str) ){
2023-03-21 17:57:54 +01:00
var oper:String = "";
if( str.indexOf("*") != -1 ) oper = "*";
if( str.indexOf(">") != -1 ) oper = ">";
if( str.indexOf("<") != -1 ) oper = "<";
if( str.indexOf("!=") != -1 ) oper = "!=";
if( str.indexOf(">=") != -1 ) oper = ">=";
if( str.indexOf("<=") != -1 ) oper = "<=";
var k:String = str.split(":")[0];
var v:String = str.split(":")[1];
if( q.get(prefix+k) ) value = q.get(prefix+k);
if( oper.length > 0 ){
value[ oper ] = Std.parseFloat( v.substr(oper.length) );
q.set( k, value );
2023-03-09 19:58:08 +01:00
}else{
2023-03-21 17:57:54 +01:00
value[ prefix+ (isExclude.match(k) ? k.substr(1) : k) ] = isExclude.match(k) == false;
q.set(v,value);
2023-03-09 19:58:08 +01:00
}
return;
2023-03-21 17:57:54 +01:00
}else{ // id
value[ "id" ] = isExclude.match(str) ? false: true;
q.set( (isExclude.match(str) ? str.substr(1) : str ) ,value );
2023-03-09 19:58:08 +01:00
}
}
2023-03-21 17:57:54 +01:00
for( i in 0...token.length ) process( expandAliases(token[i]) );
this.q = q;
2023-03-09 19:58:08 +01:00
return this.q;
}
2023-03-09 22:32:28 +01:00
@:keep
2023-03-21 17:57:54 +01:00
public function test( property:String, ?value:Dynamic ):Bool{
var conds:Int = 0;
var fails:Int = 0;
var qualify:Int = 0;
var testprop = function(expr:Bool) : Bool {
conds+=1;
fails+= expr ? 0 : 1;
return expr;
2023-03-09 19:58:08 +01:00
}
2023-03-21 17:57:54 +01:00
// class or id
if( q[value] != null ){
var v:haxe.DynamicAccess<Dynamic> = q[value];
if( v.get(property) != null ) return v.get(property);
}
// conditional props
for ( k in Reflect.fields(q) ){
var qval:Dynamic = Reflect.field(q,k);
if( Std.isOfType(value, String) ) continue;
if( Reflect.field(qval,'=') != null && testprop( value == Reflect.field(qval,'=') ) ) qualify += 1;
if( Reflect.field(qval,'*') != null && testprop( value != null ) ) qualify += 1;
if( Reflect.field(qval,'>') != null && testprop( value > Std.parseFloat(Reflect.field(qval,'>' )) ) ) qualify += 1;
if( Reflect.field(qval,'<') != null && testprop( value < Std.parseFloat(Reflect.field(qval,'<' )) ) ) qualify += 1;
if( Reflect.field(qval,'>=') != null && testprop( value >= Std.parseFloat(Reflect.field(qval,'>=')) ) ) qualify += 1;
if( Reflect.field(qval,'<=') != null && testprop( value >= Std.parseFloat(Reflect.field(qval,'<=')) ) ) qualify += 1;
if( Reflect.field(qval,'!=') != null && testprop( value != Std.parseFloat(Reflect.field(qval,'!=')) ) ) qualify += 1;
2023-03-09 19:58:08 +01:00
}
2023-03-21 17:57:54 +01:00
return qualify > 0;
2023-03-09 19:58:08 +01:00
}
}