@parischap/pretty-print
Version:
A functional library to pretty-print and treeify objects
487 lines • 24.1 kB
JavaScript
/**
* This module implements the options for pretty-printing.
*
* With the make function, you can define your own instances if the provided ones don't suit your
* needs.
*/
import { ASText } from '@parischap/ansi-styles';
import { MCache, MFunction, MMatch, MString, MStruct, MTree, MTypes } from '@parischap/effect-lib';
import { Array, Either, flow, Function, HashMap, HashSet, MutableHashMap, Number, Option, pipe, SortedMap, SortedSet, Struct, Tuple } from 'effect';
import { MInspectable, MPipeable } from '@parischap/effect-lib';
import { Equal, Hash, Predicate } from 'effect';
import * as PPByPasser from './ByPasser.js';
import * as PPByPassers from './ByPassers.js';
import * as PPMarkMap from './MarkMap.js';
import * as PPMarkShowerConstructor from './MarkShowerConstructor.js';
import * as PPNonPrimitiveFormatter from './NonPrimitiveFormatter.js';
import * as PPPrimitiveFormatter from './PrimitiveFormatter.js';
import * as PPPropertyFilters from './PropertyFilters.js';
import * as PPPropertyFormatter from './PropertyFormatter.js';
import * as PPStringifiedValue from './StringifiedValue.js';
import * as PPStyleMap from './StyleMap.js';
import * as PPValue from './Value.js';
import * as PPValueBasedStylerConstructor from './ValueBasedStylerConstructor.js';
import * as PPValues from './Values.js';
/**
* Module tag
*
* @category Models
*/
export const moduleTag = '@parischap/pretty-print/Option/';
const _TypeId = /*#__PURE__*/Symbol.for(moduleTag);
/**
* Namespace for the possible sources of properties for non-primitive values
*
* @category Models
*/
export var PropertySource;
(function (PropertySource) {
/**
* Type of a PropertySource
*
* @category Models
*/
let Type;
(function (Type) {
/**
* Properties are obtained by calling Reflect.getOwnProperties on the non-primitive-value and
* its prototypes (until maxPrototypeDepth is reached). This is usually a good choice for
* records
*/
Type[Type["FromProperties"] = 0] = "FromProperties";
/**
* Properties are obtained by iterating over the non-primitive-value that must implement the
* Iterable protocol. Each value returned by the iterator is used to create a property with an
* auto-incremented numerical key (converted to a string). This is usually a good choice for
* arrays and sets.
*/
Type[Type["FromValueIterable"] = 1] = "FromValueIterable";
/**
* Properties are obtained by iterating over the non-primitive-value that must implement the
* Iterable protocol. The iterator must return a key/value pair. Otherwise, the returned value
* is ignored. This is usually a good choice for maps,...
*/
Type[Type["FromKeyValueIterable"] = 2] = "FromKeyValueIterable";
})(Type = PropertySource.Type || (PropertySource.Type = {}));
})(PropertySource || (PropertySource = {}));
/**
* Namespace for the options regarding the display of the number of properties of a non-primitive
* value. The number of properties is shown in between parentheses just after the non-primitive
* value id.
*
* @category Models
*/
export var PropertyNumberDisplayOption;
(function (PropertyNumberDisplayOption) {
/**
* Type of a PropertyNumberDisplayOption
*
* @category Models
*/
let Type;
(function (Type) {
/** The number of properties is not shown */
Type[Type["None"] = 0] = "None";
/** Shows the number of properties retrieved from the property source */
Type[Type["All"] = 1] = "All";
/**
* Shows the number of properties actually displayed, i.e. these remaining after filtering,
* deduping and applying `maxPropertyNumber`
*/
Type[Type["Actual"] = 2] = "Actual";
/**
* Shows both the number of properties retrieved from the property source and the number of
* properties actually displayed (after filtering, deduping and applying `maxPropertyNumber`)
*/
Type[Type["AllAndActual"] = 3] = "AllAndActual";
/**
* Shows both the number of properties retrieved from the property source and the number of
* properties actually displayed (after filtering, deduping and applying `maxPropertyNumber`)
* only if these two numbers are different. Otherwise, does not show anything
*/
Type[Type["AllAndActualIfDifferent"] = 4] = "AllAndActualIfDifferent";
})(Type = PropertyNumberDisplayOption.Type || (PropertyNumberDisplayOption.Type = {}));
})(PropertyNumberDisplayOption || (PropertyNumberDisplayOption = {}));
/**
* Namespace for the options for pretty printing non-primitive values
*
* @category Models
*/
export var NonPrimitive;
(function (NonPrimitive) {
const namespaceTag = moduleTag + 'NonPrimitive/';
const _TypeId = /*#__PURE__*/Symbol.for(namespaceTag);
/**
* Type guard
*
* @category Guards
*/
NonPrimitive.has = u => Predicate.hasProperty(u, _TypeId);
/**
* Equivalence
*
* @category Equivalences
*/
NonPrimitive.equivalence = (self, that) => that.id === self.id;
/** Prototype */
const _TypeIdHash = /*#__PURE__*/Hash.hash(_TypeId);
const proto = {
[_TypeId]: _TypeId,
[Equal.symbol](that) {
return NonPrimitive.has(that) && NonPrimitive.equivalence(this, that);
},
[Hash.symbol]() {
return pipe(this.id, Hash.hash, Hash.combine(_TypeIdHash), Hash.cached(this));
},
[MInspectable.IdSymbol]() {
return this.id;
},
... /*#__PURE__*/MInspectable.BaseProto(namespaceTag),
...MPipeable.BaseProto
};
/**
* Constructor without an id
*
* @category Constructors
*/
NonPrimitive.make = params => MTypes.objectFromDataAndProto(proto, params);
/**
* Returns the `id` property of `self`
*
* @category Destructors
*/
NonPrimitive.id = /*#__PURE__*/Struct.get('id');
/**
* Defaults NonPrimitive Option instance
*
* @category Instances
*/
NonPrimitive.record = /*#__PURE__*/NonPrimitive.make({
id: 'Object',
showId: false,
propertyNumberDisplayOption: PropertyNumberDisplayOption.Type.None,
keyValueSeparatorMark: ': ',
singleLineStartDelimiterMark: '{ ',
singleLineEndDelimiterMark: ' }',
multiLineStartDelimiterMark: '{',
multiLineEndDelimiterMark: '}',
prototypeStartDelimiterMark: '',
prototypeEndDelimiterMark: '@',
singleLineInBetweenPropertySeparatorMark: ', ',
multiLineInBetweenPropertySeparatorMark: ',',
idSeparatorMark: ' ',
propertyNumberSeparatorMark: ',',
propertyNumberStartDelimiterMark: '(',
propertyNumberEndDelimiterMark: ')',
propertySource: PropertySource.Type.FromProperties,
maxPrototypeDepth: 0,
propertyFilters: PPPropertyFilters.utilInspectLike,
propertySortOrder: /*#__PURE__*/Option.none(),
dedupeProperties: false,
maxPropertyNumber: 100,
propertyFormatter: PPPropertyFormatter.keyAndValue,
nonPrimitiveFormatter: /*#__PURE__*/PPNonPrimitiveFormatter.splitOnTotalLengthMaker(80)
});
/**
* NonPrimitive Option instance for arrays
*
* @category Instances
*/
NonPrimitive.array = /*#__PURE__*/NonPrimitive.make({
...NonPrimitive.record,
id: 'Array',
propertyNumberDisplayOption: PropertyNumberDisplayOption.Type.AllAndActualIfDifferent,
singleLineStartDelimiterMark: '[ ',
singleLineEndDelimiterMark: ' ]',
multiLineStartDelimiterMark: '[',
multiLineEndDelimiterMark: ']',
propertySource: PropertySource.Type.FromValueIterable,
propertyFilters: PPPropertyFilters.empty,
propertyFormatter: PPPropertyFormatter.valueOnly
});
/**
* Constructor that generates a NonPrimitive Option instance suitable for maps
*
* @category Constructors
*/
NonPrimitive.maps = id => NonPrimitive.make({
...NonPrimitive.record,
id,
showId: true,
propertyNumberDisplayOption: PropertyNumberDisplayOption.Type.AllAndActualIfDifferent,
keyValueSeparatorMark: ' => ',
propertySource: PropertySource.Type.FromKeyValueIterable,
propertyFilters: PPPropertyFilters.empty,
propertyFormatter: PPPropertyFormatter.keyAndValue
});
/**
* Constructor that generates a NonPrimitive Option instance suitable for sets and arrays other
* than Array
*
* @category Constructors
*/
NonPrimitive.setsAndArrays = id => NonPrimitive.make({
...NonPrimitive.record,
id,
showId: true,
propertyNumberDisplayOption: PropertyNumberDisplayOption.Type.AllAndActualIfDifferent,
propertySource: PropertySource.Type.FromValueIterable,
propertyFilters: PPPropertyFilters.empty,
propertyFormatter: PPPropertyFormatter.valueOnly
});
/**
* Namespace of an initialized NonPrimitive Option
*
* @category Models
*/
let Initialized;
(function (Initialized) {
/**
* Builds an Initialized from a NonPrimitive
*
* @category Constructors
*/
Initialized.fromNonPrimitive = params => {
const valueBasedStylerConstructor = params.valueBasedStylerConstructor;
const nonPrimitiveValueIdTextFormatter = valueBasedStylerConstructor('NonPrimitiveValueId');
const nonPrimitiveValueIdSeparatorTextFormatter = valueBasedStylerConstructor('NonPrimitiveValueIdSeparator');
const propertyNumberDelimitersTextFormatter = valueBasedStylerConstructor('PropertyNumberDelimiters');
const propertyNumberSeparatorTextFormatter = valueBasedStylerConstructor('PropertyNumberSeparator');
const PropertyNumbersTextFormatter = valueBasedStylerConstructor('PropertyNumbers');
return flow(MStruct.enrichWith({
syntheticPropertyFilter: nonPrimitiveOption => PPPropertyFilters.toSyntheticPropertyFilter(nonPrimitiveOption.propertyFilters),
initializedPropertyFormatter: nonPrimitiveOption => nonPrimitiveOption.propertyFormatter(params),
initializedNonPrimitiveFormatter: nonPrimitiveOption => nonPrimitiveOption.nonPrimitiveFormatter(params),
toHeaderMarkShower: nonPrimitiveOption => {
const emptyText = Function.constant(ASText.empty);
const propertyNumberDisplayOption = nonPrimitiveOption.propertyNumberDisplayOption;
const isNone = propertyNumberDisplayOption === PropertyNumberDisplayOption.Type.None;
const isAll = propertyNumberDisplayOption === PropertyNumberDisplayOption.Type.All;
const isActual = propertyNumberDisplayOption === PropertyNumberDisplayOption.Type.Actual;
const isAllAndActual = propertyNumberDisplayOption === PropertyNumberDisplayOption.Type.AllAndActual;
const isAllAndActualIfDifferent = propertyNumberDisplayOption === PropertyNumberDisplayOption.Type.AllAndActualIfDifferent;
const showId = nonPrimitiveOption.showId;
const [propertyNumberStartDelimiter, propertyNumberEndDelimiter] = isNone ? Tuple.make(emptyText, emptyText) : Tuple.make(propertyNumberDelimitersTextFormatter.withContextLast(nonPrimitiveOption.propertyNumberStartDelimiterMark), propertyNumberDelimitersTextFormatter.withContextLast(nonPrimitiveOption.propertyNumberEndDelimiterMark));
const propertyNumberSeparator = isAllAndActual || isAllAndActualIfDifferent ? propertyNumberSeparatorTextFormatter.withContextLast(nonPrimitiveOption.propertyNumberSeparatorMark) : emptyText;
const idSeparator = showId || !isNone ? nonPrimitiveValueIdSeparatorTextFormatter.withContextLast(nonPrimitiveOption.idSeparatorMark) : emptyText;
const id = showId ? nonPrimitiveValueIdTextFormatter.withContextLast(nonPrimitiveOption.id) : emptyText;
return ({
allPropertyNumber,
actualPropertyNumber
}) => value => {
const showAllAndActual = isAllAndActual || isAllAndActualIfDifferent && allPropertyNumber !== actualPropertyNumber;
const styledTotalPropertyNumber = isAll || showAllAndActual ? pipe(allPropertyNumber, MString.fromNonNullablePrimitive, PropertyNumbersTextFormatter.withContextLast, Function.apply(value)) : ASText.empty;
const styledActualPropertyNumber = isActual || showAllAndActual ? pipe(actualPropertyNumber, MString.fromNonNullablePrimitive, PropertyNumbersTextFormatter.withContextLast, Function.apply(value)) : ASText.empty;
const [inContextPropertyNumberStartDelimiter, inContextPropertyNumberSeparator, inContextPropertyNumberEndDelimiter, inContextIdSeparator] = isAllAndActualIfDifferent && allPropertyNumber === actualPropertyNumber ? [ASText.empty, ASText.empty, ASText.empty, showId ? idSeparator(value) : ASText.empty] : [propertyNumberStartDelimiter(value), propertyNumberSeparator(value), propertyNumberEndDelimiter(value), idSeparator(value)];
return ASText.concat(id(value), inContextPropertyNumberStartDelimiter, styledTotalPropertyNumber, inContextPropertyNumberSeparator, styledActualPropertyNumber, inContextPropertyNumberEndDelimiter, inContextIdSeparator);
};
}
}));
};
})(Initialized = NonPrimitive.Initialized || (NonPrimitive.Initialized = {}));
})(NonPrimitive || (NonPrimitive = {}));
/**
* Type guard
*
* @category Guards
*/
export const has = u => Predicate.hasProperty(u, _TypeId);
/**
* Equivalence
*
* @category Equivalences
*/
export const equivalence = (self, that) => that.id === self.id;
/** Prototype */
const _TypeIdHash = /*#__PURE__*/Hash.hash(_TypeId);
const proto = {
[_TypeId]: _TypeId,
[Equal.symbol](that) {
return has(that) && equivalence(this, that);
},
[Hash.symbol]() {
return pipe(this.id, Hash.hash, Hash.combine(_TypeIdHash), Hash.cached(this));
},
[MInspectable.IdSymbol]() {
return this.id;
},
... /*#__PURE__*/MInspectable.BaseProto(moduleTag),
...MPipeable.BaseProto
};
/**
* Constructor without a id
*
* @category Constructors
*/
export const make = params => MTypes.objectFromDataAndProto(proto, params);
/**
* Returns the `id` property of `self`
*
* @category Destructors
*/
export const id = /*#__PURE__*/Struct.get('id');
/**
* `Option` instance that pretty-prints a value in a way very similar to util.inspect.
*
* @category Instances
*/
export const utilInspectLike = /*#__PURE__*/make({
id: 'UtilInspectLike',
styleMap: PPStyleMap.none,
markMap: PPMarkMap.utilInspectLike,
byPassers: /*#__PURE__*/Array.make(PPByPasser.functionToName, PPByPasser.objectToString),
primitiveFormatter: /*#__PURE__*/PPPrimitiveFormatter.utilInspectLikeMaker(),
maxDepth: 2,
generalNonPrimitiveOption: NonPrimitive.record,
specificNonPrimitiveOption: value => {
const content = value.content;
if (MTypes.isArray(content)) return Option.some(NonPrimitive.array);
if (content instanceof Map) return Option.some(NonPrimitive.maps('Map'));
if (content instanceof Set) return Option.some(NonPrimitive.setsAndArrays('Set'));
if (content instanceof WeakMap) return Option.some(NonPrimitive.maps('WeakMap'));
if (content instanceof WeakSet) return Option.some(NonPrimitive.setsAndArrays('WeakSet'));
if (HashMap.isHashMap(content)) return Option.some(NonPrimitive.maps('EffectHashMap'));
if (SortedMap.isSortedMap(content)) return Option.some(NonPrimitive.maps('EffectSortedMap'));
if (HashSet.isHashSet(content)) return Option.some(NonPrimitive.setsAndArrays('EffectHashSet'));
if (SortedSet.isSortedSet(content)) return Option.some(NonPrimitive.setsAndArrays('EffectSortedSet'));
return pipe(content, MTypes.typedArrayName, Option.map(NonPrimitive.setsAndArrays));
}
});
/**
* `Option` instance that pretty-prints a value in a way very similar to util.inspect with colors
* adapted to a terminal in dark mode.
*
* @category Instances
*/
export const darkModeUtilInspectLike = /*#__PURE__*/make({
...utilInspectLike,
id: 'DarkModeUtilInspectLike',
styleMap: PPStyleMap.darkMode
});
/**
* `Option` instance that treeifies a value
*
* @category Instances
*/
export const treeify = /*#__PURE__*/make({
id: 'Treeify',
styleMap: PPStyleMap.none,
markMap: PPMarkMap.utilInspectLike,
byPassers: /*#__PURE__*/Array.empty(),
primitiveFormatter: /*#__PURE__*/PPPrimitiveFormatter.utilInspectLikeMaker(),
maxDepth: +Infinity,
generalNonPrimitiveOption: /*#__PURE__*/NonPrimitive.make({
...NonPrimitive.record,
propertyFilters: /*#__PURE__*/Array.empty(),
propertySortOrder: /*#__PURE__*/Option.none(),
dedupeProperties: false,
maxPropertyNumber: +Infinity,
propertyFormatter: PPPropertyFormatter.treeify,
nonPrimitiveFormatter: PPNonPrimitiveFormatter.treeify
}),
specificNonPrimitiveOption: /*#__PURE__*/flow(utilInspectLike.specificNonPrimitiveOption, /*#__PURE__*/Option.map(/*#__PURE__*/flow(/*#__PURE__*/MStruct.set({
nonPrimitiveFormatter: PPNonPrimitiveFormatter.treeify,
propertyFormatter: PPPropertyFormatter.treeify
}), NonPrimitive.make)))
});
/**
* `Option` instance that treeifies a value with colors adapted to dark mode
*
* @category Instances
*/
export const darkModeTreeify = /*#__PURE__*/make({
...treeify,
id: 'DarkModeTreeify',
styleMap: PPStyleMap.darkMode
});
/**
* `Option` instance that treeifies a value and hides the leaves
*
* @category Instances
*/
export const treeifyHideLeaves = /*#__PURE__*/make({
...treeify,
id: 'TreeifyHideLeaves',
generalNonPrimitiveOption: /*#__PURE__*/NonPrimitive.make({
...treeify.generalNonPrimitiveOption,
propertyFormatter: PPPropertyFormatter.treeifyHideLeafValues
}),
specificNonPrimitiveOption: /*#__PURE__*/flow(treeify.specificNonPrimitiveOption, /*#__PURE__*/Option.map(/*#__PURE__*/flow(/*#__PURE__*/MStruct.set({
propertyFormatter: PPPropertyFormatter.treeifyHideLeafValues
}), NonPrimitive.make)))
});
/**
* `Option` instance that treeifies a value and hides the leaves with colors adapted to dark mode
*
* @category Instances
*/
export const darkModeTreeifyHideLeaves = /*#__PURE__*/make({
...treeifyHideLeaves,
id: 'DarkModeTreeifyHideLeaves',
styleMap: PPStyleMap.darkMode
});
/**
* Builds a Stringifier from an Option
*
* @category Destructors
*/
export const toStringifier = self => {
const valueBasedStylerConstructor = PPValueBasedStylerConstructor.fromOption(self);
const markShowerConstructor = PPMarkShowerConstructor.fromOption(self);
const constructors = {
markShowerConstructor,
valueBasedStylerConstructor
};
const primitiveValueTextFormatter = valueBasedStylerConstructor('PrimitiveValue');
const messageTextFormatter = valueBasedStylerConstructor('Message');
const circularObjectMarkShower = markShowerConstructor('CircularObject');
const circularReferenceStartDelimiterMarkShower = markShowerConstructor('CircularReferenceStartDelimiter');
const circularReferenceEndDelimiterMarkShower = markShowerConstructor('CircularReferenceEndDelimiter');
const messageStartDelimiterMarkShower = markShowerConstructor('MessageStartDelimiter');
const messageEndDelimiterMarkShower = markShowerConstructor('MessageEndDelimiter');
const initializedByPasser = PPByPassers.toSyntheticByPasser(self.byPassers).call(self, constructors);
const toInitializedNonPrimitiveOption = NonPrimitive.Initialized.fromNonPrimitive(constructors);
const initializedNonPrimitiveOptionCache = MCache.make({
lookUp: ({
key
}) => Tuple.make(toInitializedNonPrimitiveOption(key), true)
});
const initializedNonPrimitiveOptionGetter = MCache.toGetter(initializedNonPrimitiveOptionCache);
const initializedGeneralNonPrimitiveOption = initializedNonPrimitiveOptionGetter(self.generalNonPrimitiveOption);
const functionToNameByPasser = PPByPasser.functionToName.call(self, constructors);
let lastCyclicalIndex = 1;
const cyclicalMap = MutableHashMap.empty();
const stringifier = flow(PPValue.fromTopValue, MTree.unfoldAndFold({
unfold: (seed, cyclicalRef) => pipe(Either.gen(function* () {
const notByPassed = yield* pipe(seed, initializedByPasser, Either.fromOption(Function.constant(seed)), Either.flip);
const unBypassedNonPrimitive = yield* pipe(notByPassed, Either.liftPredicate(PPValue.isNonPrimitive, Function.unsafeCoerce), Either.mapLeft(flow(self.primitiveFormatter, primitiveValueTextFormatter(notByPassed), PPStringifiedValue.fromText)));
const initializedNonPrimitiveOption = pipe(unBypassedNonPrimitive, self.specificNonPrimitiveOption, Option.map(initializedNonPrimitiveOptionGetter), Option.getOrElse(Function.constant(initializedGeneralNonPrimitiveOption)));
const unBypassedNonPrimitiveUnderMaxDepth = yield* pipe(unBypassedNonPrimitive, Either.liftPredicate(flow(PPValue.depth, Number.lessThan(self.maxDepth)), flow(functionToNameByPasser, Option.getOrElse(pipe(initializedNonPrimitiveOption.id, messageTextFormatter(unBypassedNonPrimitive), ASText.surround(messageStartDelimiterMarkShower(unBypassedNonPrimitive), messageEndDelimiterMarkShower(unBypassedNonPrimitive)), PPStringifiedValue.fromText, Function.constant)))));
const unCyclicalUnBypassedNonPrimitiveUnderMaxDepth = yield* pipe(cyclicalRef, Option.map(([cyclicalValue]) => pipe(cyclicalMap, MutableHashMap.get(cyclicalValue), Option.getOrElse(() => {
/* eslint-disable-next-line functional/no-expression-statements */
MutableHashMap.set(cyclicalMap, cyclicalValue, lastCyclicalIndex);
return lastCyclicalIndex++;
}), MString.fromNonNullablePrimitive, messageTextFormatter(unBypassedNonPrimitiveUnderMaxDepth), ASText.prepend(circularObjectMarkShower(unBypassedNonPrimitiveUnderMaxDepth)), ASText.surround(messageStartDelimiterMarkShower(unBypassedNonPrimitiveUnderMaxDepth), messageEndDelimiterMarkShower(unBypassedNonPrimitiveUnderMaxDepth)), PPStringifiedValue.fromText)), Either.fromOption(Function.constant(unBypassedNonPrimitiveUnderMaxDepth)), Either.flip);
const properties = pipe(initializedNonPrimitiveOption.propertySource, MMatch.make, MMatch.whenIs(PropertySource.Type.FromProperties, pipe(initializedNonPrimitiveOption.maxPrototypeDepth, PPValues.fromProperties, Function.constant)), MMatch.whenIs(PropertySource.Type.FromValueIterable, Function.constant(PPValues.fromValueIterable)), MMatch.whenIs(PropertySource.Type.FromKeyValueIterable, Function.constant(PPValues.fromKeyValueIterable(stringifier))), MMatch.exhaustive, Function.apply(unCyclicalUnBypassedNonPrimitiveUnderMaxDepth));
const sort = pipe(initializedNonPrimitiveOption.propertySortOrder, Option.map(order => Array.sort(order)), Option.getOrElse(Function.constant(Function.identity)));
const filteredAndSortedProperties = pipe(properties, initializedNonPrimitiveOption.syntheticPropertyFilter, sort, MFunction.fIfTrue({
condition: initializedNonPrimitiveOption.dedupeProperties,
f: Array.dedupeWith((self, that) => self.oneLineStringKey === that.oneLineStringKey)
}), Array.take(initializedNonPrimitiveOption.maxPropertyNumber));
return Tuple.make(Tuple.make(unCyclicalUnBypassedNonPrimitiveUnderMaxDepth, initializedNonPrimitiveOption, properties.length), filteredAndSortedProperties);
}), Either.mapLeft(flow(Tuple.make, Tuple.appendElement(seed), Tuple.appendElement(true)))),
foldNonLeaf: ([nonPrimitive, initializedNonPrimitiveOption, allPropertyNumber], children) => pipe(children, Array.map(([stringified, value, isLeaf]) => pipe(stringified, initializedNonPrimitiveOption.initializedPropertyFormatter({
value,
isLeaf
}))), initializedNonPrimitiveOption.initializedNonPrimitiveFormatter({
value: nonPrimitive,
header: pipe(cyclicalMap, MutableHashMap.get(nonPrimitive), Option.map(flow(MString.fromNonNullablePrimitive, messageTextFormatter(nonPrimitive), ASText.prepend(circularReferenceStartDelimiterMarkShower(nonPrimitive)), ASText.append(circularReferenceEndDelimiterMarkShower(nonPrimitive)))), Option.getOrElse(Function.constant(ASText.empty)), ASText.append(pipe(nonPrimitive, initializedNonPrimitiveOption.toHeaderMarkShower({
allPropertyNumber,
actualPropertyNumber: children.length
}))))
}), Tuple.make, Tuple.appendElement(nonPrimitive), Tuple.appendElement(false)),
foldLeaf: Function.identity
}), ([first]) => first);
return stringifier;
};
//# sourceMappingURL=Option.js.map