1.1.0 • Published 1 month ago
@slightning/anything-to-string v1.1.0
Anything To String
Converts anything in JavaScript/TypeScript to a string with detailed formatting options.
Supported Types
- Primitives:
null
,undefined
,string
,number
,boolean
- Object Wrappers:
String
,Number
,Boolean
- Special Objects:
RegExp
,Symbol
,BigInt
- Collections:
Set
,Map
,WeakRef
- Errors:
Error
and all its subclasses - DOM:
HTMLElement
- Complex Types:
Array
,Object
,Function
(including arrow functions and classes)
Installation
npm install @slightning/anything-to-string
# or
yarn add @slightning/anything-to-string
Use
const { stringify } = require("@slightning/anything-to-string")
const basicObject = {
null: null,
undefined: undefined,
string: "string",
number: 1,
boolean: true,
String: new String("test"),
Number: new Number(1),
Boolean: new Boolean(true),
RegExp: /test/g,
[Symbol("Key")]: Symbol("Symbol"),
bigint: BigInt("10000000000000000000000000000000000000000000000000000000000000000"),
Set: new Set(),
Map: new Map(),
WeakRef: new WeakRef({}),
Error: new Error("test"),
Array: [,],
object: {},
get test() { return "value from getter" },
set test(value) { console.log("set value: " + value) }
}
Object.defineProperty(basicObject, "ref", {
value: basicObject
})
const data = {
null: null,
undefined: undefined,
string: "string",
number: 1,
boolean: true,
String: new String("test"),
Number: new Number(1),
Boolean: new Boolean(true),
RegExp: /test/g,
[Symbol("Key")]: Symbol("Symbol"),
bigint: BigInt("10000000000000000000000000000000000000000000000000000000000000000"),
Set: new Set(Object.values(basicObject)),
Map: new Map(Object.entries(basicObject)),
WeakRef: new WeakRef(basicObject),
Error: new Error("test"),
Array: Object.values(basicObject),
object: basicObject,
get test() { return "value from getter" },
set test(value) { console.log("set value: " + value) }
}
Object.defineProperty(data, "ref", {
value: data
})
console.log(stringify(data))
Output
<ref *2> Object {
null: null
undefined: undefined
string: [string: "string"]
number: [number: 1]
boolean: [boolean: true]
String: String("test") String {
length: 4
}
Number: Number(1) {}
Boolean: Boolean(true) {}
RegExp: RegExp(/test/g) RegExp {
lastIndex: 0
}
bigint: [bigint: 10000000000000000000000000000000000000000000000000000000000000000]
Set: Set {
[[Values]]:
0: null
1: undefined
2: "string"
3: 1
4: true
5: String("test")
6: Number(1)
7: Boolean(true)
8: RegExp(/test/g)
9: 10000000000000000000000000000000000000000000000000000000000000000
10: Set {
[[Values]]: None
}
11: Map {
[[Entries]]: None
}
12: WeakRef {
[[WeakRefTarget]]: [object Object]
}
13: Error: test
14: [
None
]
15: {}
16: "value from getter"
}
Map: Map {
[[Entries]]:
0:
key: "null"
value: null
1:
key: "undefined"
value: undefined
2:
key: "string"
value: "string"
3:
key: "number"
value: 1
4:
key: "boolean"
value: true
5:
key: "String"
value: String("test")
6:
key: "Number"
value: Number(1)
7:
key: "Boolean"
value: Boolean(true)
8:
key: "RegExp"
value: RegExp(/test/g)
9:
key: "bigint"
value: 10000000000000000000000000000000000000000000000000000000000000000
10:
key: "Set"
value: Set {
[[Values]]: None
}
11:
key: "Map"
value: Map {
[[Entries]]: None
}
12:
key: "WeakRef"
value: WeakRef {
[[WeakRefTarget]]: [object Object]
}
13:
key: "Error"
value: Error: test
14:
key: "Array"
value: [
None
]
15:
key: "object"
value: {}
16:
key: "test"
value: "value from getter"
}
WeakRef: WeakRef {
[[WeakRefTarget]]: <ref *1> Object {
null: null
undefined: undefined
string: "string"
number: 1
boolean: true
String: "test"
Number: 1
Boolean: true
RegExp: /test/g
bigint: 10000000000000000000000000000000000000000000000000000000000000000
Set: Set(0)
Map: Map(0)
WeakRef: [WeakRef]
Error: [Error]
Array: Array(1)
object: [object Object]
}
}
Error: Error: test
at <anonymous>:1:1
Array: Array {
0: null
1: undefined
2: "string"
3: 1
4: true
5: String("test")
6: Number(1)
7: Boolean(true)
8: RegExp(/test/g)
9: 10000000000000000000000000000000000000000000000000000000000000000
10: Set {
[[Values]]: None
}
11: Map {
[[Entries]]: None
}
12: WeakRef {
[[WeakRefTarget]]: [object Object]
}
13: Error: test
14: [
None
]
15: {}
16: "value from getter"
length: 17
}
object: [Circular *1]
test: [string: "value from getter"]
ref: [Circular *2]
[Symbol(Key)]: Symbol(Symbol)
get test: get test() {
return "value from getter";
}
set test: set test(value) {
console.log("set value: " + value);
}
[[Prototype]]: Object {
constructor: function Object() { [native code] }
__defineGetter__: function __defineGetter__() { [native code] }
__defineSetter__: function __defineSetter__() { [native code] }
hasOwnProperty: function hasOwnProperty() { [native code] }
__lookupGetter__: function __lookupGetter__() { [native code] }
__lookupSetter__: function __lookupSetter__() { [native code] }
isPrototypeOf: function isPrototypeOf() { [native code] }
propertyIsEnumerable: function propertyIsEnumerable() { [native code] }
toString: function toString() { [native code] }
valueOf: function valueOf() { [native code] }
__proto__: null
toLocaleString: function toLocaleString() { [native code] }
}
}
Config
Let's continue with the above example and make the following modifications:
- const { stringify } = require("@slightning/anything-to-string")
+ const { stringify, Rules } = require("@slightning/anything-to-string")
const basicObject = {
null: null,
undefined: undefined,
...
Object.defineProperty(data, "ref", {
value: data
})
- console.log(stringify(data))
+ console.log(stringify(data, {
+ rules: Rules.LESSER, // Rule set, Rules.LESSER keeps less information
+ depth: 0 // Maximum depth limit, '0' means no limit
+ }))
Output
Object {
null: null
undefined: undefined
string: "string"
number: 1
boolean: true
String: String("test")
Number: Number(1)
Boolean: Boolean(true)
RegExp: RegExp(/test/g)
bigint: 10000000000000000000000000000000000000000000000000000000000000000
Set: Set {
[[Values]]:
0: null
1: undefined
2: "string"
3: 1
4: true
5: String("test")
6: Number(1)
7: Boolean(true)
8: RegExp(/test/g)
9: 10000000000000000000000000000000000000000000000000000000000000000
10: Set {
[[Values]]: None
}
11: Map {
[[Entries]]: None
}
12: WeakRef {
[[WeakRefTarget]]: {}
}
13: Error: test
14: [
None
]
15: {}
16: "value from getter"
}
Map: Map {
[[Entries]]:
"null": null
"undefined": undefined
"string": "string"
"number": 1
"boolean": true
"String": String("test")
"Number": Number(1)
"Boolean": Boolean(true)
"RegExp": RegExp(/test/g)
"bigint": 10000000000000000000000000000000000000000000000000000000000000000
"Set": Set {
[[Values]]: None
}
"Map": Map {
[[Entries]]: None
}
"WeakRef": WeakRef {
[[WeakRefTarget]]: {}
}
"Error": Error: test
"Array": [
None
]
"object": {}
"test": "value from getter"
}
WeakRef: WeakRef {
[[WeakRefTarget]]: Object {
null: null
undefined: undefined
string: "string"
number: 1
boolean: true
String: String("test")
Number: Number(1)
Boolean: Boolean(true)
RegExp: RegExp(/test/g)
bigint: 10000000000000000000000000000000000000000000000000000000000000000
Set: Set {
[[Values]]: None
}
Map: Map {
[[Entries]]: None
}
WeakRef: WeakRef {
[[WeakRefTarget]]: {}
}
Error: Error: test
Array: [
None
]
object: {}
}
}
Error: Error: test
Array: [
null,
undefined,
"string",
1,
true,
String("test"),
Number(1),
Boolean(true),
RegExp(/test/g),
10000000000000000000000000000000000000000000000000000000000000000,
Set {
[[Values]]: None
},
Map {
[[Entries]]: None
},
WeakRef {
[[WeakRefTarget]]: {}
},
Error: test,
[
None
],
{},
"value from getter"
]
object: Object {
null: null
undefined: undefined
string: "string"
number: 1
boolean: true
String: String("test")
Number: Number(1)
Boolean: Boolean(true)
RegExp: RegExp(/test/g)
bigint: 10000000000000000000000000000000000000000000000000000000000000000
Set: Set {
[[Values]]: None
}
Map: Map {
[[Entries]]: None
}
WeakRef: WeakRef {
[[WeakRefTarget]]: {}
}
Error: Error: test
Array: [
None
]
object: {}
}
}
rules
The rule defines how to turn an object into a string. Default rules include Rules.MINIMUM, Rules.LESSER, Rules.MAJOR, Rules.MAXIMUM. Their names represent the level of detail in which information is retained.
Example:
const { stringify, Rules } = require("@slightning/anything-to-string")
function test() {
console.log("hello")
}
console.log(stringify(test, {
rules: Rules.MINIMUM
}))
// output: [Function: test]
console.log(stringify(test, {
rules: Rules.LESSER
}))
// output: function test() { console.log("hello") }
console.log(stringify(test, {
rules: Rules.MAJOR
}))
// output:
// function test() {
// console.log("hello")
// }
console.log(stringify(test, {
rules: Rules.MAXIMUM
}))
// (lots of output)
Custom Rule
const { stringify, Rules } = require("@slightning/anything-to-string")
console.log(stringify("data", {
rules: [
new class {
test(data) {
return typeof data == "string" // Apply rule for strings
}
toString(data, config) {
return config.ignoreString ? "" : JSON.stringify(data)
}
}, ...Rules.LESSER
],
ignoreString: true // Custom config
}))
// output: (nothing)
tips:
You may need to add a .d.ts
file to your project to declare the custom config type.
declare module "@slightning/anything-to-string" {
interface Config {
ignoreString?: boolean
}
}
If you want to use existing rules in your custom rule, you can use AnythingRule
.
const { stringify, Rules, AnythingRule } = require("@slightning/anything-to-string")
class Ref {
constructor(value) {
this.value = value
}
}
console.log(stringify("data", {
rules: [
new class {
test(data) {
return data instanceof Ref // Apply rule for Ref
},
// Ref may contain circular reference.
// To handle circular reference, you need to prepare the value first.
// Just call `prepare` method of `AnythingRule` to prepare the value.
prepare(data, config, context) {
new AnythingRule().prepare(data.value, config, context)
},
toString(data, config, context) {
return "Ref(" + new AnythingRule().toString(data.value, config, context) + ")"
}
}, ...Rules.LESSER
]
}))
// output: Ref("data")
indent
The number of indented Spaces or indented string. Default is 4.
const { stringify, Rules } = require("@slightning/anything-to-string")
console.log(stringify(["data"], {
rules: Rules.LESSER,
indent: 2
}))
// output:
// Array [
// "data"
// ]
console.log(stringify(["data"], {
rules: Rules.LESSER,
indent: "|--|"
}))
// output:
// Array [
// |--|"data"
// ]
depth
Maximum recursion depth.
object
unenumerable
: Include non-enumerable attributes.symbol
: Include properties with symbol as keys.get
: Include computed attribute.getter
: Include getter.setter
: Include setter.prototype
: Include prototype.exclude
: Exclude properties with the specified names or symbols.
Example
const { stringify, Rules } = require("@slightning/anything-to-string")
console.log(stringify({
get a() {
return "value from getter"
},
[Symbol("symbol")]: "value"
}, {
rules: Rules.LESSER,
object: {
symbol: true,
get: true,
getter: true,
prototype: true
}
}))
// output:
// Object {
// a: "value from getter"
// [Symbol(symbol)]: "value"
// get a: get a() { return "value from getter" }
// [[Prototype]]: Object {
// [[Prototype]]: null
// }
// }