UNPKG

@cucumber/gherkin

Version:
264 lines 39.5 kB
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