serialize-as-code
Version:
Serialize any Javascript object as its source code
136 lines (106 loc) • 5.03 kB
JavaScript
const NOP = () => undefined;
const __getTypeOfObject = o => Object.prototype.toString.call(o).split(' ')[1].slice(0, -1);
const __serializeProp = (key, value, custom, serialized) => typeof value === 'string' ? `${key}="${value}"` : `${key}={${__serialize(value, custom, serialized)}}`;
const __serializeProps = (o, custom, serialized) => {
const elemProps = o.props;
const props = [];
Object.entries(elemProps).forEach(([k, v]) => {
if (v !== undefined && k !== 'children') props.push(__serializeProp(k, v, custom, serialized));
});
if (o.key) props.push(__serializeProp('key', o.key, custom, serialized));
if (o.ref) props.push(__serializeProp('ref', o.ref, custom, serialized));
if (!props.length) return '';
return ' ' + props.join(' ');
};
const __serializeChildren = (o, custom, serialized) => {
const children = o.props.children;
if (!children) return '';
if (typeof children === 'string') return children;
return Array.isArray(children) ? children.map(v => __serialize(v, custom, serialized)).join('') : __serialize(children, custom, serialized);
};
const __reactTypeNameReader = {
String: type => type,
Function: type => type.name,
Symbol: type => Symbol.keyFor(type) === 'react.fragment' && 'Fragment' || undefined
};
const getTypeName = type => (__reactTypeNameReader[__getTypeOfObject(type)] || NOP)(type);
const __serializeReactElement = (o, custom, serialized) => {
const type = getTypeName(o.type) || 'UNKNOWN';
const children = __serializeChildren(o, custom, serialized);
return `<${type}${__serializeProps(o, custom, serialized)}${children ? `>${children}</${type}>` : ' />'}`;
};
const __serializeReact = (o, custom, serialized) => {
const symbolKey = Symbol.keyFor(o.$$typeof);
switch (symbolKey) {
case 'react.element':
return __serializeReactElement(o, custom, serialized);
default:
return;
}
};
const __serializeIfReact = (o, custom, serialized) => {
if ('$$typeof' in o && Object.prototype.toString.call(o.$$typeof) === '[object Symbol]') {
const key = Symbol.keyFor(o.$$typeof);
if (key && key.indexOf('react.') === 0) return __serializeReact(o, custom, serialized);
}
};
const __serializerByType = {
BigInt: o => `${String(o)}n`,
RegExp: o => `/${String(o)}/`,
String: o => o.indexOf('"') === -1 && o.indexOf("'") !== -1 ? `"${o}"` : `'${o}'`,
Function: o => o.name || 'Function',
AsyncFunction: o => o.name || 'AsyncFunction',
Date: o => `new Date(${Number(o)})`,
Number: o => String(o),
Boolean: o => String(o),
Set: o => `new Set(${__serializeArray([...o.keys()], undefined, [])})`,
Map: o => `new Map(${__serializeArray([...o.entries()], undefined, [])})`,
Symbol: o => Symbol.keyFor(o) === undefined ? o.toString() : `Symbol.for('${Symbol.keyFor(o)}')`,
Error: o => `new ${o.name}('${o.message}')`,
Window: () => `window`,
Document: () => `document`
};
const __serializeArray = (o, custom, serialized) => {
const results = [];
for (let i = 0; i < o.length; i++) {
results.push(__serialize(o[i], custom, serialized));
}
return `[${results.join(', ')}]`;
};
const __serializeOptArray = (o, custom, serialized) => {
if (Array.isArray(o)) return __serializeArray(o, custom, serialized);
};
const __serializeHTML = o => {
var _o$constructor;
const objectType = (_o$constructor = o.constructor) == null ? void 0 : _o$constructor.name;
if (/^HTML[a-zA-Z]*Element$/.test(objectType)) return objectType;
};
const __serializeObject = (o, custom, serialized) => {
var _o$constructor2;
const oKeys = Object.keys(o);
oKeys.sort();
const results = [];
for (let i = 0; i < oKeys.length; i++) {
const key = oKeys[i];
results.push(`${key}: ${__serialize(o[key], custom, serialized)}`);
}
const objectType = (_o$constructor2 = o.constructor) == null ? void 0 : _o$constructor2.name;
const displayedType = objectType === 'Object' ? '' : objectType;
return `${displayedType}{${results.join(', ')}}`;
};
const Serialize = {
custom: (o, custom) => custom && custom(o),
undefOrNull: o => o === undefined && 'undefined' || o === null && 'null' || undefined,
flat: o => (__serializerByType[__getTypeOfObject(o)] || NOP)(o),
cyclomatic: (o, _, serialized) => serialized.indexOf(o) !== -1 && '>CYCLOMATIC<' || undefined,
react: __serializeIfReact,
array: __serializeOptArray,
HTML: __serializeHTML
};
const __serialize = (o, custom, serialized) => Serialize.custom(o, custom, serialized) || Serialize.undefOrNull(o, custom, serialized) || Serialize.flat(o, custom, serialized) || Serialize.cyclomatic(o, custom, serialized) || (nextSerialized => Serialize.react(o, custom, nextSerialized) || Serialize.array(o, custom, nextSerialized) || Serialize.HTML(o, custom, nextSerialized) || __serializeObject(o, custom, nextSerialized))([...serialized, o]);
const _serialize = (o, custom) => __serialize(o, custom, []);
const Serializer = {
run: o => _serialize(o),
create: custom => o => _serialize(o, custom)
};
export { Serializer };