import escapeStringRegExp from 'escape-string-regexp';
import {meta} from '../../hydration';
import {formatDataForPreview} from '../../utils';
import isArray from 'react-devtools-shared/src/isArray';
import type {HooksTree} from 'react-debug-tools/src/ReactDebugHooks';
const hasOwnProperty = Object.prototype.hasOwnProperty;
export function alphaSortEntries(
entryA: [string, mixed],
entryB: [string, mixed],
): number {
const a = entryA[0];
const b = entryB[0];
if (String(+a) === a) {
if (String(+b) !== b) {
return -1;
}
return +a < +b ? -1 : 1;
}
return a < b ? -1 : 1;
}
export function createRegExp(string: string): RegExp {
if (string[0] === '/') {
string = string.slice(1);
if (string[string.length - 1] === '/') {
string = string.slice(0, string.length - 1);
}
try {
return new RegExp(string, 'i');
} catch (err) {
return new RegExp('.^');
}
}
function isLetter(char: string) {
return char.toLowerCase() !== char.toUpperCase();
}
function matchAnyCase(char: string) {
if (!isLetter(char)) {
return char;
}
return '[' + char.toLowerCase() + char.toUpperCase() + ']';
}
const escaped = escapeStringRegExp(string);
const firstChar = escaped[0];
let restRegex = '';
for (let i = 1; i < escaped.length; i++) {
restRegex += matchAnyCase(escaped[i]);
}
if (!isLetter(firstChar)) {
return new RegExp(firstChar + restRegex);
}
return new RegExp(
'(^' +
matchAnyCase(firstChar) +
'|' +
firstChar.toUpperCase() +
')' +
restRegex,
);
}
export function getMetaValueLabel(data: Object): string | null {
if (hasOwnProperty.call(data, meta.preview_long)) {
return data[meta.preview_long];
} else {
return formatDataForPreview(data, true);
}
}
function sanitize(data: Object): void {
for (const key in data) {
const value = data[key];
if (value && value[meta.type]) {
data[key] = getMetaValueLabel(value);
} else if (value != null) {
if (isArray(value)) {
sanitize(value);
} else if (typeof value === 'object') {
sanitize(value);
}
}
}
}
export function serializeDataForCopy(props: Object): string {
const cloned = isArray(props) ? props.slice(0) : Object.assign({}, props);
sanitize(cloned);
try {
return JSON.stringify(cloned, null, 2);
} catch (error) {
return '';
}
}
export function serializeHooksForCopy(hooks: HooksTree | null): string {
const cloned = Object.assign(([]: Array<any>), hooks);
const queue = [...cloned];
while (queue.length > 0) {
const current = queue.pop();
delete current.id;
delete current.isStateEditable;
if (current.subHooks.length > 0) {
queue.push(...current.subHooks);
}
}
sanitize(cloned);
try {
return JSON.stringify(cloned, null, 2);
} catch (error) {
return '';
}
}
let downloadUrl = null;
export function downloadFile(
element: HTMLAnchorElement,
filename: string,
text: string,
): void {
const blob = new Blob([text], {type: 'text/plain;charset=utf-8'});
if (downloadUrl !== null) {
URL.revokeObjectURL(downloadUrl);
}
downloadUrl = URL.createObjectURL(blob);
element.setAttribute('href', downloadUrl);
element.setAttribute('download', filename);
element.click();
}
export function truncateText(text: string, maxLength: number): string {
const {length} = text;
if (length > maxLength) {
return (
text.slice(0, Math.floor(maxLength / 2)) +
'…' +
text.slice(length - Math.ceil(maxLength / 2) - 1)
);
} else {
return text;
}
}
export function pluralize(word: string): string {
if (!/^[a-z]+$/i.test(word)) {
return word;
}
switch (word) {
case 'men':
case 'women':
case 'children':
case 'feet':
case 'teeth':
case 'mice':
case 'people':
return word;
}
if (
/(ches|shes|ses|xes|zes)$/i.test(word) ||
/[^s]ies$/i.test(word) ||
/ves$/i.test(word) ||
/[^s]s$/i.test(word)
) {
return word;
}
switch (word) {
case 'man':
return 'men';
case 'woman':
return 'women';
case 'child':
return 'children';
case 'foot':
return 'feet';
case 'tooth':
return 'teeth';
case 'mouse':
return 'mice';
case 'person':
return 'people';
}
if (/(s|x|z|ch|sh)$/i.test(word)) return word + 'es';
if (/[bcdfghjklmnpqrstvwxz]y$/i.test(word)) return word.slice(0, -1) + 'ies';
if (/(?:f|fe)$/i.test(word)) return word.replace(/(?:f|fe)$/i, 'ves');
return word + 's';
}