You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					132 lines
				
				3.3 KiB
			
		
		
			
		
	
	
					132 lines
				
				3.3 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								const isRegexp = require('is-regexp');
							 | 
						||
| 
								 | 
							
								const isObj = require('is-obj');
							 | 
						||
| 
								 | 
							
								const getOwnEnumPropSymbols = require('get-own-enumerable-property-symbols').default;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = (val, opts, pad) => {
							 | 
						||
| 
								 | 
							
									const seen = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return (function stringify(val, opts, pad) {
							 | 
						||
| 
								 | 
							
										opts = opts || {};
							 | 
						||
| 
								 | 
							
										opts.indent = opts.indent || '\t';
							 | 
						||
| 
								 | 
							
										pad = pad || '';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										let tokens;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (opts.inlineCharacterLimit === undefined) {
							 | 
						||
| 
								 | 
							
											tokens = {
							 | 
						||
| 
								 | 
							
												newLine: '\n',
							 | 
						||
| 
								 | 
							
												newLineOrSpace: '\n',
							 | 
						||
| 
								 | 
							
												pad,
							 | 
						||
| 
								 | 
							
												indent: pad + opts.indent
							 | 
						||
| 
								 | 
							
											};
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
											tokens = {
							 | 
						||
| 
								 | 
							
												newLine: '@@__STRINGIFY_OBJECT_NEW_LINE__@@',
							 | 
						||
| 
								 | 
							
												newLineOrSpace: '@@__STRINGIFY_OBJECT_NEW_LINE_OR_SPACE__@@',
							 | 
						||
| 
								 | 
							
												pad: '@@__STRINGIFY_OBJECT_PAD__@@',
							 | 
						||
| 
								 | 
							
												indent: '@@__STRINGIFY_OBJECT_INDENT__@@'
							 | 
						||
| 
								 | 
							
											};
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										const expandWhiteSpace = string => {
							 | 
						||
| 
								 | 
							
											if (opts.inlineCharacterLimit === undefined) {
							 | 
						||
| 
								 | 
							
												return string;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const oneLined = string
							 | 
						||
| 
								 | 
							
												.replace(new RegExp(tokens.newLine, 'g'), '')
							 | 
						||
| 
								 | 
							
												.replace(new RegExp(tokens.newLineOrSpace, 'g'), ' ')
							 | 
						||
| 
								 | 
							
												.replace(new RegExp(tokens.pad + '|' + tokens.indent, 'g'), '');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (oneLined.length <= opts.inlineCharacterLimit) {
							 | 
						||
| 
								 | 
							
												return oneLined;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return string
							 | 
						||
| 
								 | 
							
												.replace(new RegExp(tokens.newLine + '|' + tokens.newLineOrSpace, 'g'), '\n')
							 | 
						||
| 
								 | 
							
												.replace(new RegExp(tokens.pad, 'g'), pad)
							 | 
						||
| 
								 | 
							
												.replace(new RegExp(tokens.indent, 'g'), pad + opts.indent);
							 | 
						||
| 
								 | 
							
										};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (seen.indexOf(val) !== -1) {
							 | 
						||
| 
								 | 
							
											return '"[Circular]"';
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (val === null ||
							 | 
						||
| 
								 | 
							
											val === undefined ||
							 | 
						||
| 
								 | 
							
											typeof val === 'number' ||
							 | 
						||
| 
								 | 
							
											typeof val === 'boolean' ||
							 | 
						||
| 
								 | 
							
											typeof val === 'function' ||
							 | 
						||
| 
								 | 
							
											typeof val === 'symbol' ||
							 | 
						||
| 
								 | 
							
											isRegexp(val)) {
							 | 
						||
| 
								 | 
							
											return String(val);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (val instanceof Date) {
							 | 
						||
| 
								 | 
							
											return `new Date('${val.toISOString()}')`;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (Array.isArray(val)) {
							 | 
						||
| 
								 | 
							
											if (val.length === 0) {
							 | 
						||
| 
								 | 
							
												return '[]';
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											seen.push(val);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const ret = '[' + tokens.newLine + val.map((el, i) => {
							 | 
						||
| 
								 | 
							
												const eol = val.length - 1 === i ? tokens.newLine : ',' + tokens.newLineOrSpace;
							 | 
						||
| 
								 | 
							
												let value = stringify(el, opts, pad + opts.indent);
							 | 
						||
| 
								 | 
							
												if (opts.transform) {
							 | 
						||
| 
								 | 
							
													value = opts.transform(val, i, value);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												return tokens.indent + value + eol;
							 | 
						||
| 
								 | 
							
											}).join('') + tokens.pad + ']';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											seen.pop();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return expandWhiteSpace(ret);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (isObj(val)) {
							 | 
						||
| 
								 | 
							
											let objKeys = Object.keys(val).concat(getOwnEnumPropSymbols(val));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (opts.filter) {
							 | 
						||
| 
								 | 
							
												objKeys = objKeys.filter(el => opts.filter(val, el));
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (objKeys.length === 0) {
							 | 
						||
| 
								 | 
							
												return '{}';
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											seen.push(val);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											const ret = '{' + tokens.newLine + objKeys.map((el, i) => {
							 | 
						||
| 
								 | 
							
												const eol = objKeys.length - 1 === i ? tokens.newLine : ',' + tokens.newLineOrSpace;
							 | 
						||
| 
								 | 
							
												const isSymbol = typeof el === 'symbol';
							 | 
						||
| 
								 | 
							
												const isClassic = !isSymbol && /^[a-z$_][a-z$_0-9]*$/i.test(el);
							 | 
						||
| 
								 | 
							
												const key = isSymbol || isClassic ? el : stringify(el, opts);
							 | 
						||
| 
								 | 
							
												let value = stringify(val[el], opts, pad + opts.indent);
							 | 
						||
| 
								 | 
							
												if (opts.transform) {
							 | 
						||
| 
								 | 
							
													value = opts.transform(val, el, value);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												return tokens.indent + String(key) + ': ' + value + eol;
							 | 
						||
| 
								 | 
							
											}).join('') + tokens.pad + '}';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											seen.pop();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return expandWhiteSpace(ret);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										val = String(val).replace(/[\r\n]/g, x => x === '\n' ? '\\n' : '\\r');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (opts.singleQuotes === false) {
							 | 
						||
| 
								 | 
							
											val = val.replace(/"/g, '\\"');
							 | 
						||
| 
								 | 
							
											return `"${val}"`;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										val = val.replace(/\\?'/g, '\\\'');
							 | 
						||
| 
								 | 
							
										return `'${val}'`;
							 | 
						||
| 
								 | 
							
									})(val, opts, pad);
							 | 
						||
| 
								 | 
							
								};
							 |