Subscribed unsubscribe Subscribe Subscribe

枕を欹てて聴く

香炉峰の雪は簾を撥げて看る

相対パス解決

JavaScript

なんか適当に書いた. 全くbrowserに頼らず, すべて展開する. きっとbugがある. そうに違いない..
pathToURLは, A要素を使ったもの(browserに頼ってるもの). 比較用. (from AutoPagerize)

function pathToURL(path) {
    var link = document.createElement('a')
    link.href = path
    return link.href
}

var resolve_path = function(path, base){
  base || (base = document.location.href);
  var pathname = new pathName(base);
  pathname.parse(path);
  return pathname.absolute;
}

// need to be an absolute path.
var pathName = function(str){
  this.path = str;
  this.top = str.match(pathName.reg)[0];
  this.list = str.replace(this.top, "").split('/');
}
pathName.reg = /^https?:\/\/[^\/]+\//;
pathName.prototype = {
  get current(){
    var len = this.list.length;
    return len? this.list[len-1] : "";
  },
  get absolute(){
    return this.top + this.list.join('/');
  },
  child: function(name){
    this.list.push(name);
  },
  parent: function(){
    this.list.pop();
  },
  root: function(){
    this.list = [""];
  },
  parse: function(path){
    var list = path.split('/');
    var len = list.length - 1;
    list && list.forEach(function(phase, index){
      if(index == 0 && phase == '') return this.root();
      var p1 = phase[0];
      if(p1 == '.'){
        var p = phase[1];
        if(!p){
          return (!this.current == "" && this.child(""));
        } else if(p == '.'){
          this.parent();
          this.parent();
          if(!(index == len))this.child("");
        }
      } else {
        this.parent();
        this.child(phase);
        if(!(index == len))this.child("");
        return;
      }
    }, this);
  }
}
console.log(resolve_path('./hogehoge/foobar/', 'http://d.hatena.ne.jp/Constellation/'));
console.log(resolve_path('./hogehoge/foobar/', 'http://d.hatena.ne.jp/Constellation'));
console.log(resolve_path('hogehoge/foobar/', 'http://d.hatena.ne.jp/Constellation/'));
console.log(resolve_path('hogehoge/foobar/', 'http://d.hatena.ne.jp/Constellation'));
console.log(resolve_path('/hogehoge/.././foobar', 'http://d.hatena.ne.jp/Constellation/'));
console.log(resolve_path('/hogehoge/.././foobar', 'http://d.hatena.ne.jp/Constellation'));

JS1.8じゃない版

function pathToURL(path) {
    var link = document.createElement('a')
    link.href = path
    return link.href
}

var resolve_path = function(path, base){
  base || (base = document.location.href);
  var pathname = new pathName(base);
  pathname.parse(path);
  return pathname.absolute();
}

// need to be an absolute path.
var pathName = function(str){
  this.path = str;
  this.top = str.match(pathName.reg)[0];
  this.list = str.replace(this.top, "").split('/');
}
pathName.reg = /^https?:\/\/[^\/]+\//;
pathName.prototype = {
  current: function(){
    var len = this.list.length;
    return len? this.list[len-1] : "";
  },
  absolute: function(){
    return this.top + this.list.join('/');
  },
  child: function(name){
    this.list.push(name);
  },
  parent: function(){
    this.list.pop();
  },
  root: function(){
    this.list = [""];
  },
  parse: function(path){
    var list = path.split('/');
    var len = list.length - 1;
    list && list.forEach(function(phase, index){
      if(index == 0 && phase == '') return this.root();
      var p1 = phase[0];
      if(p1 == '.'){
        var p = phase[1];
        if(!p){
          return (!this.current() == "" && this.child(""));
        } else if(p == '.'){
          this.parent();
          this.parent();
          if(!(index == len))this.child("");
        }
      } else {
        this.parent();
        this.child(phase);
        if(!(index == len))this.child("");
        return;
      }
    }, this);
  }
}