node-swatch-names
Version:
Swatch-names automatically and consistently names Photoshop swatches to be shared among frontend developers and designers. Exports colors to SASS variables and JSON for use in code.
207 lines (150 loc) • 20 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.encode = exports.decode = undefined;
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var _colorConvert = require('color-convert');
var _colorConvert2 = _interopRequireDefault(_colorConvert);
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }
function _toArray(arr) { return Array.isArray(arr) ? arr : Array.from(arr); }
const PROTOCOL_SIZE = 1;
const NUMBER_OF_COLORS_SIZE = 1;
const HEADER_SIZE = PROTOCOL_SIZE + NUMBER_OF_COLORS_SIZE;
const COLOR_SIZE = 5;
const COLOR_MODES = {
rgb: 0,
hsb: 1
};
// ### DECODING ###
/**
* Decodes ACO file
*
* @param data - A Buffer with the swatch file contents
* @returns {Array} - Array of decoded color swatches: [{name: 'red', hex: '#ff0000', r: 255, g: 0, b: 0}, ...]
*/
const decode = data => {
const parts = data.match(/.{1,4}/g);
var _parts = _toArray(parts);
const numberOfColorsHex = _parts[1],
rest = _parts.slice(2);
// Let's skip the v1 protocol.
const numberOfColors = parseInt(numberOfColorsHex, 16);
const protocolOneSize = HEADER_SIZE + numberOfColors * COLOR_SIZE;
const protocolTwoColorsChunks = rest.slice(protocolOneSize);
function split(chunks) {
let getHex, hex, rgb;
var _chunks = _toArray(chunks);
const colorSpace = _chunks[0],
w = _chunks[1],
x = _chunks[2],
y = _chunks[3],
nameSizeHex = _chunks[6],
rest = _chunks.slice(7);
const nameSize = parseInt(nameSizeHex, 16);
const name = rest.slice(0, nameSize - 1).map(s => String.fromCharCode(parseInt(s.toString(16), 16))).join('');
const mode = parseInt(colorSpace, 16);
switch (mode) {
case COLOR_MODES.rgb:
{
getHex = color => _lodash2.default.padStart(Math.floor(parseInt(color, 16) / 256).toString(16), 2, '0');
hex = `#${getHex(w)}${getHex(x)}${getHex(y)}`;
rgb = _colorConvert2.default.hex.rgb(hex);
break;
}
case COLOR_MODES.hsb:
{
const h = parseInt(w, 16) / 182.04;
const s = parseInt(x, 16) / 655.35;
const v = parseInt(y, 16) / 655.35;
rgb = _colorConvert2.default.hsv.rgb([h, s, v]);
hex = '#' + _colorConvert2.default.rgb.hex(rgb);
break;
}
default:
throw new Error('Unsupported color mode. Make sure you create your swatches as RGB or HSB values in Photoshop.');
}
hex = hex.toUpperCase();
var _rgb = rgb,
_rgb2 = _slicedToArray(_rgb, 3);
const r = _rgb2[0],
g = _rgb2[1],
b = _rgb2[2];
const color = { name, hex, r, g, b };
const nextColor = rest.slice(nameSize);
return nextColor.length ? [color].concat(_toConsumableArray(split(nextColor))) : [color];
}
return split(protocolTwoColorsChunks);
};
// ### ENCODING ###
//ACO files take 16 bit words.
const writeValue = value => {
const buffer = Buffer.alloc(2);
buffer.writeUInt16BE(value, 0);
return buffer;
};
//Convenient way to write RGB integer values. Expected with this multiplier.
const writeRGBValue = value => {
return writeValue(value < 128 ? value * 256 : 255 + value * 256);
};
const hexToRgb = hex => {
const match = hex.toString(16).match(/^#([a-f0-9]{6}|[a-f0-9]{3})$/i);
if (!match) {
return [0, 0, 0];
}
let colorString = match[1];
// Parse short version hex format also
if (colorString.length === 3) {
colorString = colorString.split('').map(char => char + char).join('');
}
const integer = parseInt(colorString, 16);
const r = integer >> 16 & 0xFF;
const g = integer >> 8 & 0xFF;
const b = integer & 0xFF;
return [r, g, b];
};
const writeColors = (colors, writeNames = false) => {
let buffer = Buffer.alloc(0);
colors.forEach(color => {
try {
const hex = color.hex;
const name = color.name || hex;
//Parse RGB
const rgb = hexToRgb(hex).filter(value => !isNaN(value));
buffer = Buffer.concat([buffer, writeValue(0)]); //Write 0, for RGB color space
rgb.forEach(c => buffer = Buffer.concat([buffer, writeRGBValue(c)]));
buffer = Buffer.concat([buffer, writeValue(0)]); //Pad (we need w, x, y, and z values. RGB only has w, x, y - so z is zero.
// Only required in v2 ACO
if (writeNames) {
buffer = Buffer.concat([buffer, writeValue(0)]);
buffer = Buffer.concat([buffer, writeValue(name.length + 1)]);
[].concat(_toConsumableArray(name)).forEach(s => buffer = Buffer.concat([buffer, writeValue(s.charCodeAt(0))]));
buffer = Buffer.concat([buffer, writeValue(0)]);
}
} catch (e) {
throw e;
}
});
return buffer;
};
const encode = colors => {
if (!Array.isArray(colors) || !colors.length) {
throw new Error('Invalid argument supplied to encode(), expecting an array of objects: [{name: "color-name", hex: "#ffff00"}, ...]');
}
let aco = Buffer.alloc(0);
// Write version 1 ACO
aco = Buffer.concat([aco, writeValue(1)]);
aco = Buffer.concat([aco, writeValue(colors.length)]);
aco = Buffer.concat([aco, writeColors(colors)]);
// Version 2 ACO
aco = Buffer.concat([aco, writeValue(2)]);
aco = Buffer.concat([aco, writeValue(colors.length)]);
aco = Buffer.concat([aco, writeColors(colors, true)]);
return aco;
};
exports.decode = decode;
exports.encode = encode;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvYWNvLmpzIl0sIm5hbWVzIjpbIlBST1RPQ09MX1NJWkUiLCJOVU1CRVJfT0ZfQ09MT1JTX1NJWkUiLCJIRUFERVJfU0laRSIsIkNPTE9SX1NJWkUiLCJDT0xPUl9NT0RFUyIsInJnYiIsImhzYiIsImRlY29kZSIsImRhdGEiLCJwYXJ0cyIsIm1hdGNoIiwibnVtYmVyT2ZDb2xvcnNIZXgiLCJyZXN0IiwibnVtYmVyT2ZDb2xvcnMiLCJwYXJzZUludCIsInByb3RvY29sT25lU2l6ZSIsInByb3RvY29sVHdvQ29sb3JzQ2h1bmtzIiwic2xpY2UiLCJzcGxpdCIsImNodW5rcyIsImdldEhleCIsImhleCIsImNvbG9yU3BhY2UiLCJ3IiwieCIsInkiLCJuYW1lU2l6ZUhleCIsIm5hbWVTaXplIiwibmFtZSIsIm1hcCIsInMiLCJTdHJpbmciLCJmcm9tQ2hhckNvZGUiLCJ0b1N0cmluZyIsImpvaW4iLCJtb2RlIiwiY29sb3IiLCJwYWRTdGFydCIsIk1hdGgiLCJmbG9vciIsImgiLCJ2IiwiaHN2IiwiRXJyb3IiLCJ0b1VwcGVyQ2FzZSIsInIiLCJnIiwiYiIsIm5leHRDb2xvciIsImxlbmd0aCIsIndyaXRlVmFsdWUiLCJ2YWx1ZSIsImJ1ZmZlciIsIkJ1ZmZlciIsImFsbG9jIiwid3JpdGVVSW50MTZCRSIsIndyaXRlUkdCVmFsdWUiLCJoZXhUb1JnYiIsImNvbG9yU3RyaW5nIiwiY2hhciIsImludGVnZXIiLCJ3cml0ZUNvbG9ycyIsImNvbG9ycyIsIndyaXRlTmFtZXMiLCJmb3JFYWNoIiwiZmlsdGVyIiwiaXNOYU4iLCJjb25jYXQiLCJjIiwiY2hhckNvZGVBdCIsImUiLCJlbmNvZGUiLCJBcnJheSIsImlzQXJyYXkiLCJhY28iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBOzs7O0FBQ0E7Ozs7Ozs7Ozs7QUFFQSxNQUFNQSxnQkFBZ0IsQ0FBdEI7QUFDQSxNQUFNQyx3QkFBd0IsQ0FBOUI7QUFDQSxNQUFNQyxjQUFjRixnQkFB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QixPQUFNckIsT0FBT2MsTUFBUCxDQUFjLENBQUNPLEdBQUQsRUFBTWIsWUFBWUMsTUFBWixFQUFvQixJQUFwQixDQUFOLENBQWQsQ0FBTjs7QUFFQSxRQUFPWSxHQUFQO0FBQ0EsQ0FuQkQ7O1FBcUJRbkUsTSxHQUFBQSxNO1FBQVFnRSxNLEdBQUFBLE0iLCJmaWxlIjoiYWNvLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGNvbnZlcnQgZnJvbSAnY29sb3ItY29udmVydCc7XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuXG5jb25zdCBQUk9UT0NPTF9TSVpFID0gMTtcbmNvbnN0IE5VTUJFUl9PRl9DT0xPUlNfU0laRSA9IDE7XG5jb25zdCBIRUFERVJfU0laRSA9IFBST1RPQ09MX1NJWkUgKyBOVU1CRVJfT0ZfQ09MT1JTX1NJWkU7XG5jb25zdCBDT0xPUl9TSVpFID0gNTtcbmNvbnN0IENPTE9SX01PREVTID0ge1xuXHRyZ2I6IDAsXG5cdGhzYjogMVxufTtcblxuLy8gIyMjIERFQ09ESU5HICMjI1xuXG4vKipcbiAqIERlY29kZXMgQUNPIGZpbGVcbiAqXG4gKiBAcGFyYW0gZGF0YSAtIEEgQnVmZmVyIHdpdGggdGhlIHN3YXRjaCBmaWxlIGNvbnRlbnRzXG4gKiBAcmV0dXJucyB7QXJyYXl9IC0gQXJyYXkgb2YgZGVjb2RlZCBjb2xvciBzd2F0Y2hlczogW3tuYW1lOiAncmVkJywgaGV4OiAnI2ZmMDAwMCcsIHI6IDI1NSwgZzogMCwgYjogMH0sIC4uLl1cbiAqL1xuY29uc3QgZGVjb2RlID0gKGRhdGEpID0+IHtcblx0Y29uc3QgcGFydHMgPSBkYXRhLm1hdGNoKC8uezEsNH0vZyk7XG5cdGNvbnN0IFsgLCBudW1iZXJPZkNvbG9yc0hleCwgLi4ucmVzdF0gPSBwYXJ0cztcblxuXHQvLyBMZXQncyBza2lwIHRoZSB2MSBwcm90b2NvbC5cblx0Y29uc3QgbnVtYmVyT2ZDb2xvcnMgPSAgcGFyc2VJbnQobnVtYmVyT2ZDb2xvcnNIZXgsIDE2KTtcblx0Y29uc3QgcHJvdG9jb2xPbmVTaXplID0gSEVBREVSX1NJWkUgKyBudW1iZXJPZkNvbG9ycyAqIENPTE9SX1NJWkU7XG5cdGNvbnN0IHByb3RvY29sVHdvQ29sb3JzQ2h1bmtzID0gcmVzdC5zbGljZShwcm90b2NvbE9uZVNpemUpO1xuXG5cdGZ1bmN0aW9uIHNwbGl0KGNodW5rcykge1xuXG5cdFx0bGV0IGdldEhleCwgaGV4LCByZ2I7XG5cblx0XHRjb25zdCBbY29sb3JTcGFjZSwgdywgeCwgeSwgLCAsIG5hbWVTaXplSGV4LCAuLi5yZXN0XSA9IGNodW5rcztcblx0XHRjb25zdCBuYW1lU2l6ZSA9IHBhcnNlSW50KG5hbWVTaXplSGV4LCAxNik7XG5cdFx0Y29uc3QgbmFtZSA9IHJlc3Quc2xpY2UoMCwgbmFtZVNpemUgLSAxKVxuXHRcdFx0Lm1hcChzID0+IFN0cmluZy5mcm9tQ2hhckNvZGUocGFyc2VJbnQocy50b1N0cmluZygxNiksIDE2KSkpXG5cdFx0XHQuam9pbignJyk7XG5cblx0XHRjb25zdCBtb2RlID0gcGFyc2VJbnQoY29sb3JTcGFjZSwgMTYpO1xuXHRcdHN3aXRjaCAobW9kZSkge1xuXHRcdFx0Y2FzZSBDT0xPUl9NT0RFUy5yZ2I6IHtcblx0XHRcdFx0Z2V0SGV4ID0gKGNvbG9yKSA9PiBfLnBhZFN0YXJ0KE1hdGguZmxvb3IocGFyc2VJbnQoY29sb3IsIDE2KSAvIDI1NikudG9TdHJpbmcoMTYpLCAyLCAnMCcpO1xuXHRcdFx0XHRoZXggPSBgIyR7Z2V0SGV4KHcpfSR7Z2V0SGV4KHgpfSR7Z2V0SGV4KHkpfWA7XG5cdFx0XHRcdHJnYiA9IGNvbnZlcnQuaGV4LnJnYihoZXgpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblxuXHRcdFx0Y2FzZSBDT0xPUl9NT0RFUy5oc2I6IHtcblx0XHRcdFx0Y29uc3QgaCA9IHBhcnNlSW50KHcsIDE2KSAvIDE4Mi4wNDtcblx0XHRcdFx0Y29uc3QgcyA9IHBhcnNlSW50KHgsIDE2KSAvIDY1NS4zNTtcblx0XHRcdFx0Y29uc3QgdiA9IHBhcnNlSW50KHksIDE2KSAvIDY1NS4zNTtcblxuXHRcdFx0XHRyZ2IgPSBjb252ZXJ0Lmhzdi5yZ2IoW2gsIHMsIHZdKTtcblx0XHRcdFx0aGV4ID0gJyMnICsgY29udmVydC5yZ2IuaGV4KHJnYik7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXG5cdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ1Vuc3VwcG9ydGVkIGNvbG9yIG1vZGUuIE1ha2Ugc3VyZSB5b3UgY3JlYXRlIHlvdXIgc3dhdGNoZXMgYXMgUkdCIG9yIEhTQiB2YWx1ZXMgaW4gUGhvdG9zaG9wLicpO1xuXG5cdFx0fVxuXG5cdFx0aGV4ID0gaGV4LnRvVXBwZXJDYXNlKCk7XG5cblx0XHRjb25zdCBbciwgZywgYl0gPSByZ2I7XG5cdFx0Y29uc3QgY29sb3IgPSB7bmFtZSwgaGV4LCByLCBnLCBifTtcblx0XHRjb25zdCBuZXh0Q29sb3IgPSByZXN0LnNsaWNlKG5hbWVTaXplKTtcblxuXHRcdHJldHVybiBuZXh0Q29sb3IubGVuZ3RoID8gW2NvbG9yLCAuLi5zcGxpdChuZXh0Q29sb3IpXSA6IFtjb2xvcl07XG5cdH1cblxuXHRyZXR1cm4gc3BsaXQocHJvdG9jb2xUd29Db2xvcnNDaHVua3MpO1xufTtcblxuXG4vLyAjIyMgRU5DT0RJTkcgIyMjXG5cbi8vQUNPIGZpbGVzIHRha2UgMTYgYml0IHdvcmRzLlxuY29uc3Qgd3JpdGVWYWx1ZSA9ICh2YWx1ZSkgPT4ge1xuXHRjb25zdCBidWZmZXIgPSBCdWZmZXIuYWxsb2MoMik7XG5cdGJ1ZmZlci53cml0ZVVJbnQxNkJFKHZhbHVlLCAwKTtcblx0cmV0dXJuIGJ1ZmZlcjtcbn07XG5cbi8vQ29udmVuaWVudCB3YXkgdG8gd3JpdGUgUkdCIGludGVnZXIgdmFsdWVzLiBFeHBlY3RlZCB3aXRoIHRoaXMgbXVsdGlwbGllci5cbmNvbnN0IHdyaXRlUkdCVmFsdWUgPSAodmFsdWUpID0+IHtcblx0cmV0dXJuIHdyaXRlVmFsdWUodmFsdWUgPCAxMjggPyB2YWx1ZSAqIDI1NiA6IDI1NSArIHZhbHVlICogMjU2KTtcbn07XG5cbmNvbnN0IGhleFRvUmdiID0gKGhleCkgPT4ge1xuXG5cdGNvbnN0IG1hdGNoID0gaGV4LnRvU3RyaW5nKDE2KS5tYXRjaCgvXiMoW2EtZjAtOV17Nn18W2EtZjAtOV17M30pJC9pKTtcblxuXHRpZiAoIW1hdGNoKSB7XG5cdFx0cmV0dXJuIFswLCAwLCAwXTtcblx0fVxuXG5cdGxldCBjb2xvclN0cmluZyA9IG1hdGNoWzFdO1xuXG5cdC8vIFBhcnNlIHNob3J0IHZlcnNpb24gaGV4IGZvcm1hdCBhbHNvXG5cdGlmIChjb2xvclN0cmluZy5sZW5ndGggPT09IDMpIHtcblx0XHRjb2xvclN0cmluZyA9IGNvbG9yU3RyaW5nLnNwbGl0KCcnKS5tYXAoY2hhciA9PiBjaGFyICsgY2hhcikuam9pbignJyk7XG5cdH1cblxuXHRjb25zdCBpbnRlZ2VyID0gcGFyc2VJbnQoY29sb3JTdHJpbmcsIDE2KTtcblx0Y29uc3QgciA9IChpbnRlZ2VyID4+IDE2KSAmIDB4RkY7XG5cdGNvbnN0IGcgPSAoaW50ZWdlciA+PiA4KSAmIDB4RkY7XG5cdGNvbnN0IGIgPSBpbnRlZ2VyICYgMHhGRjtcblxuXHRyZXR1cm4gW3IsIGcsIGJdO1xufTtcblxuY29uc3Qgd3JpdGVDb2xvcnMgPSAoY29sb3JzLCB3cml0ZU5hbWVzID0gZmFsc2UpID0+IHtcblxuXHRsZXQgYnVmZmVyID0gQnVmZmVyLmFsbG9jKDApO1xuXG5cdGNvbG9ycy5mb3JFYWNoKChjb2xvcikgPT4ge1xuXHRcdHRyeSB7XG5cdFx0XHRjb25zdCBoZXggPSBjb2xvci5oZXg7XG5cdFx0XHRjb25zdCBuYW1lID0gY29sb3IubmFtZSB8fCBoZXg7XG5cblx0XHRcdC8vUGFyc2UgUkdCXG5cdFx0XHRjb25zdCByZ2IgPSBoZXhUb1JnYihoZXgpLmZpbHRlcigodmFsdWUpID0+ICFpc05hTih2YWx1ZSkpO1xuXG5cdFx0XHRidWZmZXIgPSBCdWZmZXIuY29uY2F0KFtidWZmZXIsIHdyaXRlVmFsdWUoMCldKTsgLy9Xcml0ZSAwLCBmb3IgUkdCIGNvbG9yIHNwYWNlXG5cdFx0XHRyZ2IuZm9yRWFjaCgoYykgPT4gYnVmZmVyID0gQnVmZmVyLmNvbmNhdChbYnVmZmVyLCB3cml0ZVJHQlZhbHVlKGMpXSkpO1xuXHRcdFx0YnVmZmVyID0gQnVmZmVyLmNvbmNhdChbYnVmZmVyLCB3cml0ZVZhbHVlKDApXSk7IC8vUGFkICh3ZSBuZWVkIHcsIHgsIHksIGFuZCB6IHZhbHVlcy4gUkdCIG9ubHkgaGFzIHcsIHgsIHkgLSBzbyB6IGlzIHplcm8uXG5cblx0XHRcdC8vIE9ubHkgcmVxdWlyZWQgaW4gdjIgQUNPXG5cdFx0XHRpZiAod3JpdGVOYW1lcykge1xuXHRcdFx0XHRidWZmZXIgPSBCdWZmZXIuY29uY2F0KFtidWZmZXIsIHdyaXRlVmFsdWUoMCldKTtcblx0XHRcdFx0YnVmZmVyID0gQnVmZmVyLmNvbmNhdChbYnVmZmVyLCB3cml0ZVZhbHVlKG5hbWUubGVuZ3RoICsgMSldKTtcblx0XHRcdFx0Wy4uLm5hbWVdLmZvckVhY2goKHMpID0+IGJ1ZmZlciA9IEJ1ZmZlci5jb25jYXQoW2J1ZmZlciwgd3JpdGVWYWx1ZShzLmNoYXJDb2RlQXQoMCkpXSkpO1xuXHRcdFx0XHRidWZmZXIgPSBCdWZmZXIuY29uY2F0KFtidWZmZXIsIHdyaXRlVmFsdWUoMCldKTtcblx0XHRcdH1cblx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHR0aHJvdyBlO1xuXHRcdH1cblx0fSk7XG5cblx0cmV0dXJuIGJ1ZmZlcjtcbn07XG5cbmNvbnN0IGVuY29kZSA9IChjb2xvcnMpID0+IHtcblxuXHRpZiAoIUFycmF5LmlzQXJyYXkoY29sb3JzKSB8fCAhY29sb3JzLmxlbmd0aCkge1xuXHRcdHRocm93IG5ldyBFcnJvcignSW52YWxpZCBhcmd1bWVudCBzdXBwbGllZCB0byBlbmNvZGUoKSwgZXhwZWN0aW5nIGFuIGFycmF5IG9mIG9iamVjdHM6IFt7bmFtZTogXCJjb2xvci1uYW1lXCIsIGhleDogXCIjZmZmZjAwXCJ9LCAuLi5dJyk7XG5cdH1cblxuXHRsZXQgYWNvID0gQnVmZmVyLmFsbG9jKDApO1xuXG5cdC8vIFdyaXRlIHZlcnNpb24gMSBBQ09cblx0YWNvID0gQnVmZmVyLmNvbmNhdChbYWNvLCB3cml0ZVZhbHVlKDEpXSk7XG5cdGFjbyA9IEJ1ZmZlci5jb25jYXQoW2Fjbywgd3JpdGVWYWx1ZShjb2xvcnMubGVuZ3RoKV0pO1xuXHRhY28gPSBCdWZmZXIuY29uY2F0KFthY28sIHdyaXRlQ29sb3JzKGNvbG9ycyldKTtcblxuXHQvLyBWZXJzaW9uIDIgQUNPXG5cdGFjbyA9IEJ1ZmZlci5jb25jYXQoW2Fjbywgd3JpdGVWYWx1ZSgyKV0pO1xuXHRhY28gPSBCdWZmZXIuY29uY2F0KFthY28sIHdyaXRlVmFsdWUoY29sb3JzLmxlbmd0aCldKTtcblx0YWNvID0gQnVmZmVyLmNvbmNhdChbYWNvLCB3cml0ZUNvbG9ycyhjb2xvcnMsIHRydWUpXSk7XG5cblx0cmV0dXJuIGFjbztcbn07XG5cbmV4cG9ydCB7ZGVjb2RlLCBlbmNvZGV9O1xuIl19