@nlabs/lex
Version:
139 lines (138 loc) • 19.6 kB
JavaScript
/**
* Copyright (c) 2018-Present, Nitrogen Labs, Inc.
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
*/ import { execa } from 'execa';
import { writeFileSync } from 'fs';
import capitalize from 'lodash/capitalize.js';
import isEmpty from 'lodash/isEmpty.js';
import merge from 'lodash/merge.js';
import { DateTime } from 'luxon';
import { join as pathJoin } from 'path';
import { createSpinner } from '../utils/app.js';
import { log } from '../utils/log.js';
export const createChangelog = async ({ cliName, config, outputFile = 'changelog.tmp.md', quiet })=>{
const spinner = createSpinner(quiet);
const gitOptions = [
'log',
'-3',
'--pretty=format:{"authorName": "%an", "authorEmail": "%ae", "hashShort": "%h", "hashFull": "%H", "tag": "%D", "date": %ct, "subject": "%s","comments": "%b"}[lex_break]'
];
try {
const git = await execa('git', gitOptions, {
encoding: 'utf8'
});
const { stdout } = git;
const entries = stdout.split('[lex_break]').filter((item)=>!!item);
const gitJson = JSON.parse(`[${entries.join(',')}]`.replace(/"[^"]*(?:""[^"]*)*"/g, (match)=>match.replace(/\n/g, '[lex_break]')));
const commitContent = {};
let version = 'Unreleased';
gitJson.forEach((item)=>{
const { comments, authorEmail, authorName, date, hashFull, hashShort, tag } = item;
const formatDate = DateTime.fromMillis(date).toFormat('DDD');
if (!isEmpty(tag)) {
const refs = tag.split(', ');
const updatedVersion = refs.reduce((ref, tagItem)=>{
let updatedRef = ref;
if (updatedRef === '' && tagItem.includes('tag: v')) {
updatedRef = tagItem.replace('tag: v', '').trim();
}
return updatedRef;
}, '');
if (!isEmpty(updatedVersion)) {
version = updatedVersion;
commitContent[version] = {
date: formatDate,
version: updatedVersion
};
}
}
if (!commitContent[version]) {
commitContent[version] = {
list: {}
};
}
const subjectLines = comments.split('[lex_break]');
const topics = {};
for(let idx = 0, len = subjectLines.length; idx < len; idx++){
const nextLine = subjectLines[idx];
const formatLine = nextLine.trim();
const headerPattern = /^(\w*)(?:\(([\w$.\- *]*)\))?: (.*)$/;
const matches = formatLine.match(headerPattern);
if (matches) {
const itemType = capitalize(matches[1]);
const itemScope = matches[2];
const itemDetails = matches[3];
const details = {
authorEmail,
authorName,
details: itemDetails,
hashFull,
hashShort,
type: itemType
};
if (!topics[itemScope]) {
topics[itemScope] = {
[itemType]: [
details
]
};
} else {
topics[itemScope][itemType].push(details);
}
}
}
commitContent[version] = merge(commitContent[version], {
list: topics
});
});
const formatLog = Object.keys(commitContent).reduce((content, versionKey)=>{
const { date, list = {}, version } = commitContent[versionKey];
const formatScopes = Object.keys(list);
let updatedContent = content;
const versionLabel = version ? version : 'Unreleased';
const headerLabels = [
versionLabel
];
if (date) {
headerLabels.push(`(${date})`);
}
updatedContent += `\n## ${headerLabels.join(' ')}\n`;
formatScopes.forEach((scopeName)=>{
updatedContent += `\n### ${scopeName}\n\n`;
// Get the topic name
const itemList = list[scopeName];
const itemNames = Object.keys(itemList);
itemNames.forEach((itemName)=>{
updatedContent += `* ${itemName}\n`;
itemList[itemName].forEach((changes)=>{
const { authorEmail, authorName, details, hashFull, hashShort } = changes;
const { gitUrl } = config;
let hash = `#${hashShort}`;
if (!isEmpty(gitUrl)) {
let commitPath = 'commits';
if (gitUrl.includes('github.com')) {
commitPath = 'commit';
}
hash = `[#${hashShort}](${gitUrl}/${commitPath}/${hashFull})`;
}
updatedContent += ` * ${details} ([${authorName}](mailto:${authorEmail}) in ${hash})\n`;
});
});
});
return updatedContent;
}, '# Changes\n');
const logFile = pathJoin(process.cwd(), outputFile);
writeFileSync(logFile, formatLog);
spinner.succeed('Git change log complete!');
// Kill process
return 0;
} catch (error) {
// Display error message
log(`\n${cliName} Error: ${error.message}`, 'error', quiet);
// Stop spinner
spinner.fail('Failed generating change log!');
// Kill process
return error.status;
}
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jcmVhdGUvY2hhbmdlbG9nLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChjKSAyMDE4LVByZXNlbnQsIE5pdHJvZ2VuIExhYnMsIEluYy5cbiAqIENvcHlyaWdodHMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLiBTZWUgdGhlIGFjY29tcGFueWluZyBMSUNFTlNFIGZpbGUgZm9yIHRlcm1zLlxuICovXG5pbXBvcnQge2V4ZWNhfSBmcm9tICdleGVjYSc7XG5pbXBvcnQge3dyaXRlRmlsZVN5bmN9IGZyb20gJ2ZzJztcbmltcG9ydCBjYXBpdGFsaXplIGZyb20gJ2xvZGFzaC9jYXBpdGFsaXplLmpzJztcbmltcG9ydCBpc0VtcHR5IGZyb20gJ2xvZGFzaC9pc0VtcHR5LmpzJztcbmltcG9ydCBtZXJnZSBmcm9tICdsb2Rhc2gvbWVyZ2UuanMnO1xuaW1wb3J0IHtEYXRlVGltZX0gZnJvbSAnbHV4b24nO1xuaW1wb3J0IHtqb2luIGFzIHBhdGhKb2lufSBmcm9tICdwYXRoJztcblxuXG5pbXBvcnQge2NyZWF0ZVNwaW5uZXJ9IGZyb20gJy4uL3V0aWxzL2FwcC5qcyc7XG5pbXBvcnQge2xvZ30gZnJvbSAnLi4vdXRpbHMvbG9nLmpzJztcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZUNoYW5nZWxvZyA9IGFzeW5jICh7Y2xpTmFtZSwgY29uZmlnLCBvdXRwdXRGaWxlID0gJ2NoYW5nZWxvZy50bXAubWQnLCBxdWlldH0pOiBQcm9taXNlPG51bWJlcj4gPT4ge1xuICBjb25zdCBzcGlubmVyID0gY3JlYXRlU3Bpbm5lcihxdWlldCk7XG5cbiAgY29uc3QgZ2l0T3B0aW9uczogc3RyaW5nW10gPSBbXG4gICAgJ2xvZycsXG4gICAgJy0zJyxcbiAgICAnLS1wcmV0dHk9Zm9ybWF0OntcImF1dGhvck5hbWVcIjogXCIlYW5cIiwgXCJhdXRob3JFbWFpbFwiOiBcIiVhZVwiLCBcImhhc2hTaG9ydFwiOiBcIiVoXCIsIFwiaGFzaEZ1bGxcIjogXCIlSFwiLCBcInRhZ1wiOiBcIiVEXCIsIFwiZGF0ZVwiOiAlY3QsIFwic3ViamVjdFwiOiBcIiVzXCIsXCJjb21tZW50c1wiOiBcIiViXCJ9W2xleF9icmVha10nXG4gIF07XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBnaXQgPSBhd2FpdCBleGVjYSgnZ2l0JywgZ2l0T3B0aW9ucywge2VuY29kaW5nOiAndXRmOCd9KTtcblxuICAgIGNvbnN0IHtzdGRvdXR9ID0gZ2l0O1xuICAgIGNvbnN0IGVudHJpZXM6IHN0cmluZ1tdID0gc3Rkb3V0LnNwbGl0KCdbbGV4X2JyZWFrXScpLmZpbHRlcigoaXRlbSkgPT4gISFpdGVtKTtcbiAgICBjb25zdCBnaXRKc29uID0gSlNPTi5wYXJzZShcbiAgICAgIChgWyR7ZW50cmllcy5qb2luKCcsJyl9XWApLnJlcGxhY2UoL1wiW15cIl0qKD86XCJcIlteXCJdKikqXCIvZywgKG1hdGNoKSA9PiBtYXRjaC5yZXBsYWNlKC9cXG4vZywgJ1tsZXhfYnJlYWtdJykpXG4gICAgKTtcbiAgICBjb25zdCBjb21taXRDb250ZW50ID0ge307XG4gICAgbGV0IHZlcnNpb246IHN0cmluZyA9ICdVbnJlbGVhc2VkJztcblxuICAgIGdpdEpzb24uZm9yRWFjaCgoaXRlbSkgPT4ge1xuICAgICAgY29uc3Qge2NvbW1lbnRzLCBhdXRob3JFbWFpbCwgYXV0aG9yTmFtZSwgZGF0ZSwgaGFzaEZ1bGwsIGhhc2hTaG9ydCwgdGFnfSA9IGl0ZW07XG4gICAgICBjb25zdCBmb3JtYXREYXRlOiBzdHJpbmcgPSBEYXRlVGltZS5mcm9tTWlsbGlzKGRhdGUpLnRvRm9ybWF0KCdEREQnKTtcblxuICAgICAgaWYoIWlzRW1wdHkodGFnKSkge1xuICAgICAgICBjb25zdCByZWZzID0gdGFnLnNwbGl0KCcsICcpO1xuICAgICAgICBjb25zdCB1cGRhdGVkVmVyc2lvbjogc3RyaW5nID0gcmVmcy5yZWR1Y2UoKHJlZjogc3RyaW5nLCB0YWdJdGVtOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICBsZXQgdXBkYXRlZFJlZjogc3RyaW5nID0gcmVmO1xuXG4gICAgICAgICAgaWYodXBkYXRlZFJlZiA9PT0gJycgJiYgdGFnSXRlbS5pbmNsdWRlcygndGFnOiB2JykpIHtcbiAgICAgICAgICAgIHVwZGF0ZWRSZWYgPSB0YWdJdGVtLnJlcGxhY2UoJ3RhZzogdicsICcnKS50cmltKCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIHVwZGF0ZWRSZWY7XG4gICAgICAgIH0sICcnKTtcblxuICAgICAgICBpZighaXNFbXB0eSh1cGRhdGVkVmVyc2lvbikpIHtcbiAgICAgICAgICB2ZXJzaW9uID0gdXBkYXRlZFZlcnNpb247XG4gICAgICAgICAgY29tbWl0Q29udGVudFt2ZXJzaW9uXSA9IHtkYXRlOiBmb3JtYXREYXRlLCB2ZXJzaW9uOiB1cGRhdGVkVmVyc2lvbn07XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYoIWNvbW1pdENvbnRlbnRbdmVyc2lvbl0pIHtcbiAgICAgICAgY29tbWl0Q29udGVudFt2ZXJzaW9uXSA9IHtsaXN0OiB7fX07XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHN1YmplY3RMaW5lczogc3RyaW5nW10gPSBjb21tZW50cy5zcGxpdCgnW2xleF9icmVha10nKTtcbiAgICAgIGNvbnN0IHRvcGljcyA9IHt9O1xuXG5cbiAgICAgIGZvcihsZXQgaWR4OiBudW1iZXIgPSAwLCBsZW46IG51bWJlciA9IHN1YmplY3RMaW5lcy5sZW5ndGg7IGlkeCA8IGxlbjsgaWR4KyspIHtcbiAgICAgICAgY29uc3QgbmV4dExpbmU6IHN0cmluZyA9IHN1YmplY3RMaW5lc1tpZHhdO1xuICAgICAgICBjb25zdCBmb3JtYXRMaW5lOiBzdHJpbmcgPSBuZXh0TGluZS50cmltKCk7XG4gICAgICAgIGNvbnN0IGhlYWRlclBhdHRlcm46IFJlZ0V4cCA9IC9eKFxcdyopKD86XFwoKFtcXHckLlxcLSAqXSopXFwpKT86ICguKikkLztcbiAgICAgICAgY29uc3QgbWF0Y2hlcyA9IGZvcm1hdExpbmUubWF0Y2goaGVhZGVyUGF0dGVybik7XG5cbiAgICAgICAgaWYobWF0Y2hlcykge1xuICAgICAgICAgIGNvbnN0IGl0ZW1UeXBlOiBzdHJpbmcgPSBjYXBpdGFsaXplKG1hdGNoZXNbMV0pO1xuICAgICAgICAgIGNvbnN0IGl0ZW1TY29wZTogc3RyaW5nID0gbWF0Y2hlc1syXTtcbiAgICAgICAgICBjb25zdCBpdGVtRGV0YWlsczogc3RyaW5nID0gbWF0Y2hlc1szXTtcbiAgICAgICAgICBjb25zdCBkZXRhaWxzID0ge1xuICAgICAgICAgICAgYXV0aG9yRW1haWwsXG4gICAgICAgICAgICBhdXRob3JOYW1lLFxuICAgICAgICAgICAgZGV0YWlsczogaXRlbURldGFpbHMsXG4gICAgICAgICAgICBoYXNoRnVsbCxcbiAgICAgICAgICAgIGhhc2hTaG9ydCxcbiAgICAgICAgICAgIHR5cGU6IGl0ZW1UeXBlXG4gICAgICAgICAgfTtcblxuICAgICAgICAgIGlmKCF0b3BpY3NbaXRlbVNjb3BlXSkge1xuICAgICAgICAgICAgdG9waWNzW2l0ZW1TY29wZV0gPSB7W2l0ZW1UeXBlXTogW2RldGFpbHNdfTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdG9waWNzW2l0ZW1TY29wZV1baXRlbVR5cGVdLnB1c2goZGV0YWlscyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbW1pdENvbnRlbnRbdmVyc2lvbl0gPSBtZXJnZShjb21taXRDb250ZW50W3ZlcnNpb25dLCB7bGlzdDogdG9waWNzfSk7XG4gICAgfSk7XG5cbiAgICBjb25zdCBmb3JtYXRMb2c6IHN0cmluZyA9IE9iamVjdC5rZXlzKGNvbW1pdENvbnRlbnQpLnJlZHVjZSgoY29udGVudDogc3RyaW5nLCB2ZXJzaW9uS2V5OiBzdHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IHtkYXRlLCBsaXN0ID0ge30sIHZlcnNpb259ID0gY29tbWl0Q29udGVudFt2ZXJzaW9uS2V5XTtcbiAgICAgIGNvbnN0IGZvcm1hdFNjb3Blczogc3RyaW5nW10gPSBPYmplY3Qua2V5cyhsaXN0KTtcbiAgICAgIGxldCB1cGRhdGVkQ29udGVudDogc3RyaW5nID0gY29udGVudDtcblxuICAgICAgY29uc3QgdmVyc2lvbkxhYmVsOiBzdHJpbmcgPSB2ZXJzaW9uID8gdmVyc2lvbiA6ICdVbnJlbGVhc2VkJztcbiAgICAgIGNvbnN0IGhlYWRlckxhYmVsczogc3RyaW5nW10gPSBbdmVyc2lvbkxhYmVsXTtcbiAgICAgIGlmKGRhdGUpIHtcbiAgICAgICAgaGVhZGVyTGFiZWxzLnB1c2goYCgke2RhdGV9KWApO1xuICAgICAgfVxuXG4gICAgICB1cGRhdGVkQ29udGVudCArPSBgXFxuIyMgJHtoZWFkZXJMYWJlbHMuam9pbignICcpfVxcbmA7XG5cbiAgICAgIGZvcm1hdFNjb3Blcy5mb3JFYWNoKChzY29wZU5hbWU6IHN0cmluZykgPT4ge1xuICAgICAgICB1cGRhdGVkQ29udGVudCArPSBgXFxuIyMjICR7c2NvcGVOYW1lfVxcblxcbmA7XG5cbiAgICAgICAgLy8gR2V0IHRoZSB0b3BpYyBuYW1lXG4gICAgICAgIGNvbnN0IGl0ZW1MaXN0ID0gbGlzdFtzY29wZU5hbWVdO1xuICAgICAgICBjb25zdCBpdGVtTmFtZXM6IHN0cmluZ1tdID0gT2JqZWN0LmtleXMoaXRlbUxpc3QpO1xuXG4gICAgICAgIGl0ZW1OYW1lcy5mb3JFYWNoKChpdGVtTmFtZTogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgdXBkYXRlZENvbnRlbnQgKz0gYCogJHtpdGVtTmFtZX1cXG5gO1xuXG4gICAgICAgICAgaXRlbUxpc3RbaXRlbU5hbWVdLmZvckVhY2goKGNoYW5nZXMpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHthdXRob3JFbWFpbCwgYXV0aG9yTmFtZSwgZGV0YWlscywgaGFzaEZ1bGwsIGhhc2hTaG9ydH0gPSBjaGFuZ2VzO1xuICAgICAgICAgICAgY29uc3Qge2dpdFVybH0gPSBjb25maWc7XG4gICAgICAgICAgICBsZXQgaGFzaDogc3RyaW5nID0gYCMke2hhc2hTaG9ydH1gO1xuXG4gICAgICAgICAgICBpZighaXNFbXB0eShnaXRVcmwpKSB7XG4gICAgICAgICAgICAgIGxldCBjb21taXRQYXRoOiBzdHJpbmcgPSAnY29tbWl0cyc7XG5cbiAgICAgICAgICAgICAgaWYoZ2l0VXJsLmluY2x1ZGVzKCdnaXRodWIuY29tJykpIHtcbiAgICAgICAgICAgICAgICBjb21taXRQYXRoID0gJ2NvbW1pdCc7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBoYXNoID0gYFsjJHtoYXNoU2hvcnR9XSgke2dpdFVybH0vJHtjb21taXRQYXRofS8ke2hhc2hGdWxsfSlgO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB1cGRhdGVkQ29udGVudCArPSBgICAqICR7ZGV0YWlsc30gKFske2F1dGhvck5hbWV9XShtYWlsdG86JHthdXRob3JFbWFpbH0pIGluICR7aGFzaH0pXFxuYDtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHVwZGF0ZWRDb250ZW50O1xuICAgIH0sICcjIENoYW5nZXNcXG4nKTtcblxuICAgIGNvbnN0IGxvZ0ZpbGU6IHN0cmluZyA9IHBhdGhKb2luKHByb2Nlc3MuY3dkKCksIG91dHB1dEZpbGUpO1xuICAgIHdyaXRlRmlsZVN5bmMobG9nRmlsZSwgZm9ybWF0TG9nKTtcbiAgICBzcGlubmVyLnN1Y2NlZWQoJ0dpdCBjaGFuZ2UgbG9nIGNvbXBsZXRlIScpO1xuXG4gICAgLy8gS2lsbCBwcm9jZXNzXG4gICAgcmV0dXJuIDA7XG4gIH0gY2F0Y2goZXJyb3IpIHtcbiAgICAvLyBEaXNwbGF5IGVycm9yIG1lc3NhZ2VcbiAgICBsb2coYFxcbiR7Y2xpTmFtZX0gRXJyb3I6ICR7ZXJyb3IubWVzc2FnZX1gLCAnZXJyb3InLCBxdWlldCk7XG5cbiAgICAvLyBTdG9wIHNwaW5uZXJcbiAgICBzcGlubmVyLmZhaWwoJ0ZhaWxlZCBnZW5lcmF0aW5nIGNoYW5nZSBsb2chJyk7XG5cbiAgICAvLyBLaWxsIHByb2Nlc3NcbiAgICByZXR1cm4gZXJyb3Iuc3RhdHVzO1xuICB9XG59OyJdLCJuYW1lcyI6WyJleGVjYSIsIndyaXRlRmlsZVN5bmMiLCJjYXBpdGFsaXplIiwiaXNFbXB0eSIsIm1lcmdlIiwiRGF0ZVRpbWUiLCJqb2luIiwicGF0aEpvaW4iLCJjcmVhdGVTcGlubmVyIiwibG9nIiwiY3JlYXRlQ2hhbmdlbG9nIiwiY2xpTmFtZSIsImNvbmZpZyIsIm91dHB1dEZpbGUiLCJxdWlldCIsInNwaW5uZXIiLCJnaXRPcHRpb25zIiwiZ2l0IiwiZW5jb2RpbmciLCJzdGRvdXQiLCJlbnRyaWVzIiwic3BsaXQiLCJmaWx0ZXIiLCJpdGVtIiwiZ2l0SnNvbiIsIkpTT04iLCJwYXJzZSIsInJlcGxhY2UiLCJtYXRjaCIsImNvbW1pdENvbnRlbnQiLCJ2ZXJzaW9uIiwiZm9yRWFjaCIsImNvbW1lbnRzIiwiYXV0aG9yRW1haWwiLCJhdXRob3JOYW1lIiwiZGF0ZSIsImhhc2hGdWxsIiwiaGFzaFNob3J0IiwidGFnIiwiZm9ybWF0RGF0ZSIsImZyb21NaWxsaXMiLCJ0b0Zvcm1hdCIsInJlZnMiLCJ1cGRhdGVkVmVyc2lvbiIsInJlZHVjZSIsInJlZiIsInRhZ0l0ZW0iLCJ1cGRhdGVkUmVmIiwiaW5jbHVkZXMiLCJ0cmltIiwibGlzdCIsInN1YmplY3RMaW5lcyIsInRvcGljcyIsImlkeCIsImxlbiIsImxlbmd0aCIsIm5leHRMaW5lIiwiZm9ybWF0TGluZSIsImhlYWRlclBhdHRlcm4iLCJtYXRjaGVzIiwiaXRlbVR5cGUiLCJpdGVtU2NvcGUiLCJpdGVtRGV0YWlscyIsImRldGFpbHMiLCJ0eXBlIiwicHVzaCIsImZvcm1hdExvZyIsIk9iamVjdCIsImtleXMiLCJjb250ZW50IiwidmVyc2lvbktleSIsImZvcm1hdFNjb3BlcyIsInVwZGF0ZWRDb250ZW50IiwidmVyc2lvbkxhYmVsIiwiaGVhZGVyTGFiZWxzIiwic2NvcGVOYW1lIiwiaXRlbUxpc3QiLCJpdGVtTmFtZXMiLCJpdGVtTmFtZSIsImNoYW5nZXMiLCJnaXRVcmwiLCJoYXNoIiwiY29tbWl0UGF0aCIsImxvZ0ZpbGUiLCJwcm9jZXNzIiwiY3dkIiwic3VjY2VlZCIsImVycm9yIiwibWVzc2FnZSIsImZhaWwiLCJzdGF0dXMiXSwibWFwcGluZ3MiOiJBQUFBOzs7Q0FHQyxHQUNELFNBQVFBLEtBQUssUUFBTyxRQUFRO0FBQzVCLFNBQVFDLGFBQWEsUUFBTyxLQUFLO0FBQ2pDLE9BQU9DLGdCQUFnQix1QkFBdUI7QUFDOUMsT0FBT0MsYUFBYSxvQkFBb0I7QUFDeEMsT0FBT0MsV0FBVyxrQkFBa0I7QUFDcEMsU0FBUUMsUUFBUSxRQUFPLFFBQVE7QUFDL0IsU0FBUUMsUUFBUUMsUUFBUSxRQUFPLE9BQU87QUFHdEMsU0FBUUMsYUFBYSxRQUFPLGtCQUFrQjtBQUM5QyxTQUFRQyxHQUFHLFFBQU8sa0JBQWtCO0FBRXBDLE9BQU8sTUFBTUMsa0JBQWtCLE9BQU8sRUFBQ0MsT0FBTyxFQUFFQyxNQUFNLEVBQUVDLGFBQWEsa0JBQWtCLEVBQUVDLEtBQUssRUFBQztJQUM3RixNQUFNQyxVQUFVUCxjQUFjTTtJQUU5QixNQUFNRSxhQUF1QjtRQUMzQjtRQUNBO1FBQ0E7S0FDRDtJQUVELElBQUk7UUFDRixNQUFNQyxNQUFNLE1BQU1qQixNQUFNLE9BQU9nQixZQUFZO1lBQUNFLFVBQVU7UUFBTTtRQUU1RCxNQUFNLEVBQUNDLE1BQU0sRUFBQyxHQUFHRjtRQUNqQixNQUFNRyxVQUFvQkQsT0FBT0UsS0FBSyxDQUFDLGVBQWVDLE1BQU0sQ0FBQyxDQUFDQyxPQUFTLENBQUMsQ0FBQ0E7UUFDekUsTUFBTUMsVUFBVUMsS0FBS0MsS0FBSyxDQUN4QixBQUFDLENBQUMsQ0FBQyxFQUFFTixRQUFRZCxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBRXFCLE9BQU8sQ0FBQyx3QkFBd0IsQ0FBQ0MsUUFBVUEsTUFBTUQsT0FBTyxDQUFDLE9BQU87UUFFN0YsTUFBTUUsZ0JBQWdC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