Chrome custom formatter

Something I wanted for a long time, and I didn’t find a topic about it.

I’ve created a quick and (very) dirty custom formatter for belt structures (string map & list).
I post the code here if someone wants to use it as a starting point / improve it.

when installed, if you log a code like this (reasonml syntax, sorry):

let aMap = Belt.Map.String.fromArray([|("k1", ["hello"]), ("k2", ["world"]), ("k3", ["nice", "map"])|])
Js.log(aMap)

you get this ‘nice’ formatted output in the chrome console:

image

it’s very basic, but it may already help.

file rescript-custom-formatter.js:

global.window.devtoolsFormatters = global.window.devtoolsFormatters || [];

const listStyle = {style: 'list-style-type: none; padding: 0; margin: 0 0 0 12px; font-style: normal; position: relative'};
const keyStyle = {style: 'color: #881391'};

function listToJsArray(obj, result) {
    result.push(obj.hd);
    if (obj.tl !== 0) {
        listToJsArray(obj.tl, result);
    }
}

const beltListFormatter = {
    header(obj) {
        if (obj.hasOwnProperty('hd') && obj.hasOwnProperty('tl')) {
            return ['div', {}, 'list'];
        }
        return null;
    },
    hasBody() {
        return true;
    },
    body(obj, _config) {
        const convertedList = [];
        listToJsArray(obj, convertedList);
        const children = convertedList.map((item, index) => [
                'li', {}, [
                    'span', {}, ['span', keyStyle, index + ': '], [
                        'object', {
                            object: item,
                            config: {}
                        }
                    ]
                ]
            ]);
        return ['ol', listStyle, ...children];
    }
};

function beltMapToJsMap(obj, result) {
    if (obj) {
        result[obj.k] = obj.v;
        beltMapToJsMap(obj.l, result);
        beltMapToJsMap(obj.r, result);
    }
}

const beltMapFormatter = {
    header(obj) {
        if (obj.hasOwnProperty('h') && obj.hasOwnProperty('k') && obj.hasOwnProperty('l') && obj.hasOwnProperty('r') && obj.hasOwnProperty('v')) {
            // tag-name, attributes, element-list
            return ['div', {}, 'Belt.Map.String'];
        }
        return null;
    },
    hasBody() {
        return true;
    },
    body(obj, _config) {
        const convertedMap = {};
        beltMapToJsMap(obj, convertedMap);
        const children = Object.entries(convertedMap)
            .map((entry) => [
                'li', {}, [
                    'span', {}, ['span', keyStyle, entry[0] + ': '], [
                        'object', {
                            object: entry[1],
                            config: {}
                        }
                    ]
                ]
            ]);
        return ['ol', listStyle, ...children];
    }
};

let installed = false;

export function installRescriptFormatters() {
    if (!installed) {
        console.log('installing beltMap custom formatter');
        global.window.devtoolsFormatters.push(beltMapFormatter);
        global.window.devtoolsFormatters.push(beltListFormatter);
        installed = true;
    }
}

you can use it by importing it and call the install function (must be done before any log):

import {installRescriptFormatters} from './rescript-custom-formatter';
installRescriptFormatters();
7 Likes