1

Something that drives me nuts in the developper tools of Chrome (106) and Firefox (105) is the fact that whenever some text logged to the console via console.log(text) happens to contain a hyperlink, this link is not only turned clickable (I can live with it even when I usually prefer to have just plain text) but is abbreviated, if it is a long link. So when I want to control what precise link is in some variable, I cannot just write e.g. console.log(img.src), because some of the interesting information of the link is hidden. You can try yourself with

var href = 'https://stackoverflow.com/search?q=%5Bgoogle-chrome-devtools%5D+%5Bconsole.log%5D+%5Bfirefox-developer-tools%5D+%5Bhyperlink%5D+automatic+detection&someMoreStuffTomakeTheLinkLonger';
console.log(href);

In both, Firefox and Chrome, the output for me contains some '...', e.g. in Firefox I obtain as output:

 https://stackoverflow.com/search?q=%5Bgoogle-chrome-devtools…link%5D+automatic+detection&someMoreStuffTomakeTheLinkLonger 

thus hiding the part after "-devtools". (Chrome hides a slightly different part). The console is mostly a debugging tool. I log things because I want to see them, not hide them. I always need to either hover with the mouse and wait for the tooltip (doesn't allow me to copy fractions of the link) or to right click copy the link and paste it somewhere where I can see it completely. Or take a substring to remove the "https://" in the front. But note that the variable isn't necessarily a single hyperlink, but can be any text containing several such hyperlinks. I didn't find a way to force console.log to just print plain text all content. Did anybody meet this problem as well and find a workaround?

Sebastian
  • 365
  • 3
  • 17
  • 1
    `console.log('%O', href)` works in Chrome. – wOxxOm Nov 24 '22 at 11:32
  • @wOxxOm oh cool, indeed! This answers the question for Chrome. I feel now stupid that I didn't find this in the documentation of `console.log` e.g. at [MDN](https://developer.mozilla.org/en-US/docs/Web/API/console#outputting_text_to_the_console) . Unfortunately Firefox still doesn't care ... – Sebastian Nov 24 '22 at 11:42
  • 1
    There might be no solution for Firefox. Either way, this is something that all browsers should probably agree upon and provide a unified documented method e.g. using `%O` or a new specifier to force "plain text mode" and disable linkifying, so maybe you could open a ticket in their bug trackers. – wOxxOm Nov 24 '22 at 13:03

1 Answers1

1

I made this a community wiki answer, because the main insight is not from myself but from the comments. Feel free to improve. The console.log() function allows several arguments, which allows also a formatted output similar to printf in some languages. The possibilities of formatting can be found in the documentation of console.log() on MDN. In any case, this formatted output provides a solution at least for Chrome, as @wOxxOm pointed out in the comments:

console.log('%O', href) // works in Chrome

This is rather surprising, because %O is described at MDN as "Outputs a JavaScript object. Clicking the object name opens more information about it in the inspector". It seems there is no 'clicking' in Chrome when the object is a string.

There is also %s for string output, but this just gives the standard behavior of replacing links in both browsers. And for Firefox none of the above two formatting options works. There one really has to replace the protocol "https://" by something that is not recognized as link. A space behind ':' seems enough, so "https: //". It turns out, that one can also insert a formatting string "https:%c//", which can even be empty, and thus yield an output which is the complete link and can be copied as well:

console.log(href.replace(/(https?:)/, "$1%c"), ""); // works in Firefox

In particular the FF solution is cumbersome, and there might also be several links within one console-output. So it is useful to define one's own log-function (or if one prefers, redefine console.log, but note the remark at the end)

    function isChrome() {...} // use your favorite Chrome detection here
    function isFirefox() {...} // use your favorite Firefox detection here
    function plainLog() {
        const msg = arguments[0];
        if (isChrome() && arguments.length == 1 && typeof msg == "string") {

            return console.log("%O", msg);
        }
        if (isFirefox() && arguments.length == 1 && typeof msg == "string") {
            const emptyStyle = ""; // serves only as a separator, such that FF doesn't recognize the link anymore
            const reg = /(https?:)\/\//g;
            const emptyStyles = []; // we need to insert one empty Style for every found link
            const matches = msg.matchAll(reg);
            for (let match of matches) {
                emptyStyles.push(emptyStyle);
            }

            return console.log(msg.replace(reg, '$1%c//'), ...emptyStyles);
        }

        return console.log(...arguments);
    }

For browser detection isChrome() and isFirefox() see e.g. here on SO. One can of course extend the redefinition also to the other console functions (console.info, console.warn, etc.)

The downside of the redefinition of console.log is that usually every output of the console shows also the last entry of the call stack as a practical link to the source of the logging. But due to the redefintion, this link is now always to the same place, namely the file and line number where plainLog() is defined and calls console.log(), instead of the place where the new log command plainLog() was called. This new problem is described on SO here, but the solution (see comment) is again a bit involved and also not completely satisfying to serve as a replacement for the built-in console.log . So if links appear only rarely in the logging, it's probably better to switch to the redefined plainLog() only for these links.

Sebastian
  • 365
  • 3
  • 17
  • The [solution to the stack-problem](https://stackoverflow.com/questions/66970033/javascript-change-console-call-stack/67121810#67121810) would look here as follows: First extract the stackTrace via `stackTrace = new Error().stack.split('\n').filter(x => x && x.trim() && x.trim().toLowerCase() != 'error')`; And then append the second (instead of the first) entry, so `stackTrace[1]` to the message in the `plainLog()` definition. One can also put again a `%c` in front of it and add another css formatting string with a small font size or different color. – Sebastian Dec 16 '22 at 08:15