debug icon indicating copy to clipboard operation
debug copied to clipboard

% symbol in object interpreted as formatter

Open matthieusieben opened this issue 5 years ago • 6 comments

const debug = require('debug')('foo')
debug.enabled = true // Or use ENV variables
const someObjectIWantToLog = { "%j": "%j %j %%" }
debug("%o", someObjectIWantToLog, 1, 2, 3)

result:

  foo { '1': '2 3 %' } +0ms

expected result:

  foo { "%j": "%j %j %%" } 1 2 3 +0ms

This gets even weirder when running the following several times:

debug("%o", { "%j": "%j %j %%" })
debug("%o", { "%j": "%j %j %%" })
debug("%o", { "%j": "%j %j %%" })
debug("%o", { "%j": "%j %j %%" })

result:

  foo { '"\u001b[38;5;148m+3s\u001b[0m"': '%j %j %' }
  foo { '"\u001b[38;5;148m+847ms\u001b[0m"': '%j %j %' }
  foo { '"\u001b[38;5;148m+674ms\u001b[0m"': '%j %j %' }
  foo { '"\u001b[38;5;148m+620ms\u001b[0m"': '%j %j %' }

Did I miss something in the doc? Is there a way not to interpret those % symbols? Or is this a bug?

matthieusieben avatar Jun 23 '20 12:06 matthieusieben

Reproduced; this is very clearly a bug.

Sorry you're hitting it - I'm surprised it's not been brought up before. Thank you for the reproduction steps.

PR is welcome, else I will try to find time within the next week to get to it.

Qix- avatar Jun 23 '20 12:06 Qix-

Super weird. Just investigated a bit more to make sure this wasn't introduced recently (it wasn't, it exists pre-4.x).

It appears, for whatever reason, the %o is honoring the second argument as another formatting string.

If you would like to work around this, insert another %o at the beginning of the argument list. I know this isn't ideal, but if you need a fix right now, that should get you somewhat sane output.

const debug = require('debug')('foo');
debug.enabled = true // Or use ENV variables

const someObjectIWantToLog = { "%j": "%j %j %%" }
debug("%o", "%o", someObjectIWantToLog, 1, 2, 3)
debug("%o", "%o", { "%j": "%j %j %%" })
debug("%o", "%o", { "%j": "%j %j %%" })
debug("%o", "%o", { "%j": "%j %j %%" })
debug("%o", "%o", { "%j": "%j %j %%" })
  foo '{ '%j': '%j %j %%' }' 1 2 3 +0ms
  foo '{ '%j': '%j %j %%' }' +2ms
  foo '{ '%j': '%j %j %%' }' +1ms
  foo '{ '%j': '%j %j %%' }' +0ms
  foo '{ '%j': '%j %j %%' }' +0ms

Qix- avatar Jun 23 '20 12:06 Qix-

THANKS!

Sarahho0624 avatar Apr 28 '21 06:04 Sarahho0624

@Qix FWIW EJS templates (which use <% %> as delimiters by default) have worked around this by introducing the convention that pre- or appending the delimiter will interpret it as literal. Could be a viable, simple option that eg %%o will output a literal %o

webketje avatar Jun 03 '22 00:06 webketje

2.6.8

RabiaSaid avatar Jun 21 '22 12:06 RabiaSaid

4.3.4

RabiaSaid avatar Jun 21 '22 12:06 RabiaSaid