work in progress [might break]

This commit is contained in:
Leon van Kammen 2024-03-29 17:36:48 +00:00
parent 885c41f9b3
commit 36e48a521d
4 changed files with 342 additions and 6 deletions

View File

@ -1,5 +1,6 @@
import xrfragment.Filter;
import xrfragment.URI;
import xrfragment.URL;
import xrfragment.XRF;
class Spec {
@ -44,6 +45,8 @@ class Test {
if( item.expect.fn == "testPropertyAssign" ) valid = res.exists(item.expect.input) && item.expect.out == res.get(item.expect.input).is( XRF.PROP_BIND) ;
if( item.expect.fn == "testBrowserOverride" ) valid = item.expect.out == (URI.parse(item.data,XRF.NAVIGATOR)).exists(item.expect.input);
if( item.expect.fn == "testEmbedOverride" ) valid = item.expect.out == (URI.parse(item.data,XRF.METADATA)).exists(item.expect.input);
if( item.expect.fn == "testURL" ) testURL( item.data, item.expect.input, item.expect.out );
if( item.expect.fn == "equal.string" ) valid = res.get(item.expect.input) && item.expect.out == res.get(item.expect.input).string;
if( item.expect.fn == "equal.x" ) valid = equalX(res,item);
if( item.expect.fn == "equal.xy" ) valid = equalXY(res,item);
@ -53,6 +56,7 @@ class Test {
if( item.expect.fn == "equal.mediafragmentS") valid = equalMediaFragment(res,item,"s");
if( item.expect.fn == "testFilterRoot" ) valid = res.exists(item.expect.input[0]) && res.get(item.expect.input[0]).filter.get().root == item.expect.out;
if( item.expect.fn == "testFilterDeep" ) valid = res.exists(item.expect.input[0]) && res.get(item.expect.input[0]).filter.get().deep == item.expect.out;
var ok:String = valid ? "[ ] " : "[ ] ";
trace( ok + item.fn + ": '" + item.data + "'" + (item.label ? " (" + (item.label?item.label:item.expect.fn) +")" : ""));
if( !valid ) errors += 1;
@ -79,11 +83,11 @@ class Test {
else return res.get( key ).floats[ Std.parseInt(item.expect.input) ] == Std.parseFloat(item.expect.out);
}
static public function testUrl():Void {
var Uri = xrfragment.URI;
var url:String = "http://foo.com?foo=1#bar=flop&a=1,2&b=c|d|1,2,3";
trace(url);
trace( Uri.parse(url,0) );
static public function testURL( url:String, attr:String, output:String): Bool {
var URL = xrfragment.URL;
var url = URL.parse(url,false);
if( attr == 'scheme' && url.scheme == output ) return true;
return false;
}
static public function testFilter():Void {

View File

@ -2,5 +2,6 @@
{"fn":"url","data":"http://foo.com?foo=1#mypredefinedview", "expect":{ "fn":"testPredefinedView", "input":"mypredefinedview","out":true},"label":"test predefined view executed"},
{"fn":"url","data":"http://foo.com?foo=1#mypredefinedview&another", "expect":{ "fn":"testPredefinedView", "input":"another","out":true},"label":"test predefined view executed (multiple)"},
{"fn":"url","data":"http://foo.com?foo=1#mypredefinedview&another", "expect":{ "fn":"testPredefinedView", "input":"mypredefinedview","out":true},"label":"test predefined view executed (multiple)"},
{"fn":"url","data":"http://foo.com?foo=1#mycustom=foo", "expect":{ "fn":"testParsed", "input":"mycustom","out":true},"label":"test custom property"}
{"fn":"url","data":"http://foo.com?foo=1#mycustom=foo", "expect":{ "fn":"testParsed", "input":"mycustom","out":true},"label":"test custom property"},
{"fn":"url","data":"http://foo.com?foo=1#mycustom=foo", "expect":{ "fn":"testURL", "input":"scheme","out":"https://"},"label":"test URL scheme"}
]

View File

@ -26,6 +26,9 @@ import xrfragment.XRF;
@:expose // <- makes the class reachable from plain JavaScript
@:keep // <- avoids accidental removal by dead code elimination
class URI {
public static var fragment:haxe.DynamicAccess<Dynamic>;
@:keep
public static function parse(url:String,filter:Int):haxe.DynamicAccess<Dynamic> {
var store:haxe.DynamicAccess<Dynamic> = {}; // 1. store key/values into a associative array or dynamic object

328
src/xrfragment/URL.hx Normal file
View File

@ -0,0 +1,328 @@
package xrfragment;
import xrfragment.URI;
/*
* Cocktail, HTML rendering engine
* http://haxe.org/com/libs/cocktail
*
* Copyright (c) Silex Labs
* Cocktail is available under the MIT license
* http://www.silexlabs.org/labs/cocktail-licensing/
* https://github.com/haxecocktail/cocktail-url/blob/master/cocktail/url/URL.hx
*/
/**
* Parse and serialize an URL.
*
* note : parts of the implementation originate from
* here : http://haxe.org/doc/snip/uri_parser,
* some part of the URL have been renamed to match
* w3c spec
*
* @author Yannick Dominguez
*/
class URL
{
/**
* URL parts names
*/
private static var _parts : Array<String> = ["source", "scheme", "authority", "userInfo", "user",
"password","host","port","relative","path","directory","file","query","fragment"];
/**
* URL parts
*/
public var url : String;
public var source : String;
public var scheme : String;
public var authority : String;
public var userInfo : String;
public var user : String;
public var password : String;
public var host : String;
public var port : String;
public var relative : String;
public var path : String;
public var directory : String;
public var file : String;
public var query : String;
public var browserMode: Bool;
public var fragment : String;
public var hash : haxe.DynamicAccess<Dynamic>;
/**
* class constructor
*/
public function new( )
{
}
/**
* Parse a string url and return a typed
* object from it.
*
* note : implementation originate from here :
* http://haxe.org/doc/snip/uri_parser
*/
public static function parse(stringUrl:String, browserMode:Bool ):URL
{
// The almighty regexp (courtesy of http://blog.stevenlevithan.com/archives/parseuri)
var r : EReg = ~/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
// Match the regexp to the url
r.match(stringUrl);
var url:URL = new URL();
url.browserMode = browserMode;
// Use reflection to set each part
for (i in 0..._parts.length)
{
Reflect.setField(url, _parts[i], r.matched(i));
}
//hack for relative url with only a file
if (isRelative(url) == true)
{
if (url.directory == null && url.host != null)
{
url.file = url.host;
if( !url.browserMode ) url.host = null;
}
}
if( url.fragment.length > 0 ){
url.hash = xrfragment.URI.parse( url.fragment, 0 );
}else url.hash = {};
return url;
}
/**
* Serialize an URL object into an
* URL string
*/
public static function toString(url:URL):String
{
var result:String = "";
if (url.scheme != null)
{
result += url.scheme + "://";
}
if (url.user != null)
{
result += url.user + ":";
}
if (url.password != null)
{
result += url.password + "@";
}
if (url.host != null)
{
result += url.host;
}
if (url.port != null)
{
result += ":" + url.port;
}
if (url.directory != null)
{
result += url.directory;
}
if (url.file != null)
{
result += url.file;
}
if (url.query != null)
{
result += "?" + url.query;
}
if (url.fragment != null)
{
result += "#" + url.fragment;
}
return result;
}
/**
* takes 2 urls and return a new url which is the result
* of appending the second url to the first.
*
* if the first url points to a file, the file is removed
* and the appended url is added after the last directory
*
* only the query string and fragment of the appended url are used
*/
public static function appendURL(url:URL, appendedURL:URL):URL
{
if (isRelative(url) == true)
{
return appendToRelativeURL(url, appendedURL);
}
else
{
return appendToAbsoluteURL(url, appendedURL);
}
}
/**
* return wether the url is relative (true)
* or absolute (false)
*/
public static function isRelative(url:URL):Bool
{
return url.scheme == null;
}
/**
* append the appended url to a relative url
*/
private static function appendToRelativeURL(url:URL, appendedURL:URL):URL
{
//when relative url parsed, if it contains only a file (ex : "style.css")
//then it will store it in the host attribute. So if the url has no directory
//then only the appended url content is returned, as this method replace the file
//part of the base url anyway
if (url.directory == null || url.host == null)
{
return cloneURL(appendedURL, url.browserMode);
}
var resultURL:URL = new URL();
resultURL.host = url.host;
resultURL.directory = url.directory;
if (appendedURL.host != null)
{
resultURL.directory += appendedURL.host;
}
if (appendedURL.directory != null)
{
var directory = appendedURL.directory;
if (appendedURL.host == null)
{
//remove the initial '/' char if no host, as already present
//in base url
resultURL.directory += directory.substr(1);
}
else
{
resultURL.directory += directory;
}
}
if (appendedURL.file != null)
{
resultURL.file = appendedURL.file;
}
resultURL.path = resultURL.directory + resultURL.file;
if (appendedURL.query != null)
{
resultURL.query = appendedURL.query;
}
if (appendedURL.fragment != null)
{
resultURL.fragment = appendedURL.fragment;
}
return resultURL;
}
/**
* append the appended url to an absolute url
*/
private static function appendToAbsoluteURL(url:URL, appendedURL:URL):URL
{
var resultURL:URL = new URL();
if (url.scheme != null)
{
resultURL.scheme = url.scheme;
}
if (url.host != null)
{
resultURL.host = url.host;
}
var directory:String = "";
if (url.directory != null)
{
directory = url.directory;
}
if (appendedURL.host != null)
{
appendedURL.directory += appendedURL.host;
}
if (appendedURL.directory != null)
{
directory += appendedURL.directory;
}
resultURL.directory = directory;
if (appendedURL.file != null)
{
resultURL.file = appendedURL.file;
}
resultURL.path = resultURL.directory + resultURL.file;
if (appendedURL.query != null)
{
resultURL.query = appendedURL.query;
}
if (appendedURL.fragment != null)
{
resultURL.fragment = appendedURL.fragment;
}
return resultURL;
}
/**
* clone the provided url
*/
private static function cloneURL(url:URL, browserMode:Bool):URL
{
var clonedURL:URL = new URL();
clonedURL.url = url.url;
clonedURL.source = url.source;
clonedURL.scheme = url.scheme;
clonedURL.authority = url.authority;
clonedURL.userInfo = url.userInfo;
clonedURL.password = url.password;
clonedURL.host = url.host;
clonedURL.port = url.port;
clonedURL.relative = url.relative;
clonedURL.path = url.path;
clonedURL.directory = url.directory;
clonedURL.file = url.file;
clonedURL.query = url.query;
clonedURL.browserMode = browserMode;
clonedURL.fragment = url.fragment;
return clonedURL;
}
}