application/util/strings.js
import moment from 'moment';
import diff from 'htmldiff/src/htmldiff.js';
import {Html5Entities} from 'html-entities';
import queryString from 'query-string';
/**
* Convert a string into a URL slug
* @param {string} str
* @param {string} allowTrailing Allows preservation of trailing slash. Useful when live editing
* @return {string}
*/
export const sluggify = (str, allowTrailing = false) => {
str = str.replace(/[^a-zA-Z0-9\._\-\%\& ]/g, '')
.replace(/\s{2,}/g, ' ')
.replace(/\.{2,}/g, '.')
.replace(/ /g, '-')
.replace(/(\-){2,}/, '-')
.toLowerCase();
if (str.indexOf('-') === 0) {
str = str.substr(1);
}
if (!allowTrailing && str.lastIndexOf('-') === str.length-1) {
str = str.substr(0, str.length-1);
}
return str;
};
/**
* Ensure a string is URL friendly. Unlike sluggify, it will not remove
* forward slashes (but will deduplicate them).
* @param {string} str
* @param {boolean} strip start and end slashes (default is TRUE)
* @return {string}
*/
export const urlify = (str, stripSlashes = true) => {
let newStr = str.replace(/\/{2,}/g, '/');
newStr = sluggify(newStr.replace(/\//g, '%slash%'), true).replace(/%slash%/g, '/');
if (stripSlashes && newStr.indexOf('/') === 0) {
newStr = newStr.substr(1);
}
if (stripSlashes && newStr.lastIndexOf('/') === newStr.length-1) {
newStr = newStr.substr(0, newStr.length-1);
}
return newStr;
}
/**
* Convert hash into HTTP parameter string.
*
* Adapted from
* http://stackoverflow.com/questions/1714786/querystring-encoding-of-a-javascript-object
* @param {object} obj Hash
* @param {string} prefix Used in recursion
* @return {string}
*/
export const parameterize = (obj, prefix = null) => {
let str;
if (prefix === null) {
str = queryString.stringify(obj, {arrayFormat: 'bracket'});
if (str.indexOf('object%20Object') === -1) {
return str;
}
}
str = [];
for(let p in obj) {
if (obj.hasOwnProperty(p)) {
let k = prefix ? prefix + "[" + p + "]" : p, v = obj[p];
str.push(typeof v == "object" ? parameterize(v, k) : encodeURIComponent(k) + "=" + encodeURIComponent(v));
}
}
return str.join("&");
};
/**
* Convert time to local string.
* The server stores and returns timestamps as UTC, this converts them
* to local time and formats
* @param {string} time Time
* @param {string} fmt Format, default M/DD/YYYY HH:MM:P
* @return {string}
*/
export const timeToFormat = (time, fmt) => {
if (!fmt) {
fmt = 'l LT';
}
return moment.utc(time).local().format(fmt);
};
/**
* Parse a SRN into its component parts
* @param {string} srn SRN
* @return {object} Mapped SRN
*/
export const parseSrn = (srn) => {
let parts = srn.split(':');
parts.shift();
let data = {
'client': parts.shift(),
'app': parts.shift(),
'uuid': parts.shift()
};
data.extra = parts.join(':');
parts = data.app.split('/');
data.app = parts[0];
data.model = parts[1];
return data;
};
/**
* HTML String diff
* @param {string} strA String A
* @param {string} strB String B
* @return {string} Diffed, tagged, HTML string
*/
export const htmlDiff = (strA, strB) => {
return diff(strA, strB);
};
export const degraf = (str) => {
return str.replace(/<p>(<br( ?\/?)>| )<\/p>(\n)?/g, '').trim();
}
/**
* HTML String decoder
* Decode HTML5 entities
* @param {string} str
* @return {string} decoded string
*/
export const htmlDecode = (str) => {
return Html5Entities.decode(str);
}
/**
* Truncate a string at character count, regardless of length or punctuation.
* @param {string} str
* @param {integer} length Truncate length
* @param {string} trail Trailing string, false to remove
*/
export const truncate = (str, length = 50, trail = '...') => {
if (str.length < length) {
return str;
}
let pad = 0;
if (trail && trail.length) {
pad = trail.length;
}
let returnString = str.substr(0, (length - pad));
if (trail) {
returnString += trail;
}
return returnString;
}
/**
* Generate random alpha numeric string.
* **This is not cryptographically secure**
* @param {integer} Max length
*/
export const randomString = (len = 8) => {
const getToken = () => {
const src = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
const max = src.length;
return src[Math.floor(Math.random() * (max-1))];
};
let tok = getToken();
while (tok.length < len) {
tok = tok+getToken();
}
return tok.substring(0, len);
};
/**
* Reduce slashes in an escaped string.
* @param {string} str string to reduce
*/
export const reduceSlashes = (str) => {
return str.replace(/\\"/g, '"').replace(/\\{2,}/g, "\\");
};