UNPKG

mic-inspector

Version:

A react inspector which a most similar of Chorme DevTools inspector

112 lines (111 loc) 4.29 kB
import React, { useMemo } from 'react'; import { DescriptorValueType, DescriptorNameType } from '../named-descriptor/types'; import { Property } from '../property'; import { ObjectValueSeparator } from './types'; import { getNamedDescriptors } from '../named-descriptor/locale'; import { isObjectOrFunction } from '../property-value/locale'; export const { Object, Node } = window; export const arraylikeMethodNames = [...(!window.Symbol ? [] : [Symbol.iterator]), 'entries', 'forEach', 'item', 'keys', 'splice', 'values']; /** * Returns a string represents object name * @param value An object * @param isNode A boolean represents whether the object is a node */ export const getObjectName = (value, isNode) => { // if the object is a node if (isNode) { try { const nodeName = value.nodeName.toLocaleLowerCase(); return nodeName[0] === '#' ? nodeName.substring(1) : nodeName; } catch (e) { } } const constructor = value === null || value === void 0 ? void 0 : value.constructor; return constructor === Object && value !== Object.prototype ? '' : constructor === null || constructor === void 0 ? void 0 : constructor.name; }; /** * A method to fitler object subs * @param param0 A descriptor of the object * @param arraylike A boolean represents whether the object is an array */ export const objectSubsFilter = ({ get, set, nameType, valueType, value, enumerable }, arraylike) => { // if the object is an array if (arraylike) { return (nameType & DescriptorNameType.Index) === DescriptorNameType.Index; } // if the accessors existed if (get || set) { return false; } switch (true) { case (valueType & DescriptorValueType.Normal) === DescriptorValueType.Normal: case (valueType & DescriptorValueType.Result) === DescriptorValueType.Result: break; default: return false; } return !isObjectOrFunction(value) || enumerable; }; /** * A method to render object subs * @param object The object value * @param arraylike A boolean represents whether the object is an array * @param maxPropertyLength A number represents the length of object properties to preview */ export const renderObjectSubs = (object, arraylike, maxPropertyLength = 5) => { const objectSubs = []; // for each descriptors for (const descriptor of getNamedDescriptors(object)) { const { length } = objectSubs; // if the length is greater than maxPropertyLength * 2 if (length >= maxPropertyLength * 2) { break; } // if descriptor has filtered if (!objectSubsFilter(descriptor, arraylike)) { continue; } objectSubs.push(React.createElement(Property, { key: length, descriptor: descriptor, preview: true }), React.createElement("i", { key: length + 1, "data-separator": ObjectValueSeparator.Comma }, ",")); } // if the length of subs is less than maxPropertyLength * 2 if (objectSubs.length < maxPropertyLength * 2) { // remove the last one that the comma element objectSubs.splice(objectSubs.length - 1, 1); } else { objectSubs.push(React.createElement("i", { key: objectSubs.length + 1, "data-separator": ObjectValueSeparator.Spread }, "...")); } return objectSubs; }; /** * Get the array info * @param value An object that maybe is an array */ export const useArrayInfo = (value) => { return useMemo(() => { tryBlock: try { // if the object is an array if (Array.isArray(value)) { break tryBlock; } // the the length property in the object if ('length' in value) { // for each array method names for (const name of arraylikeMethodNames) { // if this method is a function if (typeof value[name] === 'function') { break tryBlock; } } } return [false, 0]; } catch (e) { } let length = 0; try { length = value.length; } catch (e) { } return [true, length]; }, [value]); };