Skip to content

Instantly share code, notes, and snippets.

@davidgilbertson
Created January 6, 2018 05:28
Show Gist options
  • Save davidgilbertson/6eae478d9a197bfa1b4dfbef38f787e5 to your computer and use it in GitHub Desktop.
Save davidgilbertson/6eae478d9a197bfa1b4dfbef38f787e5 to your computer and use it in GitHub Desktop.
function logColor(color, args) {
console.log(`%c ${args.join(' ')}`, `color: ${color}`);
}
const log = {
aliceblue: (...args) => { logColor('aliceblue', args)},
antiquewhite: (...args) => { logColor('antiquewhite', args)},
aqua: (...args) => { logColor('aqua', args)},
aquamarine: (...args) => { logColor('aquamarine', args)},
azure: (...args) => { logColor('azure', args)},
beige: (...args) => { logColor('beige', args)},
bisque: (...args) => { logColor('bisque', args)},
black: (...args) => { logColor('black', args)},
blanchedalmond: (...args) => { logColor('blanchedalmond', args)},
blue: (...args) => { logColor('blue', args)},
blueviolet: (...args) => { logColor('blueviolet', args)},
brown: (...args) => { logColor('brown', args)},
burlywood: (...args) => { logColor('burlywood', args)},
cadetblue: (...args) => { logColor('cadetblue', args)},
chartreuse: (...args) => { logColor('chartreuse', args)},
chocolate: (...args) => { logColor('chocolate', args)},
coral: (...args) => { logColor('coral', args)},
cornflowerblue: (...args) => { logColor('cornflowerblue', args)},
cornsilk: (...args) => { logColor('cornsilk', args)},
crimson: (...args) => { logColor('crimson', args)},
cyan: (...args) => { logColor('cyan', args)},
darkblue: (...args) => { logColor('darkblue', args)},
darkcyan: (...args) => { logColor('darkcyan', args)},
darkgoldenrod: (...args) => { logColor('darkgoldenrod', args)},
darkgray: (...args) => { logColor('darkgray', args)},
darkgreen: (...args) => { logColor('darkgreen', args)},
darkgrey: (...args) => { logColor('darkgrey', args)},
darkkhaki: (...args) => { logColor('darkkhaki', args)},
darkmagenta: (...args) => { logColor('darkmagenta', args)},
darkolivegreen: (...args) => { logColor('darkolivegreen', args)},
darkorange: (...args) => { logColor('darkorange', args)},
darkorchid: (...args) => { logColor('darkorchid', args)},
darkred: (...args) => { logColor('darkred', args)},
darksalmon: (...args) => { logColor('darksalmon', args)},
darkseagreen: (...args) => { logColor('darkseagreen', args)},
darkslateblue: (...args) => { logColor('darkslateblue', args)},
darkslategray: (...args) => { logColor('darkslategray', args)},
darkslategrey: (...args) => { logColor('darkslategrey', args)},
darkturquoise: (...args) => { logColor('darkturquoise', args)},
darkviolet: (...args) => { logColor('darkviolet', args)},
deeppink: (...args) => { logColor('deeppink', args)},
deepskyblue: (...args) => { logColor('deepskyblue', args)},
dimgray: (...args) => { logColor('dimgray', args)},
dimgrey: (...args) => { logColor('dimgrey', args)},
dodgerblue: (...args) => { logColor('dodgerblue', args)},
firebrick: (...args) => { logColor('firebrick', args)},
floralwhite: (...args) => { logColor('floralwhite', args)},
forestgreen: (...args) => { logColor('forestgreen', args)},
fuchsia: (...args) => { logColor('fuchsia', args)},
gainsboro: (...args) => { logColor('gainsboro', args)},
ghostwhite: (...args) => { logColor('ghostwhite', args)},
gold: (...args) => { logColor('gold', args)},
goldenrod: (...args) => { logColor('goldenrod', args)},
gray: (...args) => { logColor('gray', args)},
green: (...args) => { logColor('green', args)},
greenyellow: (...args) => { logColor('greenyellow', args)},
grey: (...args) => { logColor('grey', args)},
honeydew: (...args) => { logColor('honeydew', args)},
hotpink: (...args) => { logColor('hotpink', args)},
indianred: (...args) => { logColor('indianred', args)},
indigo: (...args) => { logColor('indigo', args)},
ivory: (...args) => { logColor('ivory', args)},
khaki: (...args) => { logColor('khaki', args)},
lavender: (...args) => { logColor('lavender', args)},
lavenderblush: (...args) => { logColor('lavenderblush', args)},
lawngreen: (...args) => { logColor('lawngreen', args)},
lemonchiffon: (...args) => { logColor('lemonchiffon', args)},
lightblue: (...args) => { logColor('lightblue', args)},
lightcoral: (...args) => { logColor('lightcoral', args)},
lightcyan: (...args) => { logColor('lightcyan', args)},
lightgoldenrodyellow: (...args) => { logColor('lightgoldenrodyellow', args)},
lightgray: (...args) => { logColor('lightgray', args)},
lightgreen: (...args) => { logColor('lightgreen', args)},
lightgrey: (...args) => { logColor('lightgrey', args)},
lightpink: (...args) => { logColor('lightpink', args)},
lightsalmon: (...args) => { logColor('lightsalmon', args)},
lightseagreen: (...args) => { logColor('lightseagreen', args)},
lightskyblue: (...args) => { logColor('lightskyblue', args)},
lightslategray: (...args) => { logColor('lightslategray', args)},
lightslategrey: (...args) => { logColor('lightslategrey', args)},
lightsteelblue: (...args) => { logColor('lightsteelblue', args)},
lightyellow: (...args) => { logColor('lightyellow', args)},
lime: (...args) => { logColor('lime', args)},
limegreen: (...args) => { logColor('limegreen', args)},
linen: (...args) => { logColor('linen', args)},
magenta: (...args) => { logColor('magenta', args)},
maroon: (...args) => { logColor('maroon', args)},
mediumaquamarine: (...args) => { logColor('mediumaquamarine', args)},
mediumblue: (...args) => { logColor('mediumblue', args)},
mediumorchid: (...args) => { logColor('mediumorchid', args)},
mediumpurple: (...args) => { logColor('mediumpurple', args)},
mediumseagreen: (...args) => { logColor('mediumseagreen', args)},
mediumslateblue: (...args) => { logColor('mediumslateblue', args)},
mediumspringgreen: (...args) => { logColor('mediumspringgreen', args)},
mediumturquoise: (...args) => { logColor('mediumturquoise', args)},
mediumvioletred: (...args) => { logColor('mediumvioletred', args)},
midnightblue: (...args) => { logColor('midnightblue', args)},
mintcream: (...args) => { logColor('mintcream', args)},
mistyrose: (...args) => { logColor('mistyrose', args)},
moccasin: (...args) => { logColor('moccasin', args)},
navajowhite: (...args) => { logColor('navajowhite', args)},
navy: (...args) => { logColor('navy', args)},
oldlace: (...args) => { logColor('oldlace', args)},
olive: (...args) => { logColor('olive', args)},
olivedrab: (...args) => { logColor('olivedrab', args)},
orange: (...args) => { logColor('orange', args)},
orangered: (...args) => { logColor('orangered', args)},
orchid: (...args) => { logColor('orchid', args)},
palegoldenrod: (...args) => { logColor('palegoldenrod', args)},
palegreen: (...args) => { logColor('palegreen', args)},
paleturquoise: (...args) => { logColor('paleturquoise', args)},
palevioletred: (...args) => { logColor('palevioletred', args)},
papayawhip: (...args) => { logColor('papayawhip', args)},
peachpuff: (...args) => { logColor('peachpuff', args)},
peru: (...args) => { logColor('peru', args)},
pink: (...args) => { logColor('pink', args)},
plum: (...args) => { logColor('plum', args)},
powderblue: (...args) => { logColor('powderblue', args)},
purple: (...args) => { logColor('purple', args)},
red: (...args) => { logColor('red', args)},
rosybrown: (...args) => { logColor('rosybrown', args)},
royalblue: (...args) => { logColor('royalblue', args)},
saddlebrown: (...args) => { logColor('saddlebrown', args)},
salmon: (...args) => { logColor('salmon', args)},
sandybrown: (...args) => { logColor('sandybrown', args)},
seagreen: (...args) => { logColor('seagreen', args)},
seashell: (...args) => { logColor('seashell', args)},
sienna: (...args) => { logColor('sienna', args)},
silver: (...args) => { logColor('silver', args)},
skyblue: (...args) => { logColor('skyblue', args)},
slateblue: (...args) => { logColor('slateblue', args)},
slategray: (...args) => { logColor('slategray', args)},
slategrey: (...args) => { logColor('slategrey', args)},
snow: (...args) => { logColor('snow', args)},
springgreen: (...args) => { logColor('springgreen', args)},
steelblue: (...args) => { logColor('steelblue', args)},
tan: (...args) => { logColor('tan', args)},
teal: (...args) => { logColor('teal', args)},
thistle: (...args) => { logColor('thistle', args)},
tomato: (...args) => { logColor('tomato', args)},
turquoise: (...args) => { logColor('turquoise', args)},
violet: (...args) => { logColor('violet', args)},
wheat: (...args) => { logColor('wheat', args)},
white: (...args) => { logColor('white', args)},
whitesmoke: (...args) => { logColor('whitesmoke', args)},
yellow: (...args) => { logColor('yellow', args)},
yellowgreen: (...args) => { logColor('yellowgreen', args)},
};
// example
log.tomato('I am tomato');
log.chocolate('I am chocolate');
log.cornflowerblue('I am cornflowerblue');
log.darkcyan('I am darkcyan');
log.goldenrod('I am goldenrod');
@FalkF
Copy link

FalkF commented Jan 8, 2018

Copy link

ghost commented Jan 10, 2018

It's nice to see the power of metaprogramming in the wild 👍

@mkarnicki
Copy link

@josejbreijo Correct me if I'm wrong, but this is actually not metaprogramming (too bad, I hoped it was haha). The malicious JS script mentioned in the article (which I believe is what you're referring to) is hidden in a file under lib/ directory, which was not included on GitHub, but could (hypothetically) be published to an npm package - hence, the sources didn't match, and you simply wouldn't find the malicious code here. The source above is... literally what it is :).

@arun-cm
Copy link

arun-cm commented Jan 12, 2018

@ukari May I know why you are using proxy here ?

@Shahor
Copy link

Shahor commented Jan 12, 2018

@arun-cm Fewer LoC :)

That being said, you lose potential autocomplete when using the lib in the console thus reducing the developer experience :(
Also, no error handling on this Proxy on missing method calls (easily fixable)

@davidgilbertson
Copy link
Author

@brandonmcconnell - sure, why not:

function logColor(color, args) {
    console.log(`%c${args.join(' ')}`, `color: ${color}`);
}

const log = console.log;

log.aliceblue = (...args) => { logColor('aliceblue', args)};
log.antiquewhite = (...args) => { logColor('antiquewhite', args)};
log.aqua = (...args) => { logColor('aqua', args)};
log.aquamarine = (...args) => { logColor('aquamarine', args)};
log.azure = (...args) => { logColor('azure', args)};
log.beige = (...args) => { logColor('beige', args)};
log.bisque = (...args) => { logColor('bisque', args)};
log.black = (...args) => { logColor('black', args)};
log.blanchedalmond = (...args) => { logColor('blanchedalmond', args)};
log.blue = (...args) => { logColor('blue', args)};
log.blueviolet = (...args) => { logColor('blueviolet', args)};
log.brown = (...args) => { logColor('brown', args)};
log.burlywood = (...args) => { logColor('burlywood', args)};
log.cadetblue = (...args) => { logColor('cadetblue', args)};
log.chartreuse = (...args) => { logColor('chartreuse', args)};
log.chocolate = (...args) => { logColor('chocolate', args)};
log.coral = (...args) => { logColor('coral', args)};
log.cornflowerblue = (...args) => { logColor('cornflowerblue', args)};
log.cornsilk = (...args) => { logColor('cornsilk', args)};
log.crimson = (...args) => { logColor('crimson', args)};
log.cyan = (...args) => { logColor('cyan', args)};
log.darkblue = (...args) => { logColor('darkblue', args)};
log.darkcyan = (...args) => { logColor('darkcyan', args)};
log.darkgoldenrod = (...args) => { logColor('darkgoldenrod', args)};
log.darkgray = (...args) => { logColor('darkgray', args)};
log.darkgreen = (...args) => { logColor('darkgreen', args)};
log.darkgrey = (...args) => { logColor('darkgrey', args)};
log.darkkhaki = (...args) => { logColor('darkkhaki', args)};
log.darkmagenta = (...args) => { logColor('darkmagenta', args)};
log.darkolivegreen = (...args) => { logColor('darkolivegreen', args)};
log.darkorange = (...args) => { logColor('darkorange', args)};
log.darkorchid = (...args) => { logColor('darkorchid', args)};
log.darkred = (...args) => { logColor('darkred', args)};
log.darksalmon = (...args) => { logColor('darksalmon', args)};
log.darkseagreen = (...args) => { logColor('darkseagreen', args)};
log.darkslateblue = (...args) => { logColor('darkslateblue', args)};
log.darkslategray = (...args) => { logColor('darkslategray', args)};
log.darkslategrey = (...args) => { logColor('darkslategrey', args)};
log.darkturquoise = (...args) => { logColor('darkturquoise', args)};
log.darkviolet = (...args) => { logColor('darkviolet', args)};
log.deeppink = (...args) => { logColor('deeppink', args)};
log.deepskyblue = (...args) => { logColor('deepskyblue', args)};
log.dimgray = (...args) => { logColor('dimgray', args)};
log.dimgrey = (...args) => { logColor('dimgrey', args)};
log.dodgerblue = (...args) => { logColor('dodgerblue', args)};
log.firebrick = (...args) => { logColor('firebrick', args)};
log.floralwhite = (...args) => { logColor('floralwhite', args)};
log.forestgreen = (...args) => { logColor('forestgreen', args)};
log.fuchsia = (...args) => { logColor('fuchsia', args)};
log.gainsboro = (...args) => { logColor('gainsboro', args)};
log.ghostwhite = (...args) => { logColor('ghostwhite', args)};
log.gold = (...args) => { logColor('gold', args)};
log.goldenrod = (...args) => { logColor('goldenrod', args)};
log.gray = (...args) => { logColor('gray', args)};
log.green = (...args) => { logColor('green', args)};
log.greenyellow = (...args) => { logColor('greenyellow', args)};
log.grey = (...args) => { logColor('grey', args)};
log.honeydew = (...args) => { logColor('honeydew', args)};
log.hotpink = (...args) => { logColor('hotpink', args)};
log.indianred = (...args) => { logColor('indianred', args)};
log.indigo = (...args) => { logColor('indigo', args)};
log.ivory = (...args) => { logColor('ivory', args)};
log.khaki = (...args) => { logColor('khaki', args)};
log.lavender = (...args) => { logColor('lavender', args)};
log.lavenderblush = (...args) => { logColor('lavenderblush', args)};
log.lawngreen = (...args) => { logColor('lawngreen', args)};
log.lemonchiffon = (...args) => { logColor('lemonchiffon', args)};
log.lightblue = (...args) => { logColor('lightblue', args)};
log.lightcoral = (...args) => { logColor('lightcoral', args)};
log.lightcyan = (...args) => { logColor('lightcyan', args)};
log.lightgoldenrodyellow = (...args) => { logColor('lightgoldenrodyellow', args)};
log.lightgray = (...args) => { logColor('lightgray', args)};
log.lightgreen = (...args) => { logColor('lightgreen', args)};
log.lightgrey = (...args) => { logColor('lightgrey', args)};
log.lightpink = (...args) => { logColor('lightpink', args)};
log.lightsalmon = (...args) => { logColor('lightsalmon', args)};
log.lightseagreen = (...args) => { logColor('lightseagreen', args)};
log.lightskyblue = (...args) => { logColor('lightskyblue', args)};
log.lightslategray = (...args) => { logColor('lightslategray', args)};
log.lightslategrey = (...args) => { logColor('lightslategrey', args)};
log.lightsteelblue = (...args) => { logColor('lightsteelblue', args)};
log.lightyellow = (...args) => { logColor('lightyellow', args)};
log.lime = (...args) => { logColor('lime', args)};
log.limegreen = (...args) => { logColor('limegreen', args)};
log.linen = (...args) => { logColor('linen', args)};
log.magenta = (...args) => { logColor('magenta', args)};
log.maroon = (...args) => { logColor('maroon', args)};
log.mediumaquamarine = (...args) => { logColor('mediumaquamarine', args)};
log.mediumblue = (...args) => { logColor('mediumblue', args)};
log.mediumorchid = (...args) => { logColor('mediumorchid', args)};
log.mediumpurple = (...args) => { logColor('mediumpurple', args)};
log.mediumseagreen = (...args) => { logColor('mediumseagreen', args)};
log.mediumslateblue = (...args) => { logColor('mediumslateblue', args)};
log.mediumspringgreen = (...args) => { logColor('mediumspringgreen', args)};
log.mediumturquoise = (...args) => { logColor('mediumturquoise', args)};
log.mediumvioletred = (...args) => { logColor('mediumvioletred', args)};
log.midnightblue = (...args) => { logColor('midnightblue', args)};
log.mintcream = (...args) => { logColor('mintcream', args)};
log.mistyrose = (...args) => { logColor('mistyrose', args)};
log.moccasin = (...args) => { logColor('moccasin', args)};
log.navajowhite = (...args) => { logColor('navajowhite', args)};
log.navy = (...args) => { logColor('navy', args)};
log.oldlace = (...args) => { logColor('oldlace', args)};
log.olive = (...args) => { logColor('olive', args)};
log.olivedrab = (...args) => { logColor('olivedrab', args)};
log.orange = (...args) => { logColor('orange', args)};
log.orangered = (...args) => { logColor('orangered', args)};
log.orchid = (...args) => { logColor('orchid', args)};
log.palegoldenrod = (...args) => { logColor('palegoldenrod', args)};
log.palegreen = (...args) => { logColor('palegreen', args)};
log.paleturquoise = (...args) => { logColor('paleturquoise', args)};
log.palevioletred = (...args) => { logColor('palevioletred', args)};
log.papayawhip = (...args) => { logColor('papayawhip', args)};
log.peachpuff = (...args) => { logColor('peachpuff', args)};
log.peru = (...args) => { logColor('peru', args)};
log.pink = (...args) => { logColor('pink', args)};
log.plum = (...args) => { logColor('plum', args)};
log.powderblue = (...args) => { logColor('powderblue', args)};
log.purple = (...args) => { logColor('purple', args)};
log.red = (...args) => { logColor('red', args)};
log.rosybrown = (...args) => { logColor('rosybrown', args)};
log.royalblue = (...args) => { logColor('royalblue', args)};
log.saddlebrown = (...args) => { logColor('saddlebrown', args)};
log.salmon = (...args) => { logColor('salmon', args)};
log.sandybrown = (...args) => { logColor('sandybrown', args)};
log.seagreen = (...args) => { logColor('seagreen', args)};
log.seashell = (...args) => { logColor('seashell', args)};
log.sienna = (...args) => { logColor('sienna', args)};
log.silver = (...args) => { logColor('silver', args)};
log.skyblue = (...args) => { logColor('skyblue', args)};
log.slateblue = (...args) => { logColor('slateblue', args)};
log.slategray = (...args) => { logColor('slategray', args)};
log.slategrey = (...args) => { logColor('slategrey', args)};
log.snow = (...args) => { logColor('snow', args)};
log.springgreen = (...args) => { logColor('springgreen', args)};
log.steelblue = (...args) => { logColor('steelblue', args)};
log.tan = (...args) => { logColor('tan', args)};
log.teal = (...args) => { logColor('teal', args)};
log.thistle = (...args) => { logColor('thistle', args)};
log.tomato = (...args) => { logColor('tomato', args)};
log.turquoise = (...args) => { logColor('turquoise', args)};
log.violet = (...args) => { logColor('violet', args)};
log.wheat = (...args) => { logColor('wheat', args)};
log.white = (...args) => { logColor('white', args)};
log.whitesmoke = (...args) => { logColor('whitesmoke', args)};
log.yellow = (...args) => { logColor('yellow', args)};
log.yellowgreen = (...args) => { logColor('yellowgreen', args)};

// example
log.tomato('I am tomato');
log.chocolate('I am chocolate');
log.cornflowerblue('I am cornflowerblue');
log.darkcyan('I am darkcyan');
log.goldenrod('I am goldenrod');
log('I am without color');

@jeffwklein
Copy link

we can still cut down on code here while still taking the strict whitelist approach

const logColor = (color, args) => (
  console.log(`%c ${args.join(' ')}`, `color: ${color}`)
)

const colors = [
  'aliceblue',
  'antiquewhite',
  'aqua',
  'aquamarine',
  'azure',
  'beige',
  'bisque',
  'black',
  'blanchedalmond',
  'blue',
  'blueviolet',
  'brown',
  'burlywood',
  'cadetblue',
  'chartreuse',
  'chocolate',
  'coral',
  'cornflowerblue',
  'cornsilk',
  'crimson',
  'cyan',
  'darkblue',
  'darkcyan',
  'darkgoldenrod',
  'darkgray',
  'darkgreen',
  'darkgrey',
  'darkkhaki',
  'darkmagenta',
  'darkolivegreen',
  'darkorange',
  'darkorchid',
  'darkred',
  'darksalmon',
  'darkseagreen',
  'darkslateblue',
  'darkslategray',
  'darkslategrey',
  'darkturquoise',
  'darkviolet',
  'deeppink',
  'deepskyblue',
  'dimgray',
  'dimgrey',
  'dodgerblue',
  'firebrick',
  'floralwhite',
  'forestgreen',
  'fuchsia',
  'gainsboro',
  'ghostwhite',
  'gold',
  'goldenrod',
  'gray',
  'green',
  'greenyellow',
  'grey',
  'honeydew',
  'hotpink',
  'indianred',
  'indigo',
  'ivory',
  'khaki',
  'lavender',
  'lavenderblush',
  'lawngreen',
  'lemonchiffon',
  'lightblue',
  'lightcoral',
  'lightcyan',
  'lightgoldenrodyellow',
  'lightgray',
  'lightgreen',
  'lightgrey',
  'lightpink',
  'lightsalmon',
  'lightseagreen',
  'lightskyblue',
  'lightslategray',
  'lightslategrey',
  'lightsteelblue',
  'lightyellow',
  'lime',
  'limegreen',
  'linen',
  'magenta',
  'maroon',
  'mediumaquamarine',
  'mediumblue',
  'mediumorchid',
  'mediumpurple',
  'mediumseagreen',
  'mediumslateblue',
  'mediumspringgreen',
  'mediumturquoise',
  'mediumvioletred',
  'midnightblue',
  'mintcream',
  'mistyrose',
  'moccasin',
  'navajowhite',
  'navy',
  'oldlace',
  'olive',
  'olivedrab',
  'orange',
  'orangered',
  'orchid',
  'palegoldenrod',
  'palegreen',
  'paleturquoise',
  'palevioletred',
  'papayawhip',
  'peachpuff',
  'peru',
  'pink',
  'plum',
  'powderblue',
  'purple',
  'red',
  'rosybrown',
  'royalblue',
  'saddlebrown',
  'salmon',
  'sandybrown',
  'seagreen',
  'seashell',
  'sienna',
  'silver',
  'skyblue',
  'slateblue',
  'slategray',
  'slategrey',
  'snow',
  'springgreen',
  'steelblue',
  'tan',
  'teal',
  'thistle',
  'tomato',
  'turquoise',
  'violet',
  'wheat',
  'white',
  'whitesmoke',
  'yellow',
  'yellowgreen',
]

const log = {}
colors.forEach(color => log[color] = (...args) => logColor(color, args))

// example
log.tomato('I am tomato');
log.chocolate('I am chocolate');
log.cornflowerblue('I am cornflowerblue');
log.darkcyan('I am darkcyan');
log.goldenrod('I am goldenrod');

@xaosxaos
Copy link

xaosxaos commented Dec 5, 2018

log.rebeccapurple = (...args) => { logColor('rebeccapurple', args)};

@thirdwheel
Copy link

thirdwheel commented Dec 12, 2018

log.chucknorris = (...args) => { logColor('chucknorris', args) };

EDIT: aww, doesn't work :(
image

@sukiletxe
Copy link

Can anybody explain this code to me? Everything is so innocently looking for somebody who doesn't understand much js, that I'm confused.

@teschmitt
Copy link

@sukiletxe: There is nothing malicious going on in this part of the code. This is simply the alibi for including it in other packages: easy log colors, hooray! @josejbreijo described above where the funny business is hidden:

@josejbreijo […] The malicious JS script mentioned in the article (which I believe is what you're referring to) is hidden in a file under lib/ directory, which was not included on GitHub, but could (hypothetically) be published to an npm package - hence, the sources didn't match, and you simply wouldn't find the malicious code here. The source above is... literally what it is :).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment