JavaScript를 사용하여 상대 경로를 절대 경로로 변환
다음과 같은 URL을 제공하는 함수가 있습니다.
./some.css
./extra/some.css
../../lib/slider/slider.css
항상 상대 경로입니다.
http://site.com/stats/2012/
이러한 상대 경로를 실제 경로로 어떻게 변환해야하는지 잘 모르겠습니다. 과 같이 페이지의 현재 경로를 알고 있다고 생각해 봅시다 .
우리는 다음과 같은 것을 얻어야합니다.
./some.css => http://site.com/stats/2012/some.css
./extra/some.css => http://site.com/stats/2012/extra/some.css
../../lib/slider/slider.css => http://site.com/lib/slider/slider.css
jQuery는없고 바닐라 자바 스크립트 만 있습니다.
이렇게해야합니다.
function absolute(base, relative) {
var stack = base.split("/"),
parts = relative.split("/");
stack.pop(); // remove current file name (or empty string)
// (omit if "base" is the current folder without trailing slash)
for (var i=0; i<parts.length; i++) {
if (parts[i] == ".")
continue;
if (parts[i] == "..")
stack.pop();
else
stack.push(parts[i]);
}
return stack.join("/");
}
URL API를 사용하는 가장 간단하고 효율적이며 올바른 방법 입니다.
new URL("http://www.stackoverflow.com?q=hello").href;
//=> http://www.stackoverflow.com/?q=hello"
new URL("mypath","http://www.stackoverflow.com").href;
//=> "http://www.stackoverflow.com/mypath"
new URL("../mypath","http://www.stackoverflow.com/search").href
//=> "http://www.stackoverflow.com/mypath"
new URL("../mypath", window.location.href).href
//=> "https://stackoverflow.com/questions/mypath"
성능면에서이 솔루션은 문자열 조작을 사용하는 것과 동등하며 a
태그 를 만드는 것보다 두 배 빠릅니다 .
자바 스크립트가 해줄 것입니다. 함수를 만들 필요가 없습니다.
var link = document.createElement("a");
link.href = "../../lib/slider/slider.css";
alert(link.protocol+"//"+link.host+link.pathname+link.search+link.hash);
// Output will be "http://www.yoursite.com/lib/slider/slider.css"
하지만 함수로 필요한 경우 :
var absolutePath = function(href) {
var link = document.createElement("a");
link.href = href;
return (link.protocol+"//"+link.host+link.pathname+link.search+link.hash);
}
업데이트 : 전체 절대 경로가 필요한 경우 더 간단한 버전 :
var absolutePath = function(href) {
var link = document.createElement("a");
link.href = href;
return link.href;
}
MDN의 이것은 깨지지 않습니다!
/*\
|*|
|*| :: translate relative paths to absolute paths ::
|*|
|*| https://developer.mozilla.org/en-US/docs/Web/API/document.cookie
|*|
|*| The following code is released under the GNU Public License, version 3 or later.
|*| http://www.gnu.org/licenses/gpl-3.0-standalone.html
|*|
\*/
function relPathToAbs (sRelPath) {
var nUpLn, sDir = "", sPath = location.pathname.replace(/[^\/]*$/, sRelPath.replace(/(\/|^)(?:\.?\/+)+/g, "$1"));
for (var nEnd, nStart = 0; nEnd = sPath.indexOf("/../", nStart), nEnd > -1; nStart = nEnd + nUpLn) {
nUpLn = /^\/(?:\.\.\/)*/.exec(sPath.slice(nEnd))[0].length;
sDir = (sDir + sPath.substring(nStart, nEnd)).replace(new RegExp("(?:\\\/+[^\\\/]*){0," + ((nUpLn - 1) / 3) + "}$"), "/");
}
return sDir + sPath.substr(nStart);
}
샘플 사용법 :
/* Let us be in /en-US/docs/Web/API/document.cookie */
alert(location.pathname);
// displays: /en-US/docs/Web/API/document.cookie
alert(relPathToAbs("./"));
// displays: /en-US/docs/Web/API/
alert(relPathToAbs("../Guide/API/DOM/Storage"));
// displays: /en-US/docs/Web/Guide/API/DOM/Storage
alert(relPathToAbs("../../Firefox"));
// displays: /en-US/docs/Firefox
alert(relPathToAbs("../Guide/././API/../../../Firefox"));
// displays: /en-US/docs/Firefox
스크립트를 실행하는 페이지가 아닌 브라우저의 사용자 지정 웹 페이지에서 링크에 대해 상대적-절대적 변환을 수행하려는 경우 @Bergi에서 제안한 기능의보다 향상된 버전을 사용할 수 있습니다.
var resolveURL=function resolve(url, base){
if('string'!==typeof url || !url){
return null; // wrong or empty url
}
else if(url.match(/^[a-z]+\:\/\//i)){
return url; // url is absolute already
}
else if(url.match(/^\/\//)){
return 'http:'+url; // url is absolute already
}
else if(url.match(/^[a-z]+\:/i)){
return url; // data URI, mailto:, tel:, etc.
}
else if('string'!==typeof base){
var a=document.createElement('a');
a.href=url; // try to resolve url without base
if(!a.pathname){
return null; // url not valid
}
return 'http://'+url;
}
else{
base=resolve(base); // check base
if(base===null){
return null; // wrong base
}
}
var a=document.createElement('a');
a.href=base;
if(url[0]==='/'){
base=[]; // rooted path
}
else{
base=a.pathname.split('/'); // relative path
base.pop();
}
url=url.split('/');
for(var i=0; i<url.length; ++i){
if(url[i]==='.'){ // current directory
continue;
}
if(url[i]==='..'){ // parent directory
if('undefined'===typeof base.pop() || base.length===0){
return null; // wrong url accessing non-existing parent directories
}
}
else{ // child directory
base.push(url[i]);
}
}
return a.protocol+'//'+a.hostname+base.join('/');
}
null
뭔가 잘못되면 반환 됩니다.
용법:
resolveURL('./some.css', 'http://example.com/stats/2012/');
// returns http://example.com/stats/2012/some.css
resolveURL('extra/some.css', 'http://example.com/stats/2012/');
// returns http://example.com/stats/2012/extra/some.css
resolveURL('../../lib/slider/slider.css', 'http://example.com/stats/2012/');
// returns http://example.com/lib/slider/slider.css
resolveURL('/rootFolder/some.css', 'https://example.com/stats/2012/');
// returns https://example.com/rootFolder/some.css
resolveURL('localhost');
// returns http://localhost
resolveURL('../non_existing_file', 'example.com')
// returns null
function canonicalize(url) {
var div = document.createElement('div');
div.innerHTML = "<a></a>";
div.firstChild.href = url; // Ensures that the href is properly escaped
div.innerHTML = div.innerHTML; // Run the current innerHTML back through the parser
return div.firstChild.href;
}
이것은 다른 솔루션과 달리 IE6에서도 작동 합니다 (상대적인 URL에서 절대 URL 얻기 참조 ). (IE6 문제 )
href 솔루션은 문서가로드 된 후에 만 작동합니다 (적어도 IE11에서는). 이것은 나를 위해 일했습니다.
link = link || document.createElement("a");
link.href = window.location.href + "/../" + href;
return link.href;
제안되고 승인 된 솔루션은 서버 상대 URL을 지원하지 않으며 절대 URL에서 작동하지 않습니다. 내 친척이 / sites / folder1이면 예를 들어 작동하지 않습니다.
Here is another function that supports full, server relative or relative URLs as well as ../ for one level up. It is not perfect but covers a lot of options. Use this when your base URL is not the current page URL, otherwise there are better alternatives.
function relativeToAbsolute(base, relative) {
//make sure base ends with /
if (base[base.length - 1] != '/')
base += '/';
//base: https://server/relative/subfolder/
//url: https://server
let url = base.substr(0, base.indexOf('/', base.indexOf('//') + 2));
//baseServerRelative: /relative/subfolder/
let baseServerRelative = base.substr(base.indexOf('/', base.indexOf('//') + 2));
if (relative.indexOf('/') === 0)//relative is server relative
url += relative;
else if (relative.indexOf("://") > 0)//relative is a full url, ignore base.
url = relative;
else {
while (relative.indexOf('../') === 0) {
//remove ../ from relative
relative = relative.substring(3);
//remove one part from baseServerRelative. /relative/subfolder/ -> /relative/
if (baseServerRelative !== '/') {
let lastPartIndex = baseServerRelative.lastIndexOf('/', baseServerRelative.length - 2);
baseServerRelative = baseServerRelative.substring(0, lastPartIndex + 1);
}
}
url += baseServerRelative + relative;//relative is a relative to base.
}
return url;
}
Hope this helps. It was really frustrating not to have this basic utility available in JavaScript.
I had to add a fix to the accepted solution because we can have slashes after # in our angularjs navigation.
function getAbsoluteUrl(base, relative) {
// remove everything after #
var hashPosition = base.indexOf('#');
if (hashPosition > 0){
base = base.slice(0, hashPosition);
}
// the rest of the function is taken from http://stackoverflow.com/a/14780463
// http://stackoverflow.com/a/25833886 - this doesn't work in cordova
// http://stackoverflow.com/a/14781678 - this doesn't work in cordova
var stack = base.split("/"),
parts = relative.split("/");
stack.pop(); // remove current file name (or empty string)
// (omit if "base" is the current folder without trailing slash)
for (var i=0; i<parts.length; i++) {
if (parts[i] == ".")
continue;
if (parts[i] == "..")
stack.pop();
else
stack.push(parts[i]);
}
return stack.join("/");
}
I found a very simple solution to do this while still supporting IE 10 (IE doesn't support the URL-API) by using the History API (IE 10 or higher). This solution works without any string manipulation.
function resolveUrl(relativePath) {
var originalUrl = document.location.href;
history.replaceState(history.state, '', relativePath);
var resolvedUrl = document.location.href;
history.replaceState(history.state, '', originalUrl);
return resolvedUrl;
}
history.replaceState()
won't trigger browser navigation, but will still modify document.location
and supports relative aswell as absolute paths.
The one drawback of this solution is that if you are already using the History-API and have set a custom state with a title, the current state's title is lost.
This will work. but only when you open a page with it's file name. it will not work well when you open a link like this stackoverflow.com/page
. it will work with stackoverflow.com/page/index.php
function reltoabs(link){
let absLink = location.href.split("/");
let relLink = link;
let slashesNum = link.match(/[.]{2}\//g) ? link.match(/[.]{2}\//g).length : 0;
for(let i = 0; i < slashesNum + 1; i++){
relLink = relLink.replace("../", "");
absLink.pop();
}
absLink = absLink.join("/");
absLink += "/" + relLink;
return absLink;
}
ReferenceURL : https://stackoverflow.com/questions/14780350/convert-relative-path-to-absolute-using-javascript
'Programing' 카테고리의 다른 글
장고 필터에서 AND를 어떻게 사용합니까? (0) | 2021.01.05 |
---|---|
새로운 X86_64 프로세서 레지스터의 이름은 무엇입니까? (0) | 2021.01.05 |
Python에서 함수 인수를 확인하는 가장 좋은 방법 (0) | 2021.01.05 |
hastable 키 열거를 반복하면 NoSuchElementException 오류가 발생합니다. (0) | 2021.01.05 |
C # 영역과 같은 CSS의 영역? (0) | 2021.01.05 |