Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use default behavior for the body of a devtoolsFormatters formatter in Chrome Developer Tools

I have tried many things, with this as the base:

(() => {
    function getLevelIndentation(level){
        return level * 20 + "px";
    }
    var multiKeyMapFormatter = {
        header: function(x) {
            if (!(x instanceof MultiKeyMap)){
                return null;
            }

            let textArray = [];
            x.forEach((r, u, t, mkm) => textArray.push("[" + t + ", " + u + "] => " + (r instanceof Object ? r.constructor.name : r)));
            const header = "MultiKeyMap - " + textArray.join("|").substr(0, 50);

            return ["div", {"style":'color: green'}, header]
        },
        hasBody: function(){
            return true;
        },
        body: function(obj, config){
            return undefined;   
        },
    };


    window.devtoolsFormatters = [multiKeyMapFormatter];

    console.log("defined window.devtoolsFormatters");
    
})();

e.g. I tried...

  • substituting null for undefined in the return from the body function
  • omitting the body function
  • rewriting the default behavior (see below)
  • returning obj in various permutations
  • Setting hasBody to return false
    // attempt at rewriting the default behavior
    // ref: https://www.mattzeunert.com/2016/02/19/custom-chrome-devtools-object-formatters.html
    body: function(obj, config){
        var level = config !== undefined ? config.level : 0;
    
        var elements = Object.keys(obj).map(function(key){
            var child;
            var childObj = obj[key];
            if (typeof childObj === "object"){
                child = ["object", {
                    object: childObj,
                    config: {
                        key: key,
                        level: level + 1
                    }
                }];
            } else {
                child = key + ": " + (childObj && childObj.toString ? childObj.toString() : childObj);
    
            }
            return ["div", {style: "margin-left: " + getLevelIndentation(level)}, child];
        })
    
        return ["div", {}].concat(elements);
    },

Is there a way to tell Chrome to use the default body behavior?

like image 294
bnieland Avatar asked Jan 25 '20 17:01

bnieland


1 Answers

Good question, the closest I could come to is:

  • remove formatters
  • call "original" console.log
  • add formatters back

Like:

function consoleLogDefault(...args) {
  const old = window.devtoolsFormatters;
  delete window.devtoolsFormatters;
  console.log(...args);
  window.devtoolsFormatters = old;
}

Full example:

class Color {
  constructor(r, g, b) {
    this.r = r;
    this.g = g;
    this.b = b;
  }
}
function consoleLogDefault(...args) {
  const old = window.devtoolsFormatters;
  delete window.devtoolsFormatters;
  console.log(...args);
  window.devtoolsFormatters = old;
}
const FormatColor = {
  header(o) {
    if (!(o instanceof Color)) {
      return null;
    }
    const style = {
      style: `color: rgb(${o.r}, ${o.g}, ${o.b});`
    }
    return ["table", style,
      ["tr",
        ["td", "r"],
        ["td", "g"],
        ["td", "b"],
       ],
      ["tr",
        ["td", o.r],
        ["td", o.g],
        ["td", o.b],
      ]
    ];
  },
  hasBody() {
    return true;
  },
  body(o) {
    consoleLogDefault(...arguments);
    return ["ol", ["li", o.r], ["li", o.g], ["li", o.b]];
  }
};
window.devtoolsFormatters = [
  FormatColor
];
red = new Color(255,0,0);
green = new Color(0,255,0);
blue = new Color(0,0,255);
console.log(red);
console.log(green);
console.log(blue);

The problem is just that it will not appear "grouped" under the actual object, but just appended as console message. :(

Result:

enter image description here

Not perfect, still better than nothing.

like image 58
kungfooman Avatar answered Nov 15 '22 10:11

kungfooman