2

I have checked the google dev tools for console (https://developer.chrome.com/devtools/docs/console), and know that '%c' can apply CSS style rules to output string.

Here is my problem:
I want to write a functon redLog(msg, regExp), for example redLog('Page1, Page2', /\d/g) outputs the same text and style with console.log('Page%c1%c, Page%c2%c', 'color:red', 'color:black', 'color:red', 'color:black'), but the arbitrary css string('color:red', 'color:black', 'color:red', 'color:black') troubles me.
My recent code snippet is listed as follows(This is my first experience of posting a question in English, i don't know for sure that my problem has made it clear to you guys.):

// redLog('Page1, Page2', /\d/g) // function as console.log('Page%c1%c, Page%c2%c', 'color:red', 'color:black', 'color:red', 'color:black') // msg: the output string // regExp: when any characters match the regExp, red it function redLog(msg, regExp) { var cssStr = ''; if (msg && regExp) { msg = msg.replace(regExp, '%c$&%c'); // '$&' inserts the matched substring. console.log(msg); // i cannot determine the cssStr } else { console.log(msg); } }

1
  • 3
    Writing your question completely in bold does neither help to make it better readable nor does it make your question more important. writing everything in bold is more like shouting SIMILAR AS IF YOU WOULD WRITE EVERYTHING IN UPPERCASES. Commented Nov 7, 2014 at 10:12

5 Answers 5

4

Your question is really complex because console.log needs a css string argument for every %c in your message. But since you do that dynamically, you cannot hard code your arguments for console.log, what leads to the problem, that you need to call console.log with an array of arguments. For this problem the .apply method can be used:

console.log.apply(console, args); 

But to use this, you need to set up an array for the arguments:

var args = [msg]; 

and fill it with the needed amount of css styles, which is a little complicated, because you need to find all the appearances of %c in your message and toggle between two (or more if you want) css styles:

var helpString = msg; var toggleNextString = false; while (helpString.indexOf("%c") != -1) { if (!toggleNextString) args.push(cssStrNew); else args.push(cssStrStandard); toggleNextString = !toggleNextString; helpString = helpString.substr(helpString.indexOf("%c") + 2); } 

Note: I used two strings for the standard log css and for the color red.

Putting all of this together, the function looks like this:

function redLog(msg, regExp) { var cssStrNew = 'color: red;'; var cssStrStandard = 'color: black'; if (msg && regExp) { msg = msg.replace(regExp, '%c$&%c'); var args = [msg]; var helpString = msg; var toggleNextString = false; while (helpString.indexOf("%c") != -1) { if (!toggleNextString) args.push(cssStrNew); else args.push(cssStrStandard); toggleNextString = !toggleNextString; helpString = helpString.substr(helpString.indexOf("%c") + 2); } console.log.apply(console, args); } else { msg = "%c" + msg console.log(msg, cssStrNew); } } 

Here is working fiddle

IMPORTANT: %c doesn't work within all browsers (for Firefox you can use Firebug) (afaik)

Sign up to request clarification or add additional context in comments.

3 Comments

:) that's what I thought it should look like but in not into javascript :)
The %c should work with all current WebKit / Blink based browsers (Chrome, Safari, Opera). But I never tested it in IE.
@t.niese I changed the note
0

Well try this, although you need still work on the regExp. This is just a tip ( how to display your message with a color ) , your question is more complex and bit messy. You trying to add several parameters into your function, you should try use 1 parameter color and make an array of it. Inside the function you would organize it properly for your needs.

Edit2. Outcome is Page1, Page%c2 , where (%c2 doesn't want to get bold here) bold stands for blue. As I know there is no closing bracket for %c, so you need to explode parameter 1 by a comma (,) -> assign to table and lunch console.log foreach element in array.

if (msg && regExp) { msg = msg.replace(regExp, '%c$&'); // '$&' inserts the matched substring. console.log(""+msg+"", cssStr); } 

 function redLog(msg, regExp) { var cssStr = 'color: blue; font-size: x-large'; if (msg && regExp) { msg = msg.replace(regExp, '%c$&%c'); // '$&' inserts the matched substring. console.log("%c"+msg+"", cssStr); } else { console.log(msg); } } redLog('Page1, Page2', /\d/g); 

Comments

0

For every %c there needs to be a style. In your case, if you only want the numbers to be highlighted then you could make your function generic by passing the highlight and normal colors as parameters as well:

function colorLog(string, regexp, style, normalStyle) { var msg = string.replace(regexp, function (s) { return "%c" + s + "%c" }); var css = [msg]; var occurances = string.match(regexp).length; while (css.length < occurances * 2) css = css.concat([style, normalStyle]); console.log.apply(console, css); } 

And then you call it like this:

colorLog('Page-1, 23rd-Page, Page-3', /\d+/g, 'color:blue', 'color:black'); 

The idea is to create an array out of strings and flatten it out using apply. You could further simplify your call by passing only the color names and create the style string inside the function.

You can do a multi-line with different colors by making just a minimal changes.

Demo: http://jsfiddle.net/abhitalks/ydLmtm3a/4/

.

Comments

0

Thanks very much, @Markai and @abhitalks, "console.log.apply(console, args)" is indeed the key to my problem. Below is my solution inspired by Markai.

function colorLog(str, regExp, style, normalStyle) { if (str && regExp) { var css = [], i = 1, // css[0] is reserved for msg msg = str.replace(regExp, function (m) { css[i++] = style; css[i++] = normalStyle; return '%c' + m + '%c'; }); css[0] = msg; console.log.apply(console, css); } else { console.log(str); } } function redLog(str, regExp) { colorLog(str, regExp, 'color:red', 'color:black'); } redLog('Page-1, 23rd-Page, Page-3', /\d+/g);

Comments

0

Сan even shorter:

string='';//random string for painting //color classifier - 6 types of non-breaking space: for(let i=120;i--;) string+=`${'\u180E\u200B\u200C\u200D\u2060\uFEFF'[6*Math.random()^0]}${'+-0'[3*Math.random()^0]}`; css = [string];//preparing an array for spread //we are returning the replaced string in css[0], using as the second argument .replace() a arrow function (which writes to a global variables): css[0] = css[0].replace(/(\u180E[\+\-0])|(\u200B[\+\-0])|(\u200C[\+\-0])|(\u200D[\+\-0])|(\u2060[\+\-0])|(\uFEFF[\+\-0])/g, (match, $1, $2, $3, $4, $5, $6) => { if ($1) {css.push('color: blue;')} if ($2) {css.push('color: red;')} if ($3) {css.push('color: green;')} if ($4) {css.push('color: yellow;')} if ($5) {css.push('color: magenta;')} if ($6) {css.push('color: cyan;')} return`%c${match}`});//so that neighboring '%c' do not overlap console.log(...css); 

Here we do not use flags and explicit loops. We use only one function. You can write instructions of multiple choice for global variable css[] (like a 'switch...case') on one line:

css.push(`color: ${'blue red green yellow magenta cyan'.split(' ')[Math.log2(+('0b'+[$6, $5, $4, $3, $2, $1].map(e=>+!!e).join('')))]};`); 

– in the first step array of regex capturing groups transformed at bit field, further we find log2(field), which is the position in the array of colors at RPN. So length of the function is 5 lines, not counting the first 2 lines containing 'random()' for test (which you can also write on one line using recursion:

css = [(s=>(f = (i, recursion =_=>(s+=`${'\u180E\u200B\u200C\u200D\u2060\uFEFF'[6*Math.random()^0]}${'+-0'[3*Math.random()^0]}`, f(--i)))=>!i? s :recursion())(120))('')]; 

).

Thus, we can use in theory max up to 6! = 720 colors, i.e. you need &h1003/6! = 23302 groups for a standard palette with a depth of 24 bits.

Open a console by browser on this page and run:

(a => (a.type = 'text/javascript', a.id = 'demo_console', a.innerHTML = `const css = [(s=>(f = (i, recursion =_=>(s+=\`$\{'\u180E\u200B\u200C\u200D\u2060\uFEFF'[6*Math.random()^0]}$\{'+-0'[3*Math.random()^0]}\`, f(--i)))=>!i? s :recursion())(120))('')]; css[0] = css[0].replace(/(\u180E[\+\-0])|(\u200B[\+\-0])|(\u200C[\+\-0])|(\u200D[\+\-0])|(\u2060[\+\-0])|(\uFEFF[\+\-0])/g, (match, $1, $2, $3, $4, $5, $6)=>\{	css.push(\`color: $\{'blue red green yellow magenta cyan'.split(' ')[Math.log2(+('0b'+[$6, $5, $4, $3, $2, $1].map(e=>+!!e).join('')))]};\`); return\`%c$\{match}\`}); console.log(...css);` ))(document.getElementsByTagName('head')[0].appendChild(document.createElement('script')))

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.