@parischap/pretty-print
Version:
A functional library to pretty-print and treeify objects
160 lines • 5.64 kB
JavaScript
/**
* This module implements a type that takes care of the stringification of the properties of a
* non-primitive value. From the stringified representation of the value of a property which it
* receives, it must return the stringified representation of the whole property (key and value).
*
* 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 { MFunction, MInspectable, MPipeable, MTypes } from '@parischap/effect-lib';
import { Array, Equal, flow, Function, Hash, pipe, Predicate, String, Struct } from 'effect';
import * as PPStringifiedValue from './StringifiedValue.js';
/**
* Module tag
*
* @category Models
*/
export const moduleTag = '@parischap/pretty-print/PropertyFormatter/';
const _TypeId = /*#__PURE__*/Symbol.for(moduleTag);
/**
* Type guard
*
* @category Guards
*/
export const has = u => Predicate.hasProperty(u, _TypeId);
/**
* PropertyFormatter equivalence
*
* @category Equivalences
*/
export const equivalence = (self, that) => that.id === self.id;
/** Base */
const _TypeIdHash = /*#__PURE__*/Hash.hash(_TypeId);
const base = {
[_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
*
* @category Constructors
*/
export const make = ({
id,
action
}) => Object.assign(MFunction.clone(action), {
id,
...base
});
/**
* Returns the `id` property of `self`
*
* @category Destructors
*/
export const id = /*#__PURE__*/Struct.get('id');
/**
* PropertyFormatter instance that prints only the value of a property (similar to the usual way an
* array is printed).
*
* @category Instances
*/
export const valueOnly = /*#__PURE__*/make({
id: 'ValueOnly',
action: () => () => Function.identity
});
/* if onSameLine=false and isLeaf=false , the lines of the value are appended to the lines of the key and no keyValueSeparator is used. In all other cases, the last line of the key and the first line of the value are merged and separated by the keyValueSeparator. */
const _keyAndValueAction = ({
onSameLine,
dontShowLeafValue
}) => function ({
valueBasedStylerConstructor
}) {
const propertyKeyTextFormatter = valueBasedStylerConstructor('PropertyKey');
const prototypeDelimitersTextFormatter = valueBasedStylerConstructor('PrototypeDelimiters');
const KeyValueSeparatorTextFormatter = valueBasedStylerConstructor('KeyValueSeparator');
return ({
value,
isLeaf
}) => {
const stringKey = value.stringKey;
const protoDepth = value.protoDepth;
if (MTypes.isSingleton(stringKey) && String.isEmpty(stringKey[0])) return Function.identity;
const inContextPropertyKeyTextFormatter = propertyKeyTextFormatter(value);
const inContextPrototypeDelimitersTextFormatter = prototypeDelimitersTextFormatter(value);
const keyValueSeparator = pipe(this.keyValueSeparatorMark, KeyValueSeparatorTextFormatter(value));
const key = pipe(stringKey, Array.map((line, _i) => inContextPropertyKeyTextFormatter(line)), MFunction.fIfTrue({
condition: protoDepth > 0,
f: flow(PPStringifiedValue.prependToFirstLine(pipe(this.prototypeStartDelimiterMark, inContextPrototypeDelimitersTextFormatter, ASText.repeat(protoDepth))), PPStringifiedValue.appendToLastLine(pipe(this.prototypeEndDelimiterMark, inContextPrototypeDelimitersTextFormatter, ASText.repeat(protoDepth))))
}));
return stringifiedValue => {
if (!onSameLine && !isLeaf) return pipe(key, Array.appendAll(stringifiedValue));
const firstLine = Array.headNonEmpty(stringifiedValue);
const showValue = !isLeaf || !dontShowLeafValue;
return pipe(key, Array.initNonEmpty, Array.append(pipe(key,
// cannot be an empty string
Array.lastNonEmpty, MFunction.fIfTrue({
condition: showValue && ASText.isNotEmpty(firstLine),
f: flow(ASText.append(keyValueSeparator), ASText.append(firstLine))
}))), MFunction.fIfTrue({
condition: showValue,
f: Array.appendAll(Array.tailNonEmpty(stringifiedValue))
}));
};
};
};
/**
* PropertyFormatter instance that prints the key and value of a property (similar to the usual way
* a record is printed). A mark can be prepended or appended to the key to show if the property
* comes from the object itself or from one of its prototypes.
*
* @category Instances
*/
export const keyAndValue = /*#__PURE__*/make({
id: 'KeyAndValue',
action: /*#__PURE__*/_keyAndValueAction({
onSameLine: true,
dontShowLeafValue: false
})
});
/**
* PropertyFormatter instance that :
*
* - For a leaf: does the same as keyAndValue
* - For a non-leaf: prints the key and value on separate lines without any key/value separator
*
* @category Instances
*/
export const treeify = /*#__PURE__*/make({
id: 'Treeify',
action: /*#__PURE__*/_keyAndValueAction({
onSameLine: false,
dontShowLeafValue: false
})
});
/**
* PropertyFormatter instance that :
*
* - For a leaf: prints only the key
* - For a non-leaf: prints the key and value on separate lines without any key/value separator
*
* @category Instances
*/
export const treeifyHideLeafValues = /*#__PURE__*/make({
id: 'Treeify',
action: /*#__PURE__*/_keyAndValueAction({
onSameLine: false,
dontShowLeafValue: true
})
});
//# sourceMappingURL=PropertyFormatter.js.map