x-render / docs /playground /serialize.js
AbdulElahGwaith's picture
Upload folder using huggingface_hub
c9d0005 verified
Raw
History Blame Contribute Delete
9.61 kB
/*
Copyright (c) 2014, Yahoo! Inc. All rights reserved.
Copyrights licensed under the New BSD License.
See the accompanying LICENSE file for terms.
*/
// fork自https://github.com/yahoo/serialize-javascript.git,新增 ignoreUndefined 参数的支持
import { customAlphabet } from 'nanoid';
const nanoid = customAlphabet('1234567890abcdef');
// Generate an internal UID to make the regexp pattern harder to guess.
var UID = nanoid(32);
var PLACE_HOLDER_REGEXP = new RegExp(
'(\\\\)?"@__(F|R|D|M|S|A|U|I|B|L)-' + UID + '-(\\d+)__@"',
'g'
);
var IS_NATIVE_CODE_REGEXP = /\{\s*\[native code\]\s*\}/g;
var IS_PURE_FUNCTION = /function.*?\(/;
var IS_ARROW_FUNCTION = /.*?=>.*?/;
var UNSAFE_CHARS_REGEXP = /[<>\/\u2028\u2029]/g;
var RESERVED_SYMBOLS = ['*', 'async'];
// Mapping of unsafe HTML and invalid JavaScript line terminator chars to their
// Unicode char counterparts which are safe to use in JavaScript strings.
var ESCAPED_CHARS = {
'<': '\\u003C',
'>': '\\u003E',
'/': '\\u002F',
'\u2028': '\\u2028',
'\u2029': '\\u2029',
};
function escapeUnsafeChars(unsafeChar) {
return ESCAPED_CHARS[unsafeChar];
}
function deleteFunctions(obj) {
var functionKeys = [];
for (var key in obj) {
if (typeof obj[key] === 'function') {
functionKeys.push(key);
}
}
for (var i = 0; i < functionKeys.length; i++) {
delete obj[functionKeys[i]];
}
}
function deleteUndefined(obj) {
var undefinedKeys = [];
for (var key in obj) {
if (typeof obj[key] === 'undefined') {
undefinedKeys.push(key);
}
}
for (var i = 0; i < undefinedKeys.length; i++) {
delete obj[undefinedKeys[i]];
}
}
function serializeUtil(obj, options) {
options || (options = {});
// Backwards-compatibility for `space` as the second argument.
if (typeof options === 'number' || typeof options === 'string') {
options = { space: options };
}
var functions = [];
var regexps = [];
var dates = [];
var maps = [];
var sets = [];
var arrays = [];
var undefs = [];
var infinities = [];
var bigInts = [];
var urls = [];
// Returns placeholders for functions and regexps (identified by index)
// which are later replaced by their string representation.
function replacer(key, value) {
// For nested function
if (options.ignoreFunction) {
deleteFunctions(value);
}
if (options.ignoreUndefined) {
deleteUndefined(value);
}
if (!value && value !== undefined) {
return value;
}
// If the value is an object w/ a toJSON method, toJSON is called before
// the replacer runs, so we use this[key] to get the non-toJSONed value.
var origValue = this[key];
var type = typeof origValue;
if (type === 'object') {
if (origValue instanceof RegExp) {
return '@__R-' + UID + '-' + (regexps.push(origValue) - 1) + '__@';
}
if (origValue instanceof Date) {
return '@__D-' + UID + '-' + (dates.push(origValue) - 1) + '__@';
}
if (origValue instanceof Map) {
return '@__M-' + UID + '-' + (maps.push(origValue) - 1) + '__@';
}
if (origValue instanceof Set) {
return '@__S-' + UID + '-' + (sets.push(origValue) - 1) + '__@';
}
if (origValue instanceof Array) {
var isSparse =
origValue.filter(function () {
return true;
}).length !== origValue.length;
if (isSparse) {
return '@__A-' + UID + '-' + (arrays.push(origValue) - 1) + '__@';
}
}
if (origValue instanceof URL) {
return '@__L-' + UID + '-' + (urls.push(origValue) - 1) + '__@';
}
}
if (type === 'function') {
return '@__F-' + UID + '-' + (functions.push(origValue) - 1) + '__@';
}
if (type === 'undefined') {
return '@__U-' + UID + '-' + (undefs.push(origValue) - 1) + '__@';
}
if (type === 'number' && !isNaN(origValue) && !isFinite(origValue)) {
return '@__I-' + UID + '-' + (infinities.push(origValue) - 1) + '__@';
}
if (type === 'bigint') {
return '@__B-' + UID + '-' + (bigInts.push(origValue) - 1) + '__@';
}
return value;
}
function serializeFunc(fn) {
var serializedFn = fn.toString();
if (IS_NATIVE_CODE_REGEXP.test(serializedFn)) {
throw new TypeError('Serializing native function: ' + fn.name);
}
// pure functions, example: {key: function() {}}
if (IS_PURE_FUNCTION.test(serializedFn)) {
return serializedFn;
}
// arrow functions, example: arg1 => arg1+5
if (IS_ARROW_FUNCTION.test(serializedFn)) {
return serializedFn;
}
var argsStartsAt = serializedFn.indexOf('(');
var def = serializedFn
.substr(0, argsStartsAt)
.trim()
.split(' ')
.filter(function (val) {
return val.length > 0;
});
var nonReservedSymbols = def.filter(function (val) {
return RESERVED_SYMBOLS.indexOf(val) === -1;
});
// enhanced literal objects, example: {key() {}}
if (nonReservedSymbols.length > 0) {
return (
(def.indexOf('async') > -1 ? 'async ' : '') +
'function' +
(def.join('').indexOf('*') > -1 ? '*' : '') +
serializedFn.substr(argsStartsAt)
);
}
// arrow functions
return serializedFn;
}
// Check if the parameter is function
if (options.ignoreFunction && typeof obj === 'function') {
obj = undefined;
}
// Protects against `JSON.stringify()` returning `undefined`, by serializing
// to the literal string: "undefined".
if (obj === undefined) {
return String(obj);
}
var str;
// Creates a JSON string representation of the value.
// NOTE: Node 0.12 goes into slow mode with extra JSON.stringify() args.
if (options.isJSON && !options.space) {
str = JSON.stringify(obj);
} else {
str = JSON.stringify(obj, options.isJSON ? null : replacer, options.space);
}
// Protects against `JSON.stringify()` returning `undefined`, by serializing
// to the literal string: "undefined".
if (typeof str !== 'string') {
return String(str);
}
// Replace unsafe HTML and invalid JavaScript line terminator chars with
// their safe Unicode char counterpart. This _must_ happen before the
// regexps and functions are serialized and added back to the string.
if (options.unsafe !== true) {
str = str.replace(UNSAFE_CHARS_REGEXP, escapeUnsafeChars);
}
if (
functions.length === 0 &&
regexps.length === 0 &&
dates.length === 0 &&
maps.length === 0 &&
sets.length === 0 &&
arrays.length === 0 &&
undefs.length === 0 &&
infinities.length === 0 &&
bigInts.length === 0 &&
urls.length === 0
) {
return str;
}
// Replaces all occurrences of function, regexp, date, map and set placeholders in the
// JSON string with their string representations. If the original value can
// not be found, then `undefined` is used.
return str.replace(
PLACE_HOLDER_REGEXP,
function (match, backSlash, type, valueIndex) {
// The placeholder may not be preceded by a backslash. This is to prevent
// replacing things like `"a\"@__R-<UID>-0__@"` and thus outputting
// invalid JS.
if (backSlash) {
return match;
}
if (type === 'D') {
return 'new Date("' + dates[valueIndex].toISOString() + '")';
}
if (type === 'R') {
return (
'new RegExp(' +
serialize(regexps[valueIndex].source) +
', "' +
regexps[valueIndex].flags +
'")'
);
}
if (type === 'M') {
return (
'new Map(' +
serialize(Array.from(maps[valueIndex].entries()), options) +
')'
);
}
if (type === 'S') {
return (
'new Set(' +
serialize(Array.from(sets[valueIndex].values()), options) +
')'
);
}
if (type === 'A') {
return (
'Array.prototype.slice.call(' +
serialize(
Object.assign(
{ length: arrays[valueIndex].length },
arrays[valueIndex]
),
options
) +
')'
);
}
if (type === 'U') {
return 'undefined';
}
if (type === 'I') {
return infinities[valueIndex];
}
if (type === 'B') {
return 'BigInt("' + bigInts[valueIndex] + '")';
}
if (type === 'L') {
return 'new URL("' + urls[valueIndex].toString() + '")';
}
var fn = functions[valueIndex];
return serializeFunc(fn);
}
);
}
/**
* @description 使用serialize-javascript进行序列化,替代JSON.stringify()
* @description 组件rules里面会存储一些validator函数,如果用JSON.stringify提交给接口会丢失
* @param {*} obj 传入需要序列化的值
* @returns 序列化后的值
*/
function serialize(obj) {
return serializeUtil(obj, {
ignoreUndefined: true,
});
}
/**
* @description 序列化成编辑器需要的展示格式
* @param {*} obj 传入需要序列化的值
* @return {*} 序列化后的值
*/
function serializeToDraft(obj) {
return serializeUtil(obj, {
space: 2,
ignoreUndefined: true,
});
}
/**
* @description 对serialize-javascript序列化后的值进行反序列化化
* @param {*} serializedJavascript 反序列化后的值
* @returns
*/
function deserialize(serializedJavascript) {
return new Function('return ' + serializedJavascript)();
}
export { deserialize, serialize, serializeToDraft, serializeUtil };