Converting an absolute path to a relative path - javascript

Working in Node I need to convert my request path into a relative path so I can drop it into some templates that have a different folder structure.
For example, if I start with the path "/foo/bar" and want the relative path to "/foo", it would be "..", and for "/foo/bar/baz" it would be "../..".
I wrote a pair of functions to do this:
function splitPath(path) {
return path.split('/').map(dots).slice(2).join('/');
}
function dots() {
return '..';
}
Not sure if this is the best approach or if it's possible to do it with a regular expression in String.replace somehow?
edit
I should point out this is so I can render everything as static HTML, zip up the whole project, and send it to someone who doesn't have access to a web server. See my first comment.

If I understand you question correct you can use path.relative(from, to)
Documentation
Example:
var path = require('path');
console.log(path.relative('/foo/bar/baz', '/foo'));

Node.js have native method for this purposes: path.relative(from, to).

This might need some tuning but it should work:
function getPathRelation(position, basePath, input) {
var basePathR = basePath.split("/");
var inputR = input.split("/");
var output = "";
for(c=0; c < inputR.length; c++) {
if(c < position) continue;
if(basePathR.length <= c) output = "../" + output;
if(inputR[c] == basePathR[c]) output += inputR[c] + "/";
}
return output;
}
var basePath ="/foo"
var position = 2;
var input = "/foo";
console.log(getPathRelation(position,basePath,input));
var input = "/foo/bar";
console.log(getPathRelation(position,basePath,input));
var input = "/foo/bar/baz";
console.log(getPathRelation(position,basePath,input));
Result:
(an empty string)
../
../../

Related

Modify specific text with value

I Read a text document with readFile method ,and I got the current string.
I need to modify some specific fields inside and save the file and keep the original format
in the read file I got the following "string"
\r\nAPP_HOST=mo-d6fa.corp\r\nAPP_PORT=5000\r\nINS_PORT=50100\r\nPORT=66000\r\n
and I need to change just the number for properties
PORT=4000
APP_PORT =4000
I use the fs.readFile(filePath, 'utf8') and the response is this file
You can modify it turning into an object, setting values and then get back to string using Array.prototype.reduce:
var rawValues = "\r\nAPP_HOST=mo-d6fa.corp\r\nAPP_PORT=5000\r\nINS_PORT=50100\r\nPORT=66000\r\n";
// #1 You need to turn raw string into an array using String.prototype.split
// #2 It's time to reduce the array into an object to be able to access
// config values as a key-value pair store
var values = rawValues.trim().split("\r\n").reduce(
function(result, next, index, sourceArray) {
var keyValuePair = sourceArray[index].split("=");
result[keyValuePair[0]] = keyValuePair[1];
return result;
}, {});
// Now you can alter config values like a dictionary:
values["PORT"] = "9995";
values["APP_PORT"] = "9999";
// or using dot syntax if possible settings have valid JavaScript
// variable names...
values.PORT = "9995";
values.APP_PORT = "9999";
// ...more settings...
// #3 Once you've edited your settings, it's time to reduce each property
// as part of a new raw string containing all configurations.
rawValues = Object.keys(values).reduce(function(previousValue, property, index) {
previousValue += property + "=" + values[property] + "\r\n";
return previousValue;
}, "");
// Now PORT and APP_PORT contain their new values...
document.getElementById("rawResult").textContent = JSON.stringify(rawValues);
<div id="rawResult"></div>
Suggestion
IMHO, if you can turn your configuration into a valid JSON life can be even easier.
For example, your raw config can be { "APP_HOST": "mo-d6fa.corp", "APP_PORT": 5000, "INS_PORT": 50100, "PORT": 66000 }. See how this simplifies your problem:
var rawConfig = '{ "APP_HOST": "mo-d6fa.corp", "APP_PORT": 5000, "INS_PORT": 50100, "PORT": 66000 }';
var config = JSON.parse(rawConfig);
config["APP_PORT"] = 6000;
config["PORT"] = 7000;
rawConfig = JSON.stringify(config);
document.getElementById("result").textContent = rawConfig;
<div id="result"></div>
Instead of rolling your own configuration parser, you can just use JSON which is a well-known pattern and it has a built-in, out-of-the-box parser as part of every Web browser in the earth, NodeJS and even non-JavaScript platforms like .NET, Java...
The regexes for both these will be pretty similar. Here's a stab:
var portRegex = /\nPORT=\d+/g;
var appPortRegex = /\nAPP_PORT=\d+/g;
var fileStr = fs.readFile(filePath, 'utf8');
fileStr = fileStr
.replace(portRegex, '\nPORT=' + 4000)
.replace(appPortRegex, '\nAPP_PORT=' + 4000);
The problem with finding the exact PORT entry can be resolved by matching it at the beginning of a line only with /m modifier (in a multiline mode) that forces ^ to match at the beginning of a line:
/^(PORT\s*=\s*)\d+/m
/^(APP_PORT\s*=\s*)\d+/m
var re = /^(APP_PORT\s*=\s*)\d+/m;
var re2 = /^(PORT\s*=\s*)\d+/m;
var str = 'APP_HOST=mo-d6fa.corp\nAPP_PORT=5000\nINS_PORT=50100\nPORT=66000';
var result = str.replace(re, '$1NEWVALUE').replace(re2, '$1ANOTHERVALUE');
document.write(result);

How can I remove the parent folders in an array of paths?

I am using the following code in order to retrieve sub folder names from the path declared. This works fine but how do I then remove the path name so that the array is a list of just folder names?
var myPath = Folder ("Z:/My File System/Me/Work Files/Design");
var folders = getFolders (myPath);
function getFolders(sourceFolder) {
var folderArray = new Array();
var sFolders = sourceFolder.getFiles ();
var len = sFolders.length;
for (var i = 0; i < len; i++) {
var sFolder = sFolders[i];
if (sFolder instanceof Folder) {
folderArray.push(sFolder);
}
}
return folderArray;
}
Instead of returning:
Z:/My File System/Me/Work Files/Design/One
Z:/My File System/Me/Work Files/Design/Two
Z:/My File System/Me/Work Files/Design/Three
Z:/My File System/Me/Work Files/Design/Four
I need:
One
Two
Three
Four
You could implement something like this (assuming you can modify the Folder prototype, and it stores the path as this.path):
Folder.prototype.basename = function () {
return this.path.split('/').pop();
};
You would then append the base names to the array:
folderArray.push(sFolder.basename());
You could use split() like this, assuming there are no other slashes towards the end.
var sample = 'Z:/My File System/Me/Work Files/Design/Four'.split('/')
var result = sample[sample.length - 1]
Regexp the string. Start at the end, and work backward until the first '/'

Can't get Content of the folder using Skydrive API

I have real problem in displaying the content of the folders which are located inside the root directory. It managed to determine the folders which are in the Files directory but when I try to do the same to one of those folders It doesn't work.
I delieve the problem in the path name of a WL.api. However I may be mistaken.
I used code samples from skydrive page of live connect development center. in the sample below I tried to determine folders first, but eventually I would like to get the names of all files stored in a particular directory.
WL.api({ path: "me/skydrive/files/myfolder", method: "get" }).then(
function (response) {
var items = response.data;
var outPuts = "";
var number = items.length
var tempos = new Array();
var foundFolder = 0;
for (var i = 0; i < items.length; i++) {
if (items[i].type === "folder" || items[i].type === "album") {
tempos[i] = items[i].name;
foundFolder += 1;
}
}
if (foundFolder == 0) {
folderss.innerHTML = ("Unable to find any folders");
}
else {
for (var i = 0; i < number; i++) {
outPuts = outPuts + tempos[i] + "<br /> <br />"
}
folderss.innerHTML = outPuts;
}
}
);
if I retain only "me/skydrive/files" for WL path. it works. But if I add any particular folder name afer it like in my case "me/skydrive/files/myfolder" the call returns nothing. or may be I shall declare a path like: "me/skydrive/files/folder.567391047.34282821!"
Thank you for anyone who can help.
I believe your problem is due to the fact that you are using an invalid path format. According to the examples from the docs, a valid path to list files has the following form: /OBJECT_ID/files, where OBJECT_ID may be replaced by me/skydrive to reference the Skydrive root folder.
The important things to note are that:
there can be a reference (OBJECT_ID) to only one object;
this reference can only be the ID of an object (as returned by the API) or a special alias such as me/skydrive;
/files should always be the last part of the path (assuming we do not need to use a query string).
Thus, to list the contents of your subfolder folder.567391047.34282821!, you should try using the following path format instead:
/folder.567391047.34282821!/files or even folder.567391047.34282821!/files (without the leading slash, as it seems to be optional).
Please let me know if this solves your issue.

Javascript objects matching

A Javascript object can be used as an associative array.
So my question is how can I automatically set that multiple key's with the same ending match one value?
I'll write an example to be more explicit on what I want.
Something like this:
var handle = {}
handle[*css] = handlers.style;
Every key that ends with "css" should be matched to handlers.style.
Any way to doing this?
PD: Im doing this with server-side javascript with NodeJS
This is possible if you iterate through the object properties and check that the property name matches the desired pattern. Something like:
for (var i in obj) {
if (i.toString().substr(-3) === 'css') {
obj[i] = handlers.style;
}
}
A quick and dirty way:
var handle = {}
name = "article_users_css"
handle[name.substr(name.length-3)] = "something"
or if you can use some symbol to delimit the suffix, you can use this instead:
name.substr(str.lastIndexOf(YOUR_CHAR_OF_CHOICE))
I don't think you can do this. But you can the request pathname before routing the request to your handlers.
See example below:
var path = "mystyle.css"
// var path = "index.html"
// var path = "image.png"
var handle = {};
handle[css] = handlers.style;
handle[html] = handlers.html;
handle[img] = handlers.img;
if (path.match(/.*\.css/)) {
handle[css]();
}
else if (path.match(/.*\.html/)) {
handle[html]();
}
else if ((path.match(/.*\.png/) || path.match(/.*\.jpg/)) {
handle[img]();
}
You can consider using Express that does support routing based on regEx matching

Difficulty writing a function to extract URL from array

I'm trying to extract a URL from an array using JS but my code doesn't seem to be returning anything.
Would appreciate any help!
var pages = [
"www.facebook.com|Facebook",
"www.twitter.com|Twitter",
"www.google.co.uk|Google"
];
function url1_m1(pages, pattern) {
var URL = '' // variable ready to accept URL
for (var i = 0; i < pages[i].length; i++) {
// for each character in the chosen page
if (pages[i].substr(i, 4) == "www.") {
// check to see if a URL is there
while (pages[i].substr(i, 1) != "|") {
// if so then lets assemble the URL up to the colon
URL = URL + pages[i].substr(i, 1);
i++;
}
}
}
return (URL);
// let the user know the result
}
alert(url1_m1(pages, "twitter")); // should return www.twitter.com
In your case you can use this:
var page = "www.facebook.com|Facebook";
alert(page.match(/^[^|]+/)[0]);
You can see this here
It's just example of usage RegExp above. Full your code is:
var pages = [
"www.facebook.com|Facebook",
"www.twitter.com|Twitter",
"www.google.co.uk|Google"
];
var parseUrl = function(url){
return url.match(/^(www\.[^|]+)+/)[0];
};
var getUrl = function(param){
param = param.toLowerCase();
var page = _(pages).detect(function(page){
return page.toLowerCase().search(param)+1 !== 0;
});
return parseUrl(page);
};
alert(getUrl('twitter'));
You can test it here
In my code I have used Underscore library. You can replace it by standard for or while loops for find some array item.
And of course improve my code by some validations - for example, for undefined value, or if values in array are incorrect or something else.
Good luck!
Im not sure exactly what you are trying to do, but you could use split() function
var pair = pages[i].split("|");
var url = pair[0], title=pair[1];

Categories