@cucumber/gherkin
Version:
Gherkin parser
264 lines • 39.5 kB
JavaScript
import { StepKeywordType } from '@cucumber/messages';
import { compareStepKeywords } from './compareStepKeywords.js';
import { NoSuchLanguageException } from './Errors.js';
import DIALECTS from './gherkin-languages.json' with { type: 'json' };
import { TokenType } from './Parser.js';
const DIALECT_DICT = DIALECTS;
const DEFAULT_DOC_STRING_SEPARATOR = /^(```[`]*)(.*)/;
function addKeywordTypeMappings(h, keywords, keywordType) {
for (const k of keywords) {
if (!(k in h)) {
h[k] = [];
}
h[k].push(keywordType);
}
}
export default class GherkinInMarkdownTokenMatcher {
defaultDialectName;
dialect;
dialectName;
nonStarStepKeywords;
stepRegexp;
headerRegexp;
activeDocStringSeparator;
indentToRemove;
matchedFeatureLine;
keywordTypesMap;
constructor(defaultDialectName = 'en') {
this.defaultDialectName = defaultDialectName;
this.dialect = DIALECT_DICT[defaultDialectName];
this.nonStarStepKeywords = []
.concat(this.dialect.given)
.concat(this.dialect.when)
.concat(this.dialect.then)
.concat(this.dialect.and)
.concat(this.dialect.but)
.filter((value, index, self) => value !== '* ' && self.indexOf(value) === index)
.sort(compareStepKeywords);
this.initializeKeywordTypes();
this.stepRegexp = new RegExp(`${KeywordPrefix.BULLET}(${this.nonStarStepKeywords.map(escapeRegExp).join('|')})`);
const headerKeywords = []
.concat(this.dialect.feature)
.concat(this.dialect.background)
.concat(this.dialect.rule)
.concat(this.dialect.scenarioOutline)
.concat(this.dialect.scenario)
.concat(this.dialect.examples)
.filter((value, index, self) => self.indexOf(value) === index);
this.headerRegexp = new RegExp(`${KeywordPrefix.HEADER}(${headerKeywords.map(escapeRegExp).join('|')})`);
this.reset();
}
changeDialect(newDialectName, location) {
const newDialect = DIALECT_DICT[newDialectName];
if (!newDialect) {
throw NoSuchLanguageException.create(newDialectName, location);
}
this.dialectName = newDialectName;
this.dialect = newDialect;
this.initializeKeywordTypes();
}
initializeKeywordTypes() {
this.keywordTypesMap = {};
addKeywordTypeMappings(this.keywordTypesMap, this.dialect.given, StepKeywordType.CONTEXT);
addKeywordTypeMappings(this.keywordTypesMap, this.dialect.when, StepKeywordType.ACTION);
addKeywordTypeMappings(this.keywordTypesMap, this.dialect.then, StepKeywordType.OUTCOME);
addKeywordTypeMappings(this.keywordTypesMap, [].concat(this.dialect.and).concat(this.dialect.but), StepKeywordType.CONJUNCTION);
}
// We've made a deliberate choice not to support `# language: [ISO 639-1]` headers or similar
// in Markdown. Users should specify a language globally. This can be done in
// cucumber-js using the --language [ISO 639-1] option.
match_Language(token) {
if (!token) {
throw new Error('no token');
}
return false;
}
match_Empty(token) {
let result = false;
if (token.line.isEmpty) {
result = true;
}
if (!this.match_TagLine(token) &&
!this.match_FeatureLine(token) &&
!this.match_ScenarioLine(token) &&
!this.match_BackgroundLine(token) &&
!this.match_ExamplesLine(token) &&
!this.match_RuleLine(token) &&
!this.match_TableRow(token) &&
!this.match_Comment(token) &&
!this.match_Language(token) &&
!this.match_DocStringSeparator(token) &&
!this.match_EOF(token) &&
!this.match_StepLine(token)) {
// neutered
result = true;
}
if (result) {
token.matchedType = TokenType.Empty;
}
return this.setTokenMatched(token, null, result);
}
match_Other(token) {
const text = token.line.getLineText(this.indentToRemove); // take the entire line, except removing DocString indents
token.matchedType = TokenType.Other;
token.matchedText = text;
token.matchedIndent = 0;
return this.setTokenMatched(token, null, true);
}
match_Comment(token) {
let result = false;
if (token.line.startsWith('|')) {
const tableCells = token.line.getTableCells();
if (this.isGfmTableSeparator(tableCells)) {
result = true;
}
}
return this.setTokenMatched(token, null, result);
}
match_DocStringSeparator(token) {
const match = token.line.trimmedLineText.match(this.activeDocStringSeparator);
const [, newSeparator, mediaType] = match || [];
let result = false;
if (newSeparator) {
if (this.activeDocStringSeparator === DEFAULT_DOC_STRING_SEPARATOR) {
this.activeDocStringSeparator = new RegExp(`^(${newSeparator})$`);
this.indentToRemove = token.line.indent;
}
else {
this.activeDocStringSeparator = DEFAULT_DOC_STRING_SEPARATOR;
}
token.matchedKeyword = newSeparator;
token.matchedType = TokenType.DocStringSeparator;
token.matchedText = mediaType || '';
result = true;
}
return this.setTokenMatched(token, null, result);
}
match_EOF(token) {
let result = false;
if (token.isEof) {
token.matchedType = TokenType.EOF;
result = true;
}
return this.setTokenMatched(token, null, result);
}
match_FeatureLine(token) {
if (this.matchedFeatureLine) {
return this.setTokenMatched(token, null, false);
}
// We first try to match "# Feature: blah"
let result = this.matchTitleLine(KeywordPrefix.HEADER, this.dialect.feature, ':', token, TokenType.FeatureLine);
// If we didn't match "# Feature: blah", we still match this line
// as a FeatureLine.
// The reason for this is that users may not want to be constrained by having this as their fist line.
if (!result) {
token.matchedType = TokenType.FeatureLine;
token.matchedText = token.line.trimmedLineText;
result = this.setTokenMatched(token, null, true);
}
this.matchedFeatureLine = result;
return result;
}
match_BackgroundLine(token) {
return this.matchTitleLine(KeywordPrefix.HEADER, this.dialect.background, ':', token, TokenType.BackgroundLine);
}
match_RuleLine(token) {
return this.matchTitleLine(KeywordPrefix.HEADER, this.dialect.rule, ':', token, TokenType.RuleLine);
}
match_ScenarioLine(token) {
return (this.matchTitleLine(KeywordPrefix.HEADER, this.dialect.scenario, ':', token, TokenType.ScenarioLine) ||
this.matchTitleLine(KeywordPrefix.HEADER, this.dialect.scenarioOutline, ':', token, TokenType.ScenarioLine));
}
match_ExamplesLine(token) {
return this.matchTitleLine(KeywordPrefix.HEADER, this.dialect.examples, ':', token, TokenType.ExamplesLine);
}
match_StepLine(token) {
return this.matchTitleLine(KeywordPrefix.BULLET, this.nonStarStepKeywords, '', token, TokenType.StepLine);
}
matchTitleLine(prefix, keywords, keywordSuffix, token, matchedType) {
const regexp = new RegExp(`${prefix}(${keywords.map(escapeRegExp).join('|')})${keywordSuffix}(.*)`);
const match = token.line.match(regexp);
let indent = token.line.indent;
let result = false;
if (match) {
token.matchedType = matchedType;
token.matchedKeyword = match[2];
if (match[2] in this.keywordTypesMap) {
// only set the keyword type if this is a step keyword
if (this.keywordTypesMap[match[2]].length > 1) {
token.matchedKeywordType = StepKeywordType.UNKNOWN;
}
else {
token.matchedKeywordType = this.keywordTypesMap[match[2]][0];
}
}
token.matchedText = match[3].trim();
indent += match[1].length;
result = true;
}
return this.setTokenMatched(token, indent, result);
}
setTokenMatched(token, indent, matched) {
token.matchedGherkinDialect = this.dialectName;
token.matchedIndent = indent !== null ? indent : token.line == null ? 0 : token.line.indent;
token.location.column = token.matchedIndent + 1;
return matched;
}
match_TableRow(token) {
// Gherkin tables must be indented 2-5 spaces in order to be distinguidedn from non-Gherkin tables
if (token.line.lineText.match(/^\s\s\s?\s?\s?\|/)) {
const tableCells = token.line.getTableCells();
if (this.isGfmTableSeparator(tableCells)) {
return false;
}
token.matchedKeyword = '|';
token.matchedType = TokenType.TableRow;
token.matchedItems = tableCells;
return true;
}
return false;
}
isGfmTableSeparator(tableCells) {
const separatorValues = tableCells
.map((item) => item.text)
.filter((value) => value.match(/^:?-+:?$/));
return separatorValues.length > 0;
}
match_TagLine(token) {
const tags = [];
let m;
const re = /`(@[^`]+)`/g;
do {
m = re.exec(token.line.trimmedLineText);
if (m) {
tags.push({
column: token.line.indent + m.index + 2,
text: m[1],
});
}
} while (m);
if (tags.length === 0) {
return false;
}
token.matchedType = TokenType.TagLine;
token.matchedItems = tags;
return true;
}
reset() {
if (this.dialectName !== this.defaultDialectName) {
this.changeDialect(this.defaultDialectName);
}
this.activeDocStringSeparator = DEFAULT_DOC_STRING_SEPARATOR;
}
}
var KeywordPrefix;
(function (KeywordPrefix) {
// https://spec.commonmark.org/0.29/#bullet-list-marker
KeywordPrefix["BULLET"] = "^(\\s*[*+-]\\s*)";
KeywordPrefix["HEADER"] = "^(#{1,6}\\s)";
})(KeywordPrefix || (KeywordPrefix = {}));
// https://stackoverflow.com/questions/3115150/how-to-escape-regular-expression-special-characters-using-javascript
function escapeRegExp(text) {
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiR2hlcmtpbkluTWFya2Rvd25Ub2tlbk1hdGNoZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvR2hlcmtpbkluTWFya2Rvd25Ub2tlbk1hdGNoZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFpQixlQUFlLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQTtBQUNuRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQTtBQUU5RCxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxhQUFhLENBQUE7QUFDckQsT0FBTyxRQUFRLE1BQU0sMEJBQTBCLENBQUMsT0FBTyxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUE7QUFHckUsT0FBTyxFQUFjLFNBQVMsRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQUVuRCxNQUFNLFlBQVksR0FBK0IsUUFBUSxDQUFBO0FBQ3pELE1BQU0sNEJBQTRCLEdBQUcsZ0JBQWdCLENBQUE7QUFFckQsU0FBUyxzQkFBc0IsQ0FDN0IsQ0FBdUMsRUFDdkMsUUFBMkIsRUFDM0IsV0FBNEI7SUFFNUIsS0FBSyxNQUFNLENBQUMsSUFBSSxRQUFRLEVBQUUsQ0FBQztRQUN6QixJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNkLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUF1QixDQUFBO1FBQ2hDLENBQUM7UUFDRCxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFBO0lBQ3hCLENBQUM7QUFDSCxDQUFDO0FBRUQsTUFBTSxDQUFDLE9BQU8sT0FBTyw2QkFBNkI7SUFXbkIsa0JBQWtCO0lBVnZDLE9BQU8sQ0FBUztJQUNoQixXQUFXLENBQVE7SUFDVixtQkFBbUIsQ0FBVTtJQUM3QixVQUFVLENBQVE7SUFDbEIsWUFBWSxDQUFRO0lBQzdCLHdCQUF3QixDQUFRO0lBQ2hDLGNBQWMsQ0FBUTtJQUN0QixrQkFBa0IsQ0FB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LElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUE7UUFDN0MsQ0FBQztRQUNELElBQUksQ0FBQyx3QkFBd0IsR0FBRyw0QkFBNEIsQ0FBQTtJQUM5RCxDQUFDO0NBQ0Y7QUFFRCxJQUFLLGFBSUo7QUFKRCxXQUFLLGFBQWE7SUFDaEIsdURBQXVEO0lBQ3ZELDRDQUEyQixDQUFBO0lBQzNCLHdDQUF1QixDQUFBO0FBQ3pCLENBQUMsRUFKSSxhQUFhLEtBQWIsYUFBYSxRQUlqQjtBQUVELG1IQUFtSDtBQUNuSCxTQUFTLFlBQVksQ0FBQyxJQUFZO0lBQ2hDLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQywwQkFBMEIsRUFBRSxNQUFNLENBQUMsQ0FBQTtBQUN6RCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgdHlwZSBMb2NhdGlvbiwgU3RlcEtleXdvcmRUeXBlIH0gZnJvbSAnQGN1Y3VtYmVyL21lc3NhZ2VzJ1xuaW1wb3J0IHsgY29tcGFyZVN0ZXBLZXl3b3JkcyB9IGZyb20gJy4vY29tcGFyZVN0ZXBLZXl3b3Jkcy5qcydcbmltcG9ydCB0eXBlIERpYWxlY3QgZnJvbSAnLi9EaWFsZWN0LmpzJ1xuaW1wb3J0IHsgTm9TdWNoTGFuZ3VhZ2VFeGNlcHRpb24gfSBmcm9tICcuL0Vycm9ycy5qcydcbmltcG9ydCBESUFMRUNUUyBmcm9tICcuL2doZXJraW4tbGFuZ3VhZ2VzLmpzb24nIHdpdGggeyB0eXBlOiAnanNvbicgfVxuaW1wb3J0IHR5cGUgeyBJdGVtIH0gZnJvbSAnLi9JVG9rZW4uanMnXG5pbXBvcnQgdHlwZSBJVG9rZW5NYXRjaGVyIGZyb20gJy4vSVRva2VuTWF0Y2hlci5qcydcbmltcG9ydCB7IHR5cGUgVG9rZW4sIFRva2VuVHlwZSB9IGZyb20gJy4vUGFyc2VyLmpzJ1xuXG5jb25zdCBESUFMRUNUX0RJQ1Q6IHsgW2tleTogc3RyaW5nXTogRGlhbGVjdCB9ID0gRElBTEVDVFNcbmNvbnN0IERFRkFVTFRfRE9DX1NUUklOR19TRVBBUkFUT1IgPSAvXihgYGBbYF0qKSguKikvXG5cbmZ1bmN0aW9uIGFkZEtleXdvcmRUeXBlTWFwcGluZ3MoXG4gIGg6IHsgW2tleTogc3RyaW5nXTogU3RlcEtleXdvcmRUeXBlW10gfSxcbiAga2V5d29yZHM6IHJlYWRvbmx5IHN0cmluZ1tdLFxuICBrZXl3b3JkVHlwZTogU3RlcEtleXdvcmRUeXBlXG4pIHtcbiAgZm9yIChjb25zdCBrIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKCEoayBpbiBoKSkge1xuICAgICAgaFtrXSA9IFtdIGFzIFN0ZXBLZXl3b3JkVHlwZVtdXG4gICAgfVxuICAgIGhba10ucHVzaChrZXl3b3JkVHlwZSlcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBHaGVya2luSW5NYXJrZG93blRva2VuTWF0Y2hlciBpbXBsZW1lbnRzIElUb2tlbk1hdGNoZXI8VG9rZW5UeXBlPiB7XG4gIHByaXZhdGUgZGlhbGVjdDogRGlhbGVjdFxuICBwcml2YXRlIGRpYWxlY3ROYW1lOiBzdHJpbmdcbiAgcHJpdmF0ZSByZWFkb25seSBub25TdGFyU3RlcEtleXdvcmRzOiBzdHJpbmdbXVxuICBwcml2YXRlIHJlYWRvbmx5IHN0ZXBSZWdleHA6IFJlZ0V4cFxuICBwcml2YXRlIHJlYWRvbmx5IGhlYWRlclJlZ2V4cDogUmVnRXhwXG4gIHByaXZhdGUgYWN0aXZlRG9jU3RyaW5nU2VwYXJhdG9yOiBSZWdFeHBcbiAgcHJpdmF0ZSBpbmRlbnRUb1JlbW92ZTogbnVtYmVyXG4gIHByaXZhdGUgbWF0Y2hlZEZlYXR1cmVMaW5lOiBib29sZWFuXG4gIHByaXZhdGUga2V5d29yZFR5cGVzTWFwOiB7IFtrZXk6IHN0cmluZ106IFN0ZXBLZXl3b3JkVHlwZVtdIH1cblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IGRlZmF1bHREaWFsZWN0TmFtZTogc3RyaW5nID0gJ2VuJykge1xuICAgIHRoaXMuZGlhbGVjdCA9IERJQUxFQ1RfRElDVFtkZWZhdWx0RGlhbGVjdE5hbWVdXG4gICAgdGhpcy5ub25TdGFyU3RlcEtleXdvcmRzID0gW11cbiAgICAgIC5jb25jYXQodGhpcy5kaWFsZWN0LmdpdmVuKVxuICAgICAgLmNvbmNhdCh0aGlzLmRpYWxlY3Qud2hlbilcbiAgICAgIC5jb25jYXQodGhpcy5kaWFsZWN0LnRoZW4pXG4gICAgICAuY29uY2F0KHRoaXMuZGlhbGVjdC5hbmQpXG4gICAgICAuY29uY2F0KHRoaXMuZGlhbGVjdC5idXQpXG4gICAgICAuZmlsdGVyKCh2YWx1ZSwgaW5kZXgsIHNlbGYpID0+IHZhbHVlICE9PSAnKiAnICYmIHNlbGYuaW5kZXhPZih2YWx1ZSkgPT09IGluZGV4KVxuICAgICAgLnNvcnQoY29tcGFyZVN0ZXBLZXl3b3JkcylcbiAgICB0aGlzLmluaXRpYWxpemVLZXl3b3JkVHlwZXMoKVxuXG4gICAgdGhpcy5zdGVwUmVnZXhwID0gbmV3IFJlZ0V4cChcbiAgICAgIGAke0tleXdvcmRQcmVmaXguQlVMTEVUfSgke3RoaXMubm9uU3RhclN0ZXBLZXl3b3Jkcy5tYXAoZXNjYXBlUmVnRXhwKS5qb2luKCd8Jyl9KWBcbiAgICApXG5cbiAgICBjb25zdCBoZWFkZXJLZXl3b3JkcyA9IFtdXG4gICAgICAuY29uY2F0KHRoaXMuZGlhbGVjdC5mZWF0dXJlKVxuICAgICAgLmNvbmNhdCh0aGlzLmRpYWxlY3QuYmFja2dyb3VuZClcbiAgICAgIC5jb25jYXQodGhpcy5kaWFsZWN0LnJ1bGUpXG4gICAgICAuY29uY2F0KHRoaXMuZGlhbGVjdC5zY2VuYXJpb091dGxpbmUpXG4gICAgICAuY29uY2F0KHRoaXMuZGlhbGVjdC5zY2VuYXJpbylcbiAgICAgIC5jb25jYXQodGhpcy5kaWFsZWN0LmV4YW1wbGVzKVxuICAgICAgLmZpbHRlcigodmFsdWUsIGluZGV4LCBzZWxmKSA9PiBzZWxmLmluZGV4T2YodmFsdWUpID09PSBpbmRleClcblxuICAgIHRoaXMuaGVhZGVyUmVnZXhwID0gbmV3IFJlZ0V4cChcbiAgICAgIGAke0tleXdvcmRQcmVmaXguSEVBREVSfSgke2hlYWRlcktleXdvcmRzLm1hcChlc2NhcGVSZWdFeHApLmpvaW4oJ3wnKX0pYFxuICAgIClcblxuICAgIHRoaXMucmVzZXQoKVxuICB9XG5cbiAgY2hhbmdlRGlhbGVjdChuZXdEaWFsZWN0TmFtZTogc3RyaW5nLCBsb2NhdGlvbj86IExvY2F0aW9uKSB7XG4gICAgY29uc3QgbmV3RGlhbGVjdCA9IERJQUxFQ1RfRElDVFtuZXdEaWFsZWN0TmFtZV1cbiAgICBpZiAoIW5ld0RpYWxlY3QpIHtcbiAgICAgIHRocm93IE5vU3VjaExhbmd1YWdlRXhjZXB0aW9uLmNyZWF0ZShuZXdEaWFsZWN0TmFtZSwgbG9jYXRpb24pXG4gICAgfVxuXG4gICAgdGhpcy5kaWFsZWN0TmFtZSA9IG5ld0RpYWxlY3ROYW1lXG4gICAgdGhpcy5kaWFsZWN0ID0gbmV3RGlhbGVjdFxuICAgIHRoaXMuaW5pdGlhbGl6ZUtleXdvcmRUeXBlcygpXG4gIH1cblxuICBpbml0aWFsaXplS2V5d29yZFR5cGVzKCkge1xuICAgIHRoaXMua2V5d29yZFR5cGVzTWFwID0ge31cbiAgICBhZGRLZXl3b3JkVHlwZU1hcHBpbmdzKHRoaXMua2V5d29yZFR5cGVzTWFwLCB0aGlzLmRpYWxlY3QuZ2l2ZW4sIFN0ZXBLZXl3b3JkVHlwZS5DT05URVhUKVxuICAgIGFkZEtleXdvcmRUeXBlTWFwcGluZ3ModGhpcy5rZXl3b3JkVHlwZXNNYXAsIHRoaXMuZGlhbGVjdC53aGVuLCBTdGVwS2V5d29yZFR5cGUuQUNUSU9OKVxuICAgIGFkZEtleXdvcmRUeXBlTWFwcGluZ3ModGhpcy5rZXl3b3JkVHlwZXNNYXAsIHRoaXMuZGlhbGVjdC50aGVuLCBTdGVwS2V5d29yZFR5cGUuT1VUQ09NRSlcbiAgICBhZGRLZXl3b3JkVHlwZU1hcHBpbmdzKFxuICAgICAgdGhpcy5rZXl3b3JkVHlwZXNNYXAsXG4gICAgICBbXS5jb25jYXQodGhpcy5kaWFsZWN0LmFuZCkuY29uY2F0KHRoaXMuZGlhbGVjdC5idXQpLFxuICAgICAgU3RlcEtleXdvcmRUeXBlLkNPTkpVTkNUSU9OXG4gICAgKVxuICB9XG5cbiAgLy8gV2UndmUgbWFkZSBhIGRlbGliZXJhdGUgY2hvaWNlIG5vdCB0byBzdXBwb3J0IGAjIGxhbmd1YWdlOiBbSVNPIDYzOS0xXWAgaGVhZGVycyBvciBzaW1pbGFyXG4gIC8vIGluIE1hcmtkb3duLiBVc2VycyBzaG91bGQgc3BlY2lmeSBhIGxhbmd1YWdlIGdsb2JhbGx5LiBUaGlzIGNhbiBiZSBkb25lIGluXG4gIC8vIGN1Y3VtYmVyLWpzIHVzaW5nIHRoZSAtLWxhbmd1YWdlIFtJU08gNjM5LTFdIG9wdGlvbi5cbiAgbWF0Y2hfTGFuZ3VhZ2UodG9rZW46IFRva2VuKTogYm9vbGVhbiB7XG4gICAgaWYgKCF0b2tlbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdubyB0b2tlbicpXG4gICAgfVxuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgbWF0Y2hfRW1wdHkodG9rZW46IFRva2VuKTogYm9vbGVhbiB7XG4gICAgbGV0IHJlc3VsdCA9IGZhbHNlXG4gICAgaWYgKHRva2VuLmxpbmUuaXNFbXB0eSkge1xuICAgICAgcmVzdWx0ID0gdHJ1ZVxuICAgIH1cbiAgICBpZiAoXG4gICAgICAhdGhpcy5tYXRjaF9UYWdMaW5lKHRva2VuKSAmJlxuICAgICAgIXRoaXMubWF0Y2hfRmVhdHVyZUxpbmUodG9rZW4pICYmXG4gICAgICAhdGhpcy5tYXRjaF9TY2VuYXJpb0xpbmUodG9rZW4pICYmXG4gICAgICAhdGhpcy5tYXRjaF9CYWNrZ3JvdW5kTGluZSh0b2tlbikgJiZcbiAgICAgICF0aGlzLm1hdGNoX0V4YW1wbGVzTGluZSh0b2tlbikgJiZcbiAgICAgICF0aGlzLm1hdGNoX1J1bGVMaW5lKHRva2VuKSAmJlxuICAgICAgIXRoaXMubWF0Y2hfVGFibGVSb3codG9rZW4pICYmXG4gICAgICAhdGhpcy5tYXRjaF9Db21tZW50KHRva2VuKSAmJlxuICAgICAgIXRoaXMubWF0Y2hfTGFuZ3VhZ2UodG9rZW4pICYmXG4gICAgICAhdGhpcy5tYXRjaF9Eb2NTdHJpbmdTZXBhcmF0b3IodG9rZW4pICYmXG4gICAgICAhdGhpcy5tYXRjaF9FT0YodG9rZW4pICYmXG4gICAgICAhdGhpcy5tYXRjaF9TdGVwTGluZSh0b2tlbilcbiAgICApIHtcbiAgICAgIC8vIG5ldXRlcmVkXG4gICAgICByZXN1bHQgPSB0cnVlXG4gICAgfVxuXG4gICAgaWYgKHJlc3VsdCkge1xuICAgICAgdG9rZW4ubWF0Y2hlZFR5cGUgPSBUb2tlblR5cGUuRW1wdHlcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc2V0VG9rZW5NYXRjaGVkKHRva2VuLCBudWxsLCByZXN1bHQpXG4gIH1cblxuICBtYXRjaF9PdGhlcih0b2tlbjogVG9rZW4pOiBib29sZWFuIHtcbiAgICBjb25zdCB0ZXh0ID0gdG9rZW4ubGluZS5nZXRMaW5lVGV4dCh0aGlzLmluZGVudFRvUmVtb3ZlKSAvLyB0YWtlIHRoZSBlbnRpcmUgbGluZSwgZXhjZXB0IHJlbW92aW5nIERvY1N0cmluZyBpbmRlbnRzXG4gICAgdG9rZW4ubWF0Y2hlZFR5cGUgPSBUb2tlblR5cGUuT3RoZXJcbiAgICB0b2tlbi5tYXRjaGVkVGV4dCA9IHRleHRcbiAgICB0b2tlbi5tYXRjaGVkSW5kZW50ID0gMFxuICAgIHJldHVybiB0aGlzLnNldFRva2VuTWF0Y2hlZCh0b2tlbiwgbnVsbCwgdHJ1ZSlcbiAgfVxuXG4gIG1hdGNoX0NvbW1lbnQodG9rZW46IFRva2VuKTogYm9vbGVhbiB7XG4gICAgbGV0IHJlc3VsdCA9IGZhbHNlXG4gICAgaWYgKHRva2VuLmxpbmUuc3RhcnRzV2l0aCgnfCcpKSB7XG4gICAgICBjb25zdCB0YWJsZUNlbGxzID0gdG9rZW4ubGluZS5nZXRUYWJsZUNlbGxzKClcbiAgICAgIGlmICh0aGlzLmlzR2ZtVGFibGVTZXBhcmF0b3IodGFibGVDZWxscykpIHtcbiAgICAgICAgcmVzdWx0ID0gdHJ1ZVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5zZXRUb2tlbk1hdGNoZWQodG9rZW4sIG51bGwsIHJlc3VsdClcbiAgfVxuXG4gIG1hdGNoX0RvY1N0cmluZ1NlcGFyYXRvcih0b2tlbjogVG9rZW4pIHtcbiAgICBjb25zdCBtYXRjaCA9IHRva2VuLmxpbmUudHJpbW1lZExpbmVUZXh0Lm1hdGNoKHRoaXMuYWN0aXZlRG9jU3RyaW5nU2VwYXJhdG9yKVxuICAgIGNvbnN0IFssIG5ld1NlcGFyYXRvciwgbWVkaWFUeXBlXSA9IG1hdGNoIHx8IFtdXG4gICAgbGV0IHJlc3VsdCA9IGZhbHNlXG4gICAgaWYgKG5ld1NlcGFyYXRvcikge1xuICAgICAgaWYgKHRoaXMuYWN0aXZlRG9jU3RyaW5nU2VwYXJhdG9yID09PSBERUZBVUxUX0RPQ19TVFJJTkdfU0VQQVJBVE9SKSB7XG4gICAgICAgIHRoaXMuYWN0aXZlRG9jU3RyaW5nU2VwYXJhdG9yID0gbmV3IFJlZ0V4cChgXigke25ld1NlcGFyYXRvcn0pJGApXG4gICAgICAgIHRoaXMuaW5kZW50VG9SZW1vdmUgPSB0b2tlbi5saW5lLmluZGVudFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5hY3RpdmVEb2NTdHJpbmdTZXBhcmF0b3IgPSBERUZBVUxUX0RPQ19TVFJJTkdfU0VQQVJBVE9SXG4gICAgICB9XG5cbiAgICAgIHRva2VuLm1hdGNoZWRLZXl3b3JkID0gbmV3U2VwYXJhdG9yXG4gICAgICB0b2tlbi5tYXRjaGVkVHlwZSA9IFRva2VuVHlwZS5Eb2NTdHJpbmdTZXBhcmF0b3JcbiAgICAgIHRva2VuLm1hdGNoZWRUZXh0ID0gbWVkaWFUeXBlIHx8ICcnXG5cbiAgICAgIHJlc3VsdCA9IHRydWVcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc2V0VG9rZW5NYXRjaGVkKHRva2VuLCBudWxsLCByZXN1bHQpXG4gIH1cblxuICBtYXRjaF9FT0YodG9rZW46IFRva2VuKTogYm9vbGVhbiB7XG4gICAgbGV0IHJlc3VsdCA9IGZhbHNlXG4gICAgaWYgKHRva2VuLmlzRW9mKSB7XG4gICAgICB0b2tlbi5tYXRjaGVkVHlwZSA9IFRva2VuVHlwZS5FT0ZcbiAgICAgIHJlc3VsdCA9IHRydWVcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc2V0VG9rZW5NYXRjaGVkKHRva2VuLCBudWxsLCByZXN1bHQpXG4gIH1cblxuICBtYXRjaF9GZWF0dXJlTGluZSh0b2tlbjogVG9rZW4pOiBib29sZWFuIHtcbiAgICBpZiAodGhpcy5tYXRjaGVkRmVhdHVyZUxpbmUpIHtcbiAgICAgIHJldHVybiB0aGlzLnNldFRva2VuTWF0Y2hlZCh0b2tlbiwgbnVsbCwgZmFsc2UpXG4gICAgfVxuICAgIC8vIFdlIGZpcnN0IHRyeSB0byBtYXRjaCBcIiMgRmVhdHVyZTogYmxhaFwiXG4gICAgbGV0IHJlc3VsdCA9IHRoaXMubWF0Y2hUaXRsZUxpbmUoXG4gICAgICBLZXl3b3JkUHJlZml4LkhFQURFUixcbiAgICAgIHRoaXMuZGlhbGVjdC5mZWF0dXJlLFxuICAgICAgJzonLFxuICAgICAgdG9rZW4sXG4gICAgICBUb2tlblR5cGUuRmVhdHVyZUxpbmVcbiAgICApXG4gICAgLy8gSWYgd2UgZGlkbid0IG1hdGNoIFwiIyBGZWF0dXJlOiBibGFoXCIsIHdlIHN0aWxsIG1hdGNoIHRoaXMgbGluZVxuICAgIC8vIGFzIGEgRmVhdHVyZUxpbmUuXG4gICAgLy8gVGhlIHJlYXNvbiBmb3IgdGhpcyBpcyB0aGF0IHVzZXJzIG1heSBub3Qgd2FudCB0byBiZSBjb25zdHJhaW5lZCBieSBoYXZpbmcgdGhpcyBhcyB0aGVpciBmaXN0IGxpbmUuXG4gICAgaWYgKCFyZXN1bHQpIHtcbiAgICAgIHRva2VuLm1hdGNoZWRUeXBlID0gVG9rZW5UeXBlLkZlYXR1cmVMaW5lXG4gICAgICB0b2tlbi5tYXRjaGVkVGV4dCA9IHRva2VuLmxpbmUudHJpbW1lZExpbmVUZXh0XG4gICAgICByZXN1bHQgPSB0aGlzLnNldFRva2VuTWF0Y2hlZCh0b2tlbiwgbnVsbCwgdHJ1ZSlcbiAgICB9XG4gICAgdGhpcy5tYXRjaGVkRmVhdHVyZUxpbmUgPSByZXN1bHRcbiAgICByZXR1cm4gcmVzdWx0XG4gIH1cblxuICBtYXRjaF9CYWNrZ3JvdW5kTGluZSh0b2tlbjogVG9rZW4pOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5tYXRjaFRpdGxlTGluZShcbiAgICAgIEtleXdvcmRQcmVmaXguSEVBREVSLFxuICAgICAgdGhpcy5kaWFsZWN0LmJhY2tncm91bmQsXG4gICAgICAnOicsXG4gICAgICB0b2tlbixcbiAgICAgIFRva2VuVHlwZS5CYWNrZ3JvdW5kTGluZVxuICAgIClcbiAgfVxuXG4gIG1hdGNoX1J1bGVMaW5lKHRva2VuOiBUb2tlbik6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm1hdGNoVGl0bGVMaW5lKFxuICAgICAgS2V5d29yZFByZWZpeC5IRUFERVIsXG4gICAgICB0aGlzLmRpYWxlY3QucnVsZSxcbiAgICAgICc6JyxcbiAgICAgIHRva2VuLFxuICAgICAgVG9rZW5UeXBlLlJ1bGVMaW5lXG4gICAgKVxuICB9XG5cbiAgbWF0Y2hfU2NlbmFyaW9MaW5lKHRva2VuOiBUb2tlbik6IGJvb2xlYW4ge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLm1hdGNoVGl0bGVMaW5lKFxuICAgICAgICBLZXl3b3JkUHJlZml4LkhFQURFUixcbiAgICAgICAgdGhpcy5kaWFsZWN0LnNjZW5hcmlvLFxuICAgICAgICAnOicsXG4gICAgICAgIHRva2VuLFxuICAgICAgICBUb2tlblR5cGUuU2NlbmFyaW9MaW5lXG4gICAgICApIHx8XG4gICAgICB0aGlzLm1hdGNoVGl0bGVMaW5lKFxuICAgICAgICBLZXl3b3JkUHJlZml4LkhFQURFUixcbiAgICAgICAgdGhpcy5kaWFsZWN0LnNjZW5hcmlvT3V0bGluZSxcbiAgICAgICAgJzonLFxuICAgICAgICB0b2tlbixcbiAgICAgICAgVG9rZW5UeXBlLlNjZW5hcmlvTGluZVxuICAgICAgKVxuICAgIClcbiAgfVxuXG4gIG1hdGNoX0V4YW1wbGVzTGluZSh0b2tlbjogVG9rZW4pOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5tYXRjaFRpdGxlTGluZShcbiAgICAgIEtleXdvcmRQcmVmaXguSEVBREVSLFxuICAgICAgdGhpcy5kaWFsZWN0LmV4YW1wbGVzLFxuICAgICAgJzonLFxuICAgICAgdG9rZW4sXG4gICAgICBUb2tlblR5cGUuRXhhbXBsZXNMaW5lXG4gICAgKVxuICB9XG5cbiAgbWF0Y2hfU3RlcExpbmUodG9rZW46IFRva2VuKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMubWF0Y2hUaXRsZUxpbmUoXG4gICAgICBLZXl3b3JkUHJlZml4LkJVTExFVCxcbiAgICAgIHRoaXMubm9uU3RhclN0ZXBLZXl3b3JkcyxcbiAgICAgICcnLFxuICAgICAgdG9rZW4sXG4gICAgICBUb2tlblR5cGUuU3RlcExpbmVcbiAgICApXG4gIH1cblxuICBtYXRjaFRpdGxlTGluZShcbiAgICBwcmVmaXg6IEtleXdvcmRQcmVmaXgsXG4gICAga2V5d29yZHM6IHJlYWRvbmx5IHN0cmluZ1tdLFxuICAgIGtleXdvcmRTdWZmaXg6ICc6JyB8ICcnLFxuICAgIHRva2VuOiBUb2tlbixcbiAgICBtYXRjaGVkVHlwZTogVG9rZW5UeXBlXG4gICkge1xuICAgIGNvbnN0IHJlZ2V4cCA9IG5ldyBSZWdFeHAoXG4gICAgICBgJHtwcmVmaXh9KCR7a2V5d29yZHMubWFwKGVzY2FwZVJlZ0V4cCkuam9pbignfCcpfSkke2tleXdvcmRTdWZmaXh9KC4qKWBcbiAgICApXG4gICAgY29uc3QgbWF0Y2ggPSB0b2tlbi5saW5lLm1hdGNoKHJlZ2V4cClcbiAgICBsZXQgaW5kZW50ID0gdG9rZW4ubGluZS5pbmRlbnRcbiAgICBsZXQgcmVzdWx0ID0gZmFsc2VcbiAgICBpZiAobWF0Y2gpIHtcbiAgICAgIHRva2VuLm1hdGNoZWRUeXBlID0gbWF0Y2hlZFR5cGVcbiAgICAgIHRva2VuLm1hdGNoZWRLZXl3b3JkID0gbWF0Y2hbMl1cblxuICAgICAgaWYgKG1hdGNoWzJdIGluIHRoaXMua2V5d29yZFR5cGVzTWFwKSB7XG4gICAgICAgIC8vIG9ubHkgc2V0IHRoZSBrZXl3b3JkIHR5cGUgaWYgdGhpcyBpcyBhIHN0ZXAga2V5d29yZFxuICAgICAgICBpZiAodGhpcy5rZXl3b3JkVHlwZXNNYXBbbWF0Y2hbMl1dLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICB0b2tlbi5tYXRjaGVkS2V5d29yZFR5cGUgPSBTdGVwS2V5d29yZFR5cGUuVU5LTk9XTlxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRva2VuLm1hdGNoZWRLZXl3b3JkVHlwZSA9IHRoaXMua2V5d29yZFR5cGVzTWFwW21hdGNoWzJdXVswXVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0b2tlbi5tYXRjaGVkVGV4dCA9IG1hdGNoWzNdLnRyaW0oKVxuICAgICAgaW5kZW50ICs9IG1hdGNoWzFdLmxlbmd0aFxuICAgICAgcmVzdWx0ID0gdHJ1ZVxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5zZXRUb2tlbk1hdGNoZWQodG9rZW4sIGluZGVudCwgcmVzdWx0KVxuICB9XG5cbiAgc2V0VG9rZW5NYXRjaGVkKHRva2VuOiBUb2tlbiwgaW5kZW50OiBudW1iZXIgfCBudWxsLCBtYXRjaGVkOiBib29sZWFuKSB7XG4gICAgdG9rZW4ubWF0Y2hlZEdoZXJraW5EaWFsZWN0ID0gdGhpcy5kaWFsZWN0TmFtZVxuICAgIHRva2VuLm1hdGNoZWRJbmRlbnQgPSBpbmRlbnQgIT09IG51bGwgPyBpbmRlbnQgOiB0b2tlbi5saW5lID09IG51bGwgPyAwIDogdG9rZW4ubGluZS5pbmRlbnRcbiAgICB0b2tlbi5sb2NhdGlvbi5jb2x1bW4gPSB0b2tlbi5tYXRjaGVkSW5kZW50ICsgMVxuICAgIHJldHVybiBtYXRjaGVkXG4gIH1cblxuICBtYXRjaF9UYWJsZVJvdyh0b2tlbjogVG9rZW4pOiBib29sZWFuIHtcbiAgICAvLyBHaGVya2luIHRhYmxlcyBtdXN0IGJlIGluZGVudGVkIDItNSBzcGFjZXMgaW4gb3JkZXIgdG8gYmUgZGlzdGluZ3VpZGVkbiBmcm9tIG5vbi1HaGVya2luIHRhYmxlc1xuICAgIGlmICh0b2tlbi5saW5lLmxpbmVUZXh0Lm1hdGNoKC9eXFxzXFxzXFxzP1xccz9cXHM/XFx8LykpIHtcbiAgICAgIGNvbnN0IHRhYmxlQ2VsbHMgPSB0b2tlbi5saW5lLmdldFRhYmxlQ2VsbHMoKVxuICAgICAgaWYgKHRoaXMuaXNHZm1UYWJsZVNlcGFyYXRvcih0YWJsZUNlbGxzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgIH1cblxuICAgICAgdG9rZW4ubWF0Y2hlZEtleXdvcmQgPSAnfCdcbiAgICAgIHRva2VuLm1hdGNoZWRUeXBlID0gVG9rZW5UeXBlLlRhYmxlUm93XG4gICAgICB0b2tlbi5tYXRjaGVkSXRlbXMgPSB0YWJsZUNlbGxzXG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuXG4gIHByaXZhdGUgaXNHZm1UYWJsZVNlcGFyYXRvcih0YWJsZUNlbGxzOiByZWFkb25seSBJdGVtW10pOiBib29sZWFuIHtcbiAgICBjb25zdCBzZXBhcmF0b3JWYWx1ZXMgPSB0YWJsZUNlbGxzXG4gICAgICAubWFwKChpdGVtKSA9PiBpdGVtLnRleHQpXG4gICAgICAuZmlsdGVyKCh2YWx1ZSkgPT4gdmFsdWUubWF0Y2goL146Py0rOj8kLykpXG4gICAgcmV0dXJuIHNlcGFyYXRvclZhbHVlcy5sZW5ndGggPiAwXG4gIH1cblxuICBtYXRjaF9UYWdMaW5lKHRva2VuOiBUb2tlbik6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHRhZ3M6IEl0ZW1bXSA9IFtdXG4gICAgbGV0IG06IFJlZ0V4cE1hdGNoQXJyYXlcbiAgICBjb25zdCByZSA9IC9gKEBbXmBdKylgL2dcbiAgICBkbyB7XG4gICAgICBtID0gcmUuZXhlYyh0b2tlbi5saW5lLnRyaW1tZWRMaW5lVGV4dClcbiAgICAgIGlmIChtKSB7XG4gICAgICAgIHRhZ3MucHVzaCh7XG4gICAgICAgICAgY29sdW1uOiB0b2tlbi5saW5lLmluZGVudCArIG0uaW5kZXggKyAyLFxuICAgICAgICAgIHRleHQ6IG1bMV0sXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfSB3aGlsZSAobSlcblxuICAgIGlmICh0YWdzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICAgIHRva2VuLm1hdGNoZWRUeXBlID0gVG9rZW5UeXBlLlRhZ0xpbmVcbiAgICB0b2tlbi5tYXRjaGVkSXRlbXMgPSB0YWdzXG4gICAgcmV0dXJuIHRydWVcbiAgfVxuXG4gIHJlc2V0KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmRpYWxlY3ROYW1lICE9PSB0aGlzLmRlZmF1bHREaWFsZWN0TmFtZSkge1xuICAgICAgdGhpcy5jaGFuZ2VEaWFsZWN0KHRoaXMuZGVmYXVsdERpYWxlY3ROYW1lKVxuICAgIH1cbiAgICB0aGlzLmFjdGl2ZURvY1N0cmluZ1NlcGFyYXRvciA9IERFRkFVTFRfRE9DX1NUUklOR19TRVBBUkFUT1JcbiAgfVxufVxuXG5lbnVtIEtleXdvcmRQcmVmaXgge1xuICAvLyBodHRwczovL3NwZWMuY29tbW9ubWFyay5vcmcvMC4yOS8jYnVsbGV0LWxpc3QtbWFya2VyXG4gIEJVTExFVCA9ICdeKFxcXFxzKlsqKy1dXFxcXHMqKScsXG4gIEhFQURFUiA9ICdeKCN7MSw2fVxcXFxzKScsXG59XG5cbi8vIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzMxMTUxNTAvaG93LXRvLWVzY2FwZS1yZWd1bGFyLWV4cHJlc3Npb24tc3BlY2lhbC1jaGFyYWN0ZXJzLXVzaW5nLWphdmFzY3JpcHRcbmZ1bmN0aW9uIGVzY2FwZVJlZ0V4cCh0ZXh0OiBzdHJpbmcpIHtcbiAgcmV0dXJuIHRleHQucmVwbGFjZSgvWy1bXFxde30oKSorPy4sXFxcXF4kfCNcXHNdL2csICdcXFxcJCYnKVxufVxuIl19