@scion-scxml/scxml
Version:
An implementation of SCXML in JavaScript.
87 lines (80 loc) • 3.58 kB
JavaScript
const urlM = require('url'),
path = require('path');
/**
* Resolver algorithm:
*
* doc loaded from url over http (http protocol)
* invoke/@src has http protocol: different domain. different path.
* invoke/@src has absolute file protocol: same domain. change the path.
* invoke/@src has relative file protocol: same domain. resolve relative to the path.
* doc loaded from filesystem path (file protocol)
* invoke/@src has http protocol: fine. load the session over http.
* invoke/@src has absolute file protocol: fine. load file from filesystem. absolute path.
* invoke/@src has relative file protocol: fine. load file from filesystem. resolve relative path
*/
function resolveUri(relativeToUrl, resourceUrl){
const resourceUrlObj = urlM.parse(resourceUrl),
relativeToUrlObj = urlM.parse(relativeToUrl);
switch(relativeToUrlObj.protocol){
// doc loaded from url over http (http protocol)
case 'http:':
case 'https:':
switch(resourceUrlObj.protocol){
case 'http:':
case 'https:':
// invoke/@src has http protocol: different domain. different path.
return resourceUrl;
case 'file:':
default:
if(path.isAbsolute(resourceUrlObj.pathname)){
// invoke/@src has absolute file protocol: same domain. change the path.
relativeToUrlObj.pathname = resourceUrlObj.pathname;
return urlM.format(relativeToUrlObj);
} else {
// invoke/@src has relative file protocol: same domain. resolve relative to the path.
// resolve relative path
return convertRelativePath(relativeToUrlObj, resourceUrlObj)
}
}
// doc loaded from filesystem path (file protocol)
case 'file:':
default:
switch(resourceUrlObj.protocol){
case 'http:':
case 'https:':
// invoke/@src has http protocol: fine. load the session over http.
return resourceUrl;
case 'file:':
default:
if(path.isAbsolute(resourceUrlObj.pathname)){
// invoke/@src has absolute file protocol: fine. load file from filesystem. absolute path.
relativeToUrlObj.protocol = 'file:';
relativeToUrlObj.pathname = resourceUrlObj.pathname;
return urlM.format(relativeToUrlObj);
} else {
// invoke/@src has relative file protocol: fine. load file from filesystem. resolve relative path
relativeToUrlObj.protocol = 'file:';
return convertRelativePath(relativeToUrlObj, resourceUrlObj)
}
}
}
}
function convertRelativePath(relativeToUrlObj, resourceUrlObj){
let newPath;
if(path.extname(relativeToUrlObj.pathname)){
//assume he is a file
newPath = path.join(path.dirname(relativeToUrlObj.pathname), resourceUrlObj.pathname);
}else{
//assume he is a directory
newPath = path.join(relativeToUrlObj.pathname, resourceUrlObj.pathname);
}
relativeToUrlObj.pathname = newPath;
return urlM.format(relativeToUrlObj);
}
//console.log(resolveUri('http://foo.com/bar','bat.scxml'));
//console.log(resolveUri('http://foo.com/bar/bat.scxml','bif.scxml'));
//console.log(resolveUri('http://foo.com/bar/bat.scxml','bif.js'));
//console.log(resolveUri('file:/foo/bar/','bat.scxml'));
//console.log(resolveUri('file:/foo/bar/bat.scxml','bif.js'));
//console.log(resolveUri('file:/foo/bar/bat.scxml','bif.scxml'));
module.exports = resolveUri;