@kwiz/common
Version:
KWIZ common utilities and helpers for M365 platform
322 lines • 12.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.endsWith = endsWith;
exports.startsWith = startsWith;
exports.trim = trim;
exports.trimEnd = trimEnd;
exports.trimStart = trimStart;
exports.splice = splice;
exports.padRight = padRight;
exports.padLeft = padLeft;
exports.GetTokens = GetTokens;
exports.ReplaceTokens = ReplaceTokens;
exports.ReplaceTokensInDictionary = ReplaceTokensInDictionary;
exports.normalizeGuid = normalizeGuid;
exports.isEmptyGuid = isEmptyGuid;
exports.escapeRegExp = escapeRegExp;
exports.isValidDomainLogin = isValidDomainLogin;
exports.stripRichTextWhitespace = stripRichTextWhitespace;
exports.isValidVarName = isValidVarName;
exports.isValidHeaderName = isValidHeaderName;
exports.GetTokenInfo = GetTokenInfo;
exports.stringEqualsOrEmpty = stringEqualsOrEmpty;
exports.stringContains = stringContains;
exports.cleanupString = cleanupString;
exports.normalizeHtmlSpace = normalizeHtmlSpace;
exports.replaceAll = replaceAll;
exports.capitalizeFirstLetter = capitalizeFirstLetter;
exports.escapeXml = escapeXml;
exports.replaceRegex = replaceRegex;
exports.maskString = maskString;
exports.splitString = splitString;
const collections_base_1 = require("./collections.base");
const typecheckers_1 = require("./typecheckers");
function endsWith(str, value, ignoreCase) {
let str1 = str;
let find = value;
if (ignoreCase) {
str1 = str1.toLowerCase();
find = find.toLowerCase();
}
return str1.substr(str1.length - find.length) === find;
}
function startsWith(str, value, ignoreCase) {
let str1 = str;
let find = value;
if (ignoreCase) {
str1 = str1.toLowerCase();
find = find.toLowerCase();
}
return str1.substr(0, find.length) === find;
}
/** remove space at start or end */
function trim(str) {
return str.replace(/^\s+|\s+$/g, '');
}
function trimEnd(str) {
return str.replace(/\s+$/, "");
}
function trimStart(str) {
return str.replace(/^\s+/, "");
}
function splice(str, start, delCount, insert) {
return str.slice(0, start) + insert + str.slice(start + Math.abs(delCount));
}
function padRight(value, length, fillString = "0") {
if ((0, typecheckers_1.isNumber)(value))
value = value.toString(10);
let pad = (0, typecheckers_1.isNullOrEmptyString)(fillString) ? "0" : fillString[0];
return value + Array(length - value.length + 1).join(pad);
}
function padLeft(value, length, fillString = "0") {
if ((0, typecheckers_1.isNumber)(value))
value = value.toString(10);
let pad = (0, typecheckers_1.isNullOrEmptyString)(fillString) ? "0" : fillString[0];
return Array(length - String(value).length + 1).join(pad) + value;
}
/** returns array of [token] found inside the string
* supports token formats [Author??Created by {0}::Unknown author] will return "Author" as the token
* */
function GetTokens(StringFormat) {
let tokensResult = [];
if ((0, typecheckers_1.isNullOrEmptyString)(StringFormat))
return tokensResult;
let tokens = StringFormat.match(/\[[^\]]*\]/g);
if (tokens && tokens.length > 0) {
tokens.forEach(token => {
let key = token.slice(1, token.length - 1);
key = GetTokenInfo(key).tokenName;
if (tokensResult.indexOf(key) < 0)
tokensResult.push(key);
});
}
return tokensResult;
}
/** replaces a string with [token] and [otherToken] with their matched provided values
* supports token formats [Author??Created by {0}::Unknown author]
*/
function ReplaceTokens(StringFormat, TokenValues, options) {
let skipMissingTokens = options && options.keepMissingTokens;
if ((0, typecheckers_1.isNullOrUndefined)(StringFormat))
return null;
if (StringFormat !== '') {
let tokens = StringFormat.match(/\[[^\]]*\]/g);
if (tokens && tokens.length > 0) {
if ((0, typecheckers_1.isNullOrUndefined)(TokenValues))
TokenValues = {};
tokens.forEach(token => {
let key = token.slice(1, token.length - 1);
let tokenInfo = GetTokenInfo(key);
let value = TokenValues[tokenInfo.tokenName];
let skip = false;
if ((0, typecheckers_1.isNullOrUndefined)(value)) {
value = "";
skip = skipMissingTokens; //if true we won't replace this one
}
if (!skip || tokenInfo.hasFormat)
StringFormat = StringFormat.replace(token, tokenInfo.getValue(value));
});
}
}
return StringFormat;
}
/** calls replace tokens on every dictionary value, or set null keys to "". This function ignores null/empty dictionaries */
function ReplaceTokensInDictionary(Dictionary, TokenValues) {
if (!(0, typecheckers_1.isNullOrUndefined)(Dictionary)) {
Object.keys(Dictionary).forEach(key => {
Dictionary[key] = (0, typecheckers_1.isNullOrEmptyString)(Dictionary[key]) ? "" : ReplaceTokens(Dictionary[key], TokenValues);
});
}
}
/** Normalizes a guid string, lower case and removes {} */
function normalizeGuid(text, removeDashes) {
if ((0, typecheckers_1.isNullOrEmptyString)(text) || !(0, typecheckers_1.isString)(text)) {
return text;
}
var guid = text.toLowerCase().trim();
if (guid.startsWith("{")) {
guid = guid.substr(1);
}
if (guid.endsWith("}")) {
guid = guid.substr(0, guid.length - 1);
}
if (removeDashes) {
guid = guid.replace(/-/g, '');
}
return guid;
}
function isEmptyGuid(guid) {
if ((0, typecheckers_1.isNullOrEmptyString)(guid))
return true;
else if (Number(normalizeGuid(guid.toString(), true)) === 0)
return true;
return false;
}
function escapeRegExp(text) {
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
}
function isValidDomainLogin(login) {
return /^[A-Za-z0-9\\._-]{7,}$/.test(login);
}
function stripRichTextWhitespace(value) {
// richText fields in have random markup even when field is empty
// \u200B zero width space
// \u200C zero width non-joiner Unicode code point
// \u200D zero width joiner Unicode code point
// \uFEFF zero width no-break space Unicode code point
return (0, typecheckers_1.isString)(value) ? value.replace(/[\u200B-\u200D\uFEFF]/g, "") : value;
}
/** allows min length 1, letters, numbers underscore only */
function isValidVarName(text) {
return /^[A-Za-z0-9_]{1,}$/.test(text);
}
/** allows min length 1, letters, numbers underscore and hyphen only */
function isValidHeaderName(text) {
return /^[A-Za-z0-9_-]{1,}$/.test(text);
}
/** returns token info with format */
function GetTokenInfo(text) {
let split = text.split('??');
let hasFormat = split.length > 0 && !(0, typecheckers_1.isNullOrEmptyString)(split[1]);
let formatSplit = hasFormat ? split[1].split('::') : [];
let valueIfEmpty = formatSplit.length > 1 ? formatSplit[1] : "";
let formatIfNotEmpty = formatSplit[0];
let info = {
tokenName: hasFormat ? split[0] : text,
hasFormat: hasFormat,
getValue: (value) => {
if (!hasFormat)
return value;
else {
if ((0, typecheckers_1.isNullOrEmptyString)(value))
return valueIfEmpty;
else
return formatIfNotEmpty.replace('{0}', value);
}
}
};
return info;
}
/** return true if both strings are the same, or both are empty/null/undefined */
function stringEqualsOrEmpty(str1, str2, ignoreCase) {
if ((0, typecheckers_1.isNullOrEmptyString)(str1) && (0, typecheckers_1.isNullOrEmptyString)(str2))
return true;
if (ignoreCase) {
if (!(0, typecheckers_1.isNullOrEmptyString)(str1))
str1 = str1.toLowerCase();
if (!(0, typecheckers_1.isNullOrEmptyString)(str2))
str2 = str2.toLowerCase();
}
return str1 === str2;
}
/** return true if str1 contains str2 */
function stringContains(str1, str2, ignoreCase) {
if ((0, typecheckers_1.isNullOrEmptyString)(str1) && (0, typecheckers_1.isNullOrEmptyString)(str2))
return true;
if ((0, typecheckers_1.isNullOrEmptyString)(str1))
str1 = "";
if ((0, typecheckers_1.isNullOrEmptyString)(str2))
str2 = "";
if (ignoreCase) {
str1 = str1.toLowerCase();
str2 = str2.toLowerCase();
}
return str1.indexOf(str2) >= 0;
}
function cleanupString(str, options) {
if ((0, typecheckers_1.isString)(options.replaceNewLines))
str = str.replace(/\r/g, '') //no returns
.replace(/\n/g, options.replaceNewLines); //no line breaks
if ((0, typecheckers_1.isString)(options.collapseMultipleDashes))
str = str.replace(/-+/g, options.collapseMultipleSpaces); //no extra spaces
if ((0, typecheckers_1.isString)(options.collapseMultipleUnderscore))
str = str.replace(/_+/g, options.collapseMultipleUnderscore); //no extra spaces
// do this last, so it will collapse spaces added by previous options
if ((0, typecheckers_1.isString)(options.collapseMultipleSpaces)) {
str = str.replace(new RegExp(String.fromCharCode(160), "g"), '') //get rid of non-breaking spaces
.replace(/ +/g, options.collapseMultipleSpaces); //no extra spaces
}
return str;
}
/** normalizes   to see Issue 752 */
function normalizeHtmlSpace(html) {
if ((0, typecheckers_1.isNullOrEmptyString)(html))
return html;
return html.replace(/ /i, " ");
}
function replaceAll(str, find, replace, ignoreCase = false) {
//must call escapeRegExp on find, to make sure it works when there are protected regex characters
return str.replace(new RegExp(escapeRegExp(find), `g${ignoreCase ? 'i' : ''}`), replace);
}
function capitalizeFirstLetter(str) {
return (0, typecheckers_1.isNullOrEmptyString)(str)
? ""
: `${str.charAt(0).toUpperCase()}${str.substring(1)}`;
}
function escapeXml(unsafe, isAttribute = false) {
if ((0, typecheckers_1.isNullOrEmptyString)(unsafe))
return "";
return isAttribute
? unsafe.replace(/[<>&'"]/g, (c) => {
switch (c) {
case '<': return '<';
case '>': return '>';
case '&': return '&';
case '\'': return ''';
case '"': return '"';
}
return c;
})
: unsafe.replace(/[<>&]/g, (c) => {
switch (c) {
case '<': return '<';
case '>': return '>';
case '&': return '&';
}
return c;
});
}
/** uses regex str.match to replace each match by calling the replacer function (imported from CMS) */
function replaceRegex(str, regex, replacer) {
let matches = str.match(regex);
if (!matches || matches.length < 1)
return str;
//replace each found token only once
let unique = (0, collections_base_1.makeUniqueArray)(matches);
//todo: this has a bug where tokens matched contain each other, example, match numbers and prefix with #: 10, 100 will match both and produce #10 ##100
unique.forEach(m => {
let replacement = replacer(m);
if (!(0, typecheckers_1.isNullOrUndefined)(replacement)) //ignore nulls
str = replaceAll(str, m, replacement);
});
return str;
}
/** masks a long string, keeping X number for characters at the start/end and replacing the middle with the mask string (default: CC*****CCC) */
function maskString(str, options) {
const mask = options && options.mask || "*****";
const start = options && (0, typecheckers_1.isNumber)(options.start) ? options.start : 2;
const end = options && (0, typecheckers_1.isNumber)(options.end) ? options.end : 2;
const prefix = start >= 0 ? str.slice(0, start) : str;
const sliceEnd = str.length - end;
const suffix = sliceEnd >= 0 ? str.slice(sliceEnd) : str;
return `${prefix}${mask}${suffix}`;
}
function splitString(str, options) {
let strArr = [str];
if (!(0, typecheckers_1.isNullOrUndefined)(options.marker))
strArr = str.split(options.marker);
if ((0, typecheckers_1.isNumber)(options.maxLength) && options.maxLength > 0) {
let splitted = [];
strArr.forEach(currentStr => {
while (currentStr.length > 0) {
splitted.push(currentStr.slice(0, options.maxLength));
currentStr = currentStr.slice(options.maxLength);
}
});
strArr = splitted;
}
if (options.clearEmptyEntries)
strArr = (0, collections_base_1.filterEmptyEntries)(strArr);
return strArr;
}
//# sourceMappingURL=strings.js.map