Need a basename function in Javascript - javascript

I need a short basename function (one-liner ?) for Javascript:
basename("/a/folder/file.a.ext") -> "file.a"
basename("/a/folder/file.ext") -> "file"
basename("/a/folder/file") -> "file"
That should strip the path and any extension.
Update:
For dot at the beginning would be nice to treat as "special" files
basename("/a/folder/.file.a.ext") -> ".file.a"
basename("/a/folder/.file.ext") -> ".file"
basename("/a/folder/.file") -> ".file" # empty is Ok
basename("/a/folder/.fil") -> ".fil" # empty is Ok
basename("/a/folder/.file..a..") -> # does'nt matter

function basename(path) {
return path.split('/').reverse()[0];
}
Breaks up the path into component directories and filename then returns the last piece (the filename) which is the last element of the array.

function baseName(str)
{
var base = new String(str).substring(str.lastIndexOf('/') + 1);
if(base.lastIndexOf(".") != -1)
base = base.substring(0, base.lastIndexOf("."));
return base;
}
If you can have both / and \ as separators, you have to change the code to add one more line

Any of the above works although they have no respect for speed/memory :-).
A faster/simpler implementation should uses as fewer functions/operations as possible. RegExp is a bad choice because it consumes a lot of resources when actually we can achieve the same result but easier.
An implementation when you want the filename including extension (which in fact this is the genuine definition of basename):
function basename(str, sep) {
return str.substr(str.lastIndexOf(sep) + 1);
}
If you need a custom basename implementation that has to strip also the extension I would recommend instead a specific extension-stripping function for that case which you can call it whenever you like.
function strip_extension(str) {
return str.substr(0,str.lastIndexOf('.'));
}
Usage example:
basename('file.txt','/'); // real basename
strip_extension(basename('file.txt','/')); // custom basename
They are separated such that you can combine them to obtain 3 different things: stripping the extention, getting the real-basename, getting your custom-basename. I regard it as a more elegant implementation than others approaches.

Maybe try to use existing packages if you can. http://nodejs.org/api/path.html
var path = require('path');
var str = '/path/to/file/test.html'
var fileNameStringWithoutExtention = path.basename(str, '.html');
// returns 'test'
// let path determine the extension
var fileNameStringWithoutExtention = path.basename(str, path.extname(str));
// returns 'test'
Other examples:
var pathString = path.dirname(str);
var fileNameStringWithExtention = path.basename(str);
var fullPathAndFileNameString = path.join(pathString, fileNameString);

basename = function(path) {
return path.replace(/.*\/|\.[^.]*$/g, '');
}
replace anything that ends with a slash .*\/ or dot - some non-dots - end \.[^.]*$ with nothing

Just like #3DFace has commented:
path.split(/[\\/]/).pop(); // works with both separators
Or if you like prototypes:
String.prototype.basename = function(sep) {
sep = sep || '\\/';
return this.split(new RegExp("["+sep+"]")).pop();
}
Testing:
var str = "http://stackoverflow.com/questions/3820381/need-a-basename-function-in-javascript";
alert(str.basename());
Will return "need-a-basename-function-in-javascript".
Enjoy!

Using modern (2020) js code:
function basename (path) {
return path.substring(path.lastIndexOf('/') + 1)
}
console.log(basename('/home/user/file.txt'))

Contrary to misinformation provided above, regular expressions are extremely efficient. The caveat is that, when possible, they should be in a position so that they are compiled exactly once in the life of the program.
Here is a solution that gives both dirname and basename.
const rx1 = /(.*)\/+([^/]*)$/; // (dir/) (optional_file)
const rx2 = /()(.*)$/; // () (file)
function dir_and_file(path) {
// result is array with
// [0] original string
// [1] dirname
// [2] filename
return rx1.exec(path) || rx2.exec(path);
}
// Single purpose versions.
function dirname(path) {
return (rx1.exec(path) || rx2.exec(path))[1];
}
function basename(path) {
return (rx1.exec(path) || rx2.exec(path))[2];
}
As for performance, I have not measured it, but I expect this solution to be in the same range as the fastest of the others on this page, but this solution does more. Helping the real-world performance is the fact that rx1 will match most actual paths, so rx2 is rarely executed.
Here is some test code.
function show_dir(parts) {
console.log("Original str :"+parts[0]);
console.log("Directory nm :"+parts[1]);
console.log("File nm :"+parts[2]);
console.log();
}
show_dir(dir_and_file('/absolute_dir/file.txt'));
show_dir(dir_and_file('relative_dir////file.txt'));
show_dir(dir_and_file('dir_no_file/'));
show_dir(dir_and_file('just_one_word'));
show_dir(dir_and_file('')); // empty string
show_dir(dir_and_file(null));
And here is what the test code yields:
# Original str :/absolute_dir/file.txt
# Directory nm :/absolute_dir
# File nm :file.txt
#
# Original str :relative_dir////file.txt
# Directory nm :relative_dir
# File nm :file.txt
#
# Original str :dir_no_file/
# Directory nm :dir_no_file
# File nm :
#
# Original str :just_one_word
# Directory nm :
# File nm :just_one_word
#
# Original str :
# Directory nm :
# File nm :
#
# Original str :null
# Directory nm :
# File nm :null
By the way, "node" has a built in module called "path" that has "dirname" and "basename". Node's "path.dirname()" function accurately imitates the behavior of the "bash" shell's "dirname," but is that good? Here's what it does:
Produces '.' (dot) when path=="" (empty string).
Produces '.' (dot) when path=="just_one_word".
Produces '.' (dot) when path=="dir_no_file/".
I prefer the results of the function defined above.

Another good solution:
function basename (path, suffix) {
// discuss at: http://locutus.io/php/basename/
// original by: Kevin van Zonneveld (http://kvz.io)
// improved by: Ash Searle (http://hexmen.com/blog/)
// improved by: Lincoln Ramsay
// improved by: djmix
// improved by: Dmitry Gorelenkov
// example 1: basename('/www/site/home.htm', '.htm')
// returns 1: 'home'
// example 2: basename('ecra.php?p=1')
// returns 2: 'ecra.php?p=1'
// example 3: basename('/some/path/')
// returns 3: 'path'
// example 4: basename('/some/path_ext.ext/','.ext')
// returns 4: 'path_ext'
var b = path
var lastChar = b.charAt(b.length - 1)
if (lastChar === '/' || lastChar === '\\') {
b = b.slice(0, -1)
}
b = b.replace(/^.*[\/\\]/g, '')
if (typeof suffix === 'string' && b.substr(b.length - suffix.length) === suffix) {
b = b.substr(0, b.length - suffix.length)
}
return b
}
from: http://locutus.io/php/filesystem/basename/

Fast without regular expressions, suitable for both path types '/' and '\'. Gets the extension also:
function baseName(str)
{
let li = Math.max(str.lastIndexOf('/'), str.lastIndexOf('\\'));
return new String(str).substring(li + 1);
}

This is my implementation which I use in my fundamental js file.
// BASENAME
Window.basename = function() {
var basename = window.location.pathname.split(/[\\/]/);
return basename.pop() || basename.pop();
}

JavaScript Functions for basename and also dirname:
function basename(path) {
return path.replace(/.*\//, '');
}
function dirname(path) {
return path.match(/.*\//);
}
Sample:
Input dirname() basename()
/folder/subfolder/file.ext /folder/subfolder/ file.ext
/folder/subfolder /folder/ subfolder
/file.ext file.ext /
file.ext file.ext null
See reference.

Defining a flexible basename implementation
Despite all the answers, I still had to produce my own solution which fits the following criteria:
Is fully portable and works in any environment (thus Node's path.basename won't do)
Works with both kinds of separators (/ and \)
Allows for mixing separators - e.g. a/b\c (this is different from Node's implementation which respects the underlying system's separator instead)
Does not return an empty path if path ends on separator (i.e. getBaseName('a/b/c/') === 'c')
Code
(make sure to open the console before running the Snippet)
/**
* Flexible `basename` implementation
* #see https://stackoverflow.com/a/59907288/2228771
*/
function getBasename(path) {
// make sure the basename is not empty, if string ends with separator
let end = path.length-1;
while (path[end] === '/' || path[end] === '\\') {
--end;
}
// support mixing of Win + Unix path separators
const i1 = path.lastIndexOf('/', end);
const i2 = path.lastIndexOf('\\', end);
let start;
if (i1 === -1) {
if (i2 === -1) {
// no separator in the whole thing
return path;
}
start = i2;
}
else if (i2 === -1) {
start = i1;
}
else {
start = Math.max(i1, i2);
}
return path.substring(start+1, end+1);
}
// tests
console.table([
['a/b/c', 'c'],
['a/b/c//', 'c'],
['a\\b\\c', 'c'],
['a\\b\\c\\', 'c'],
['a\\b\\c/', 'c'],
['a/b/c\\', 'c'],
['c', 'c']
].map(([input, expected]) => {
const result = getBasename(input);
return {
input,
result,
expected,
good: result === expected ? '✅' : '❌'
};
}));

A nice one line, using ES6 arrow functions:
var basename = name => /([^\/\\]*|\.[^\/\\]*)\..*$/gm.exec(name)[1];
// In response to #IAM_AL_X's comments, even shorter and it
// works with files that don't have extensions:
var basename = name => /([^\/\\\.]*)(\..*)?$/.exec(name)[1];

function basename(url){
return ((url=/(([^\/\\\.#\? ]+)(\.\w+)*)([?#].+)?$/.exec(url))!= null)? url[2]: '';
}

Fairly simple using regex:
function basename(input) {
return input.split(/\.[^.]+$/)[0];
}
Explanation:
Matches a single dot character, followed by any character except a dot ([^.]), one or more times (+), tied to the end of the string ($).
It then splits the string based on this matching criteria, and returns the first result (ie everything before the match).
[EDIT]
D'oh. Misread the question -- he wants to strip off the path as well. Oh well, this answers half the question anyway.

my_basename('http://www.example.com/dir/file.php?param1=blabla#cprod', '/', '?');
// returns: file.php
CODE:
function my_basename(str, DirSeparator, FileSeparator) { var x= str.split(DirSeparator); return x[x.length-1].split(FileSeparator)[0];}

UPDATE
An improved version which works with forward / and backslash \ single or double means either of the following
\\path\\to\\file
\path\to\file
//path//to//file
/path/to/file
http://url/path/file.ext
http://url/path/file
See a working demo below
let urlHelper = {};
urlHelper.basename = (path) => {
let isForwardSlash = path.match(/\/{1,2}/g) !== null;
let isBackSlash = path.match(/\\{1,2}/g) !== null;
if (isForwardSlash) {
return path.split('/').reverse().filter(function(el) {
return el !== '';
})[0];
} else if (isBackSlash) {
return path.split('\\').reverse().filter(function(el) {
return el !== '';
})[0];
}
return path;
};
$('em').each(function() {
var text = $(this).text();
$(this).after(' --> <strong>' + urlHelper.basename(text) + '</strong><br>');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<em>http://folder/subfolder/file.ext</em><br>
<em>http://folder/subfolder/subfolder2</em><br>
<em>/folder/subfolder</em><br>
<em>/file.ext</em><br>
<em>file.ext</em><br>
<em>/folder/subfolder/</em><br>
<em>//folder//subfolder//</em><br>
<em>//folder//subfolder</em><br>
<em>\\folder\\subfolder\\</em><br>
<em>\\folder\\subfolder\\file.ext</em><br>
<em>\folder\subfolder\</em><br>
<em>\\folder\\subfolder</em><br>
<em>\\folder\\subfolder\\file.ext</em><br>
<em>\folder\subfolder</em><br>
A more simpler solution could be
function basename(path) {
return path.replace(/\/+$/, "").replace( /.*\//, "" );
}
Input basename()
/folder/subfolder/file.ext --> file.ext
/folder/subfolder --> subfolder
/file.ext --> file.ext
file.ext --> file.ext
/folder/subfolder/ --> subfolder
Working example: https://jsfiddle.net/Smartik/2c20q0ak/1/

If your original string or text file contains a single backslash character, you could locate it by using '\\'.
In my circumstance, I am using JavaScript to find the index of "\N" from a text file. And str.indexOf('\\N'); helped me locate the \N from the original string, which is read from the source file.

Related

Extract the last part of URL path with Custom JS - but not added parameters with?

I am trying to extract the last part of a URL to track in GTM, but not include added parameters like "?gclid=...".
As in:
https://example.com/m/5f5a0a9472cf844b320b6136/?gclid=1234
I want to just extract the 5f5a0a9472cf844b320b6136.
So far I've used:
function() {
var pageUrl = window.location.href;
return pageUrl.split("/")[pageUrl.split("/").length - 1];
}
But that is giving me the gclid number. This issue is, that parameter only exists on the landing page, not subsequent pages.
so if I were to use length - 2] that won't work once they leave the landing page. It would return the /m/.
How do I escape the "?" string on the landing page?
You can do something like this which will be easier
function (){
paths = window.location.pathname.split("/")
return paths[paths.length-1]
}
maybe this will help
const strs = [
"https://example.com/5f5a0a9472cf844b320b6136/?gclid=1234/",
"https://example.com/m/5f5a0a9472cf844b320b6136/?gclid=1234/",
"https://example.com/m/n/5f5a0a9472cf844b320b6136/",
"https://example.com/m/n/5f5a0a9472cf844b320b6136",
];
strs.forEach((str) => {
// ********************
if (str.includes("?")) {
const parts = str.split("/?")[0].split("/");
console.log(parts[parts.length - 1]);
} else {
const lastChar = str.charAt(str.length - 1);
str = lastChar === "/" ? str.substring(0, str.length - 1) : str;
const parts = str.split("/");
console.log(parts[parts.length - 1]);
}
// ********************
});
Since your using GTM, enable and use the built-in "page path" variable instead, which does not include parameters:
function() {
return {{Page Path}}.split("/").pop();
}
pop() return the last element from the array (it also removes it from the array, which in this case does not matter).
Okay, I found an alternative solution that I thought I'd share. Because that variable string always totals 24 characters, I created a function to look for it.
function getQuoteId() {
var segments = window.location.pathname.split('/');
for (var i = segments.length - 1; i >= 0; i--) {
if (segments[i] && segments[i].length === 24) {
return segments[i];
}
}
return null;
}
This mitigates the trailing "/" as well as the added parameters, and it returns the path I was looking to isolate.

How do I use Regex to check an array of URLs to see if I return to the original folder

Let's say we have an array of strings and each strings are either ./ or ../, where ./ meaning entering the next level of the current folder, and ../ meaning going back to the upper level folder. So the array would be something like [./, ../, ../, ./]. And we want to check if we eventually return to the original folder.
I know this problem is quite simple. I tried to iterate the array and for each item I delete the last char in the string i.e. the '/' using str.slice(0,-1) then I count every '..' and '.' to see if they are equal.
However I feel somehow my code is brittle and really would like to see how someone can use regex to solve this problem.
let numOfGoingDeeper = 0;
let numOfGoingBack = 0;
arr.forEach(str => {
if(str.slice(0,-1) === '..') {
numOfGoingBack++;
} else if(str.slice(0,-1) === '.') {
numOfGoingDeeper++;
}
}
return numOfGoingDeeper === numOfGoingBack
))
Your code already performs quite well. If you desire more regexiness and speed you could count the .match results.
function pathFunction(arr) {
let inputString = arr.join();
let regex = /\.\.\//g; // To count and remove all ../
let numOfGoingDeeper = (inputString.match(regex) || []).length;
inputString = inputString.replace(regex);
regex = /\.\//g; // To count all ./
let numOfGoingBack = (inputString.match(regex) || []).length;
return numOfGoingDeeper === numOfGoingBack;
}
console.log ( pathFunction(['../','./','../','./']) );
This isn't your question but just in case: In UNIX ../ does mean go up a directory but ./ represents the current directory. So a path .././.././ would be equal to the path ../../
You don't even need a Regex. You could perform a simple search/replace to change every "../" to -1 and every "./" to +1, then sum the results.
var arr = ["./", "../", "../", "./"];
var new_arr = arr.map(x => x.replace("../", -1).replace("./", 1));
var deplacement = new_arr.reduce((acc, val) => acc + parseInt(val, 10), 0);
console.log(deplacement)

How to namespace a string (eg. 'a(x) + b' => 'Namespace.a(x) + Namespace.b')

I am looking for a function that will namespace a string, for example if I wanted to namespace the following string with "MyLib",
"select('#input') + someconstant * otherconstant"
will be changed to
"MyLib.select('#input') + MyLib.someconstant * MyLib.otherconstant"
btw it takes in a string as an input, and returns another string
The reason I want to do this is because I am writing a user interface which compares my custom math functions with another libraries custom math functions, for example the user might type
"factorial(2) + sin(intpow(2, 4))"
which would be converted to
"MyCustomLib.factorial(2) + MyCustomLib.sin(MyCustomLib.intpow(2, 4))"
/* and */
"OtherLib.factorial(2) + OtherLib.sin(OtherLib.intpow(2, 4))"
And then i can use eval() to evaluate it ( dont worry about me using eval, worry about the question :) )
my current function looks like
const namespace = (str, ns) => {
ns = ns + '.'; // add the dot to the namespace
let s = String(str),
m, // the result of regex
re = /\w+/g, // only namespace words
a = 0; // because there are two strings, and i am
// only adding to one of them,
// i have to increase the index to make up for
// the difference between the two
while ((m = re.exec(str)) !== null) { // until there is no more words
// get the new string (put the namespace in)
// eg. "(junk) abc (junk)" => "(junk) Namespace.abc (junk)"
s = s.slice(0, m.index + a) + ns + s.slice(m.index + a);
a += ns.length; // add to the offset
}
return s; // return the parsed string
};
where param str is the input string, and param ns is the namespace
it works, ie.
namespace("PI * sin(E)", "Math") === "Math.PI * Math.sin(Math.E)"
but it doesnt fully work, ie
namespace("23", "abc"); /* === "abc.23" */
when it should instead equal "23"
any ideas?
You can use re = /[A-z]+/g, to map only alphabet characters

Number formatting in template strings (Javascript - ES6)

I was wondering if it is possible to format numbers in Javascript template strings, for example something like:
var n = 5.1234;
console.log(`This is a number: $.2d{n}`);
// -> 5.12
Or possibly
var n = 5.1234;
console.log(`This is a number: ${n.toString('.2d')}`);
// -> 5.12
That syntax obviously doesn't work, it is just an illustration of the type of thing I'm looking for.
I am aware of tools like sprintf from underscore.string, but this seems like something that JS should be able to do out the box, especially given the power of template strings.
EDIT
As stated above, I am already aware of 3rd party tools (e.g. sprintf) and customised functions to do this. Similar questions (e.g. JavaScript equivalent to printf/String.Format) don't mention template strings at all, probably because they were asked before the ES6 template strings were around. My question is specific to ES6, and is independent of implementation. I am quite happy to accept an answer of "No, this is not possible" if that is case, but what would be great is either info about a new ES6 feature that provides this, or some insight into whether such a feature is on its way.
No, ES6 does not introduce any new number formatting functions, you will have to live with the existing .toExponential(fractionDigits), .toFixed(fractionDigits), .toPrecision(precision), .toString([radix]) and toLocaleString(…) (which has been updated to optionally support the ECMA-402 Standard, though).
Template strings have nothing to do with number formatting, they just desugar to a function call (if tagged) or string concatenation (default).
If those Number methods are not sufficient for you, you will have to roll your own. You can of course write your formatting function as a template string tag if you wish to do so.
You should be able to use the toFixed() method of a number:
var num = 5.1234;
var n = num.toFixed(2);
If you want to use ES6 tag functions here's how such a tag function would look,
function d2(pieces) {
var result = pieces[0];
var substitutions = [].slice.call(arguments, 1);
for (var i = 0; i < substitutions.length; ++i) {
var n = substitutions[i];
if (Number(n) == n) {
result += Number(substitutions[i]).toFixed(2);
} else {
result += substitutions[i];
}
result += pieces[i + 1];
}
return result;
}
which can then be applied to a template string thusly,
d2`${some_float} (you can interpolate as many floats as you want) of ${some_string}`;
that will format the float and leave the string alone.
Here's a fully ES6 version of Filip Allberg's solution above, using ES6 "rest" params. The only thing missing is being able to vary the precision; that could be done by making a factory function. Left as an exercise for the reader.
function d2(strs, ...args) {
var result = strs[0];
for (var i = 0; i < args.length; ++i) {
var n = args[i];
if (Number(n) == n) {
result += Number(args[i]).toFixed(2);
} else {
result += args[i];
}
result += strs[i+1];
}
return result;
}
f=1.2345678;
s="a string";
console.log(d2`template: ${f} ${f*100} and ${s} (literal:${9.0001})`);
While template-string interpolation formatting is not available as a built-in, you can get equivalent behavior with Intl.NumberFormat:
const format = (num, fraction = 2) => new Intl.NumberFormat([], {
minimumFractionDigits: fraction,
maximumFractionDigits: fraction,
}).format(num);
format(5.1234); // -> '5.12'
Note that regardless of your implementation of choice, you might get bitten by rounding errors:
(9.999).toFixed(2) // -> '10.00'
new Intl.NumberFormat([], {
minimumFractionDigits: 2,
maximumFractionDigits: 2, // <- implicit rounding!
}).format(9.999) // -> '10.00'
based on ES6 Tagged Templates (credit to https://stackoverflow.com/a/51680250/711085), this will emulate typical template string syntax in other languages (this is loosely based on python f-strings; I avoid calling it f in case of name overlaps):
Demo:
> F`${(Math.sqrt(2))**2}{.0f}` // normally 2.0000000000000004
"2"
> F`${1/3}{%} ~ ${1/3}{.2%} ~ ${1/3}{d} ~ ${1/3}{.2f} ~ ${1/3}"
"33% ~ 33.33% ~ 0 ~ 0.33 ~ 0.3333333333333333"
> F`${[1/3,1/3]}{.2f} ~ ${{a:1/3, b:1/3}}{.2f} ~ ${"someStr"}`
"[0.33,0.33] ~ {\"a\":\"0.33\",\"b\":\"0.33\"} ~ someStr
Fairly simple code using :
var FORMATTER = function(obj,fmt) {
/* implements things using (Number).toFixed:
${1/3}{.2f} -> 0.33
${1/3}{.0f} -> 1
${1/3}{%} -> 33%
${1/3}{.3%} -> 33.333%
${1/3}{d} -> 0
${{a:1/3,b:1/3}}{.2f} -> {"a":0.33, "b":0.33}
${{a:1/3,b:1/3}}{*:'.2f',b:'%'} -> {"a":0.33, "b":'33%'} //TODO not implemented
${[1/3,1/3]}{.2f} -> [0.33, 0.33]
${someObj} -> if the object/class defines a method [Symbol.FTemplate](){...},
it will be evaluated; alternatively if a method [Symbol.FTemplateKey](key){...}
that can be evaluated to a fmt string; alternatively in the future
once decorators exist, metadata may be appended to object properties to derive
formats //TODO not implemented
*/
try {
let fracDigits=0,percent;
if (fmt===undefined) {
if (typeof obj === 'string')
return obj;
else
return JSON.stringify(obj);
} else if (obj instanceof Array)
return '['+obj.map(x=> FORMATTER(x,fmt))+']'
else if (typeof obj==='object' && obj!==null /*&&!Array.isArray(obj)*/)
return JSON.stringify(Object.fromEntries(Object.entries(obj).map(([k,v])=> [k,FORMATTER(v,fmt)])));
else if (matches = fmt.match(/^\.(\d+)f$/))
[_,fracDigits] = matches;
else if (matches = fmt.match(/^(?:\.(\d+))?(%)$/))
[_,fracDigits,percent] = matches;
else if (matches = fmt.match(/^d$/))
fracDigits = 0;
else
throw 'format not recognized';
if (obj===null)
return 'null';
if (obj===undefined) {
// one might extend the above syntax to
// allow for example for .3f? -> "undefined"|"0.123"
return 'undefined';
}
if (percent)
obj *= 100;
fracDigits = parseFloat(fracDigits);
return obj.toFixed(fracDigits) + (percent? '%':'');
} catch(err) {
throw `error executing F\`$\{${someObj}\}{${fmt}}\` specification: ${err}`
}
}
function F(strs, ...args) {
/* usage: F`Demo: 1+1.5 = ${1+1.5}{.2f}`
--> "Demo: 1+1.5 = 2.50"
*/
let R = strs[0];
args.forEach((arg,i)=> {
let [_,fmt,str] = strs[i+1].match(/(?:\{(.*)(?<!\\)\})?(.*)/);
R += FORMATTER(arg,fmt) + str;
});
return R;
}
sidenote: The core of the code is as follows. The heavy lifting is done by the formatter. The negative lookbehind is somewhat optional, and to let one escape actual curly braces.
let R = strs[0];
args.forEach((arg,i)=> {
let [_,fmt,str] = strs[i+1].match(/(?:\{(.*)(?<!\\)\})?(.*)/);
R += FORMATTER(arg,fmt) + str;
});
You can use es6 tag functions. I don't know ready for use of that.
It might look like this:
num`This is a number: $.2d{n}`
Learn more:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
https://developers.google.com/web/updates/2015/01/ES6-Template-Strings

Javascript say if a folder is child of another

I have these strings which are addresses of files and folder:
../../../folder1/sub1/sub12/
../../../folder1/
../../../another-folder/
I want to compare them using javascript - possibily jquery - to see if for example string 1 have a part egual to string 2 but something more saying that string 1 is child of string 2.
How can i do this?
you could try something like the following
var path1 = "../../../folder1/";
var path2 = "../../../folder1/sub1/sub12/";
if (path2.indexOf(path1) != -1){
//path2 is a sub of path 1
}
In case your string can contain also absolute paths or paths containing .. not only at the beginning I would recommend checking if .indexOf return 0 instead of anything that is not -1.
It can help with cases like.
var path1 = "/rootFolder/";
var path2 = "../folder/rootFolder/";
if (path2.indexOf(path1) === 0) {
console.log("You want this"); // won't get executed => good
}
if (path2.indexOf(path1) !=-1) {
console.log("You don't want this"); // will get executed => bad
}
if(string1.indexOf(string2) != -1){
//string2 is present in string1
}
else{
//string2 is not present in string1
}
You can use the indexOf method to find whether one string is a part of another string.
From w3schools documentation:
The indexOf() method returns the position of the first occurrence of a
specified value in a string.
This method returns -1 if the value to search for never occurs.
var test = "../folder/subfolder1";
var test2 = "../folder";
if (test.indexOf(test2) !=-1) {
alert(test + " is a subfolder of " + test2);
}

Categories