@n3okill/utils
Version:
Many javascript helpers
115 lines • 4.84 kB
JavaScript
import { rangeFromString } from "../array/rangeFromString";
import { isAlphaSequence } from "../type/isAlphaSequence";
import { isArray } from "../type/isArray";
import { isNumericSequence } from "../type/isNumericSequence";
import { isString } from "../type/isString";
import { balancedData } from "./balancedData";
import { isBalanced } from "./isBalanced";
/**
* Return an expanded string based on input string and options
* @param input
* @param options {IExpandOpts}
* @returns
*
* Examples:
*
* expand("{1..3}") => ["1","2","3"]
* expand("{a..c}") => ["a","b","c"]
* expand("a{b..d}g{1..3}z") => ["abg1z", "abg2z", "abg3z", "acg1z", "acg2z", "acg3z", "adg1z", "adg2z", "adg3z"]
* expand("{a,b{1..3},c}") => ["a", "b1", "b2", "b3", "c"]
* expand("{{A..Z},{a..z}}") => ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
* expand("a{d,c,b}e") => ["ade", "ace", "abe"]
* expand("a{1..2}b{2..3}c") => ["a1b2c", "a1b3c", "a2b2c", "a2b3c"]
* expand("{3..-2}") => ["3", "2", "1", "0", "-1", "-2"]
*
* For more examples check the tests
*/
export function expand(input, options = {
open: "{",
close: "}",
separator: ",",
}) {
if (!isBalanced(input, options.open, options.close)) {
return [];
}
const matches = balancedData(input, options.open, options.close); //(balancedData(input, options.open, options.close) ?? []) as BalancedData[];
if (matches.length === 0) {
return [input];
}
else {
let str = input;
matches.forEach((match) => {
if (match.pre.charAt(match.pre.length - 1) !== "$") {
if (match.body.indexOf(",") === -1) {
str = str.replace(`${options.open}${match.body}${options.close}`, () => {
let toInsert = "";
if (isNumericSequence(match.body) || isAlphaSequence(match.body)) {
toInsert = rangeFromString(match.body).join(options.separator);
}
else {
toInsert = match.body;
}
return /\.\./.test(match.body)
? `${options.open}${toInsert}${options.close}`
: toInsert;
});
}
}
});
if (str.indexOf(options.open) === -1 && str.indexOf(options.close) === -1) {
return [str];
}
const normalizeNestedOptions = function (str) {
const matches = balancedData(str, options.open, options.close); //(balancedData(str, options.open as string, options.close as string) ?? []) as BalancedData[];
if (matches.length === 0) {
if (str.indexOf(",") !== -1) {
return str.split(",");
}
else {
return str;
}
}
else {
matches.forEach((match) => {
let result = normalizeNestedOptions(match.body);
if (isString(result)) {
str = str.replace(match.body, result);
}
else if (isArray(result)) {
const pre = match.pre.split(",");
const p = pre.pop();
result = result.map((val) => p + val);
str = str.replace(`${p}${options.open}${match.body}${options.close}`, result.join(","));
}
});
}
return str;
};
let matches2 = balancedData(str, options.open, options.close); //(balancedData(str, options.open as string, options.close as string) ?? []) as BalancedData[];
matches2.forEach((m) => {
str = str.replace(m.body, normalizeNestedOptions(m.body));
});
let result = [str];
matches2 = balancedData(str, options.open, options.close); //(balancedData(str, options.open as string, options.close as string) ?? []) as BalancedData[];
matches2.forEach((m) => {
const tempResult = [];
result.forEach((s) => {
if (m.pre.charAt(m.pre.length - 1) === "$") {
tempResult.push(s);
}
else {
m.body.split(",").forEach((a) => {
tempResult.push(s.replace(`${options.open}${m.body}${options.close}`, () => {
return /\.\./.test(m.body)
? `${options.open}${m.body}${options.close}`
: a;
}));
});
}
});
result = tempResult;
});
return result;
}
}
//# sourceMappingURL=expand.js.map