@cucumber/gherkin
Version:
Gherkin parser
220 lines • 32.2 kB
JavaScript
import { StepKeywordType } from '@cucumber/messages';
import { compareStepKeywords } from './compareStepKeywords.js';
import countSymbols from './countSymbols.js';
import { NoSuchLanguageException, ParserException } from './Errors.js';
import DIALECTS from './gherkin-languages.json' with { type: 'json' };
import { TokenType } from './Parser.js';
const DIALECT_DICT = DIALECTS;
const LANGUAGE_PATTERN = /^\s*#\s*language\s*:\s*([a-zA-Z\-_]+)\s*$/;
function addKeywordTypeMappings(h, keywords, keywordType) {
for (const k of keywords) {
if (!(k in h)) {
h[k] = [];
}
h[k].push(keywordType);
}
}
export default class GherkinClassicTokenMatcher {
defaultDialectName;
dialect;
dialectName;
activeDocStringSeparator;
indentToRemove;
keywordTypesMap;
sortedStepKeywords;
constructor(defaultDialectName = 'en') {
this.defaultDialectName = defaultDialectName;
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();
this.initializeSortedStepKeywords();
}
reset() {
if (this.dialectName !== this.defaultDialectName) {
this.changeDialect(this.defaultDialectName);
}
this.activeDocStringSeparator = null;
this.indentToRemove = 0;
}
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);
}
initializeSortedStepKeywords() {
this.sortedStepKeywords = []
.concat(this.dialect.given)
.concat(this.dialect.when)
.concat(this.dialect.then)
.concat(this.dialect.and)
.concat(this.dialect.but)
.sort(compareStepKeywords);
}
match_TagLine(token) {
if (token.line.startsWith('@')) {
this.setTokenMatched(token, TokenType.TagLine, null, null, null, null, this.getTags(token.line));
return true;
}
return false;
}
match_FeatureLine(token) {
return this.matchTitleLine(token, TokenType.FeatureLine, this.dialect.feature);
}
match_ScenarioLine(token) {
return (this.matchTitleLine(token, TokenType.ScenarioLine, this.dialect.scenario) ||
this.matchTitleLine(token, TokenType.ScenarioLine, this.dialect.scenarioOutline));
}
match_BackgroundLine(token) {
return this.matchTitleLine(token, TokenType.BackgroundLine, this.dialect.background);
}
match_ExamplesLine(token) {
return this.matchTitleLine(token, TokenType.ExamplesLine, this.dialect.examples);
}
match_RuleLine(token) {
return this.matchTitleLine(token, TokenType.RuleLine, this.dialect.rule);
}
match_TableRow(token) {
if (token.line.startsWith('|')) {
// TODO: indent
this.setTokenMatched(token, TokenType.TableRow, null, null, null, null, token.line.getTableCells());
return true;
}
return false;
}
match_Empty(token) {
if (token.line.isEmpty) {
this.setTokenMatched(token, TokenType.Empty, null, null, 0);
return true;
}
return false;
}
match_Comment(token) {
if (token.line.startsWith('#')) {
const text = token.line.getLineText(0); // take the entire line, including leading space
this.setTokenMatched(token, TokenType.Comment, text, null, 0);
return true;
}
return false;
}
match_Language(token) {
const match = token.line.trimmedLineText.match(LANGUAGE_PATTERN);
if (match) {
const newDialectName = match[1];
this.setTokenMatched(token, TokenType.Language, newDialectName);
this.changeDialect(newDialectName, token.location);
return true;
}
return false;
}
match_DocStringSeparator(token) {
return this.activeDocStringSeparator == null
? // open
this._match_DocStringSeparator(token, '"""', true) ||
this._match_DocStringSeparator(token, '```', true)
: // close
this._match_DocStringSeparator(token, this.activeDocStringSeparator, false);
}
_match_DocStringSeparator(token, separator, isOpen) {
if (token.line.startsWith(separator)) {
let mediaType = null;
if (isOpen) {
mediaType = token.line.getRestTrimmed(separator.length);
this.activeDocStringSeparator = separator;
this.indentToRemove = token.line.indent;
}
else {
this.activeDocStringSeparator = null;
this.indentToRemove = 0;
}
this.setTokenMatched(token, TokenType.DocStringSeparator, mediaType, separator);
return true;
}
return false;
}
match_EOF(token) {
if (token.isEof) {
this.setTokenMatched(token, TokenType.EOF);
return true;
}
return false;
}
match_StepLine(token) {
for (const keyword of this.sortedStepKeywords) {
if (token.line.startsWith(keyword)) {
const title = token.line.getRestTrimmed(keyword.length);
const keywordTypes = this.keywordTypesMap[keyword];
let keywordType = keywordTypes[0];
if (keywordTypes.length > 1) {
keywordType = StepKeywordType.UNKNOWN;
}
this.setTokenMatched(token, TokenType.StepLine, title, keyword, null, keywordType);
return true;
}
}
return false;
}
match_Other(token) {
const text = token.line.getLineText(this.indentToRemove); // take the entire line, except removing DocString indents
this.setTokenMatched(token, TokenType.Other, this.unescapeDocString(text), null, 0);
return true;
}
getTags(line) {
const uncommentedLine = line.trimmedLineText.split(/\s#/g, 2)[0];
let column = line.indent + 1;
const items = uncommentedLine.split('@');
const tags = [];
for (let i = 0; i < items.length; i++) {
const item = items[i].trimRight();
if (item.length === 0) {
continue;
}
if (!item.match(/^\S+$/)) {
throw ParserException.create('A tag may not contain whitespace', line.lineNumber, column);
}
const span = { column, text: `@${item}` };
tags.push(span);
column += countSymbols(items[i]) + 1;
}
return tags;
}
matchTitleLine(token, tokenType, keywords) {
for (const keyword of keywords) {
if (token.line.startsWithTitleKeyword(keyword)) {
const title = token.line.getRestTrimmed(keyword.length + ':'.length);
this.setTokenMatched(token, tokenType, title, keyword);
return true;
}
}
return false;
}
setTokenMatched(token, matchedType, text, keyword, indent, keywordType, items) {
token.matchedType = matchedType;
token.matchedText = text;
token.matchedKeyword = keyword;
token.matchedKeywordType = keywordType;
token.matchedIndent =
typeof indent === 'number' ? indent : token.line == null ? 0 : token.line.indent;
token.matchedItems = items || [];
token.location.column = token.matchedIndent + 1;
token.matchedGherkinDialect = this.dialectName;
}
unescapeDocString(text) {
if (this.activeDocStringSeparator === '"""') {
return text.replace('\\"\\"\\"', '"""');
}
if (this.activeDocStringSeparator === '```') {
return text.replace('\\`\\`\\`', '```');
}
return text;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiR2hlcmtpbkNsYXNzaWNUb2tlbk1hdGNoZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvR2hlcmtpbkNsYXNzaWNUb2tlbk1hdGNoZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFpQixlQUFlLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQTtBQUNuRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQTtBQUM5RCxPQUFPLFlBQVksTUFBTSxtQkFBbUIsQ0FBQTtBQUU1QyxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsZUFBZSxFQUFFLE1BQU0sYUFBYSxDQUFBO0FBQ3RFLE9BQU8sUUFBUSxNQUFNLDBCQUEwQixDQUFDLE9BQU8sSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFBO0FBSXJFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxhQUFhLENBQUE7QUFFdkMsTUFBTSxZQUFZLEdBQStCLFFBQVEsQ0FBQTtBQUN6RCxNQUFNLGdCQUFnQixHQUFHLDJDQUEyQyxDQUFBO0FBRXBFLFNBQVMsc0JBQXNCLENBQzdCLENBQXVDLEVBQ3ZDLFFBQTJCLEVBQzNCLFdBQTRCO0lBRTVCLEtBQUssTUFBTSxDQUFDLElBQUksUUFBUSxFQUFFLENBQUM7UUFDekIsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDZCxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBdUIsQ0FBQTtRQUNoQyxDQUFDO1FBQ0QsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQTtJQUN4QixDQUFDO0FBQ0gsQ0FBQztBQUVELE1BQU0sQ0FBQyxPQUFPLE9BQU8sMEJBQTBCO0lBUWhCLGtCQUFrQjtJQVB2QyxPQUFPLENBQVM7SUFDaEIsV0FBVyxDQUFRO0lBQ25CLHdCQUF3QixDQUFRO0lBQ2hDLGNBQWMsQ0FBUTtJQUN0QixlQUFlLENBQXNDO0lBQ3JELGtCQUFr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TUFBTSxDQUFBO1FBQ2xGLEtBQUssQ0FBQyxZQUFZLEdBQUcsS0FBSyxJQUFJLEVBQUUsQ0FBQTtRQUVoQyxLQUFLLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsYUFBYSxHQUFHLENBQUMsQ0FBQTtRQUMvQyxLQUFLLENBQUMscUJBQXFCLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQTtJQUNoRCxDQUFDO0lBRU8saUJBQWlCLENBQUMsSUFBWTtRQUNwQyxJQUFJLElBQUksQ0FBQyx3QkFBd0IsS0FBSyxLQUFLLEVBQUUsQ0FBQztZQUM1QyxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLEtBQUssQ0FBQyxDQUFBO1FBQ3pDLENBQUM7UUFDRCxJQUFJLElBQUksQ0FBQyx3QkFBd0IsS0FBSyxLQUFLLEVBQUUsQ0FBQztZQUM1QyxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLEtBQUssQ0FBQyxDQUFBO1FBQ3pDLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQTtJQUNiLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHR5cGUgTG9jYXRpb24sIFN0ZXBLZXl3b3JkVHlwZSB9IGZyb20gJ0BjdWN1bWJlci9tZXNzYWdlcydcbmltcG9ydCB7IGNvbXBhcmVTdGVwS2V5d29yZHMgfSBmcm9tICcuL2NvbXBhcmVTdGVwS2V5d29yZHMuanMnXG5pbXBvcnQgY291bnRTeW1ib2xzIGZyb20gJy4vY291bnRTeW1ib2xzLmpzJ1xuaW1wb3J0IHR5cGUgRGlhbGVjdCBmcm9tICcuL0RpYWxlY3QuanMnXG5pbXBvcnQgeyBOb1N1Y2hMYW5ndWFnZUV4Y2VwdGlvbiwgUGFyc2VyRXhjZXB0aW9uIH0gZnJvbSAnLi9FcnJvcnMuanMnXG5pbXBvcnQgRElBTEVDVFMgZnJvbSAnLi9naGVya2luLWxhbmd1YWdlcy5qc29uJyB3aXRoIHsgdHlwZTogJ2pzb24nIH1cbmltcG9ydCB0eXBlIElUb2tlbiBmcm9tICcuL0lUb2tlbi5qcydcbmltcG9ydCB0eXBlIHsgSUdoZXJraW5MaW5lLCBJdGVtIH0gZnJvbSAnLi9JVG9rZW4uanMnXG5pbXBvcnQgdHlwZSBJVG9rZW5NYXRjaGVyIGZyb20gJy4vSVRva2VuTWF0Y2hlci5qcydcbmltcG9ydCB7IFRva2VuVHlwZSB9IGZyb20gJy4vUGFyc2VyLmpzJ1xuXG5jb25zdCBESUFMRUNUX0RJQ1Q6IHsgW2tleTogc3RyaW5nXTogRGlhbGVjdCB9ID0gRElBTEVDVFNcbmNvbnN0IExBTkdVQUdFX1BBVFRFUk4gPSAvXlxccyojXFxzKmxhbmd1YWdlXFxzKjpcXHMqKFthLXpBLVpcXC1fXSspXFxzKiQvXG5cbmZ1bmN0aW9uIGFkZEtleXdvcmRUeXBlTWFwcGluZ3MoXG4gIGg6IHsgW2tleTogc3RyaW5nXTogU3RlcEtleXdvcmRUeXBlW10gfSxcbiAga2V5d29yZHM6IHJlYWRvbmx5IHN0cmluZ1tdLFxuICBrZXl3b3JkVHlwZTogU3RlcEtleXdvcmRUeXBlXG4pIHtcbiAgZm9yIChjb25zdCBrIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKCEoayBpbiBoKSkge1xuICAgICAgaFtrXSA9IFtdIGFzIFN0ZXBLZXl3b3JkVHlwZVtdXG4gICAgfVxuICAgIGhba10ucHVzaChrZXl3b3JkVHlwZSlcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBHaGVya2luQ2xhc3NpY1Rva2VuTWF0Y2hlciBpbXBsZW1lbnRzIElUb2tlbk1hdGNoZXI8VG9rZW5UeXBlPiB7XG4gIHByaXZhdGUgZGlhbGVjdDogRGlhbGVjdFxuICBwcml2YXRlIGRpYWxlY3ROYW1lOiBzdHJpbmdcbiAgcHJpdmF0ZSBhY3RpdmVEb2NTdHJpbmdTZXBhcmF0b3I6IHN0cmluZ1xuICBwcml2YXRlIGluZGVudFRvUmVtb3ZlOiBudW1iZXJcbiAgcHJpdmF0ZSBrZXl3b3JkVHlwZXNNYXA6IHsgW2tleTogc3RyaW5nXTogU3RlcEtleXdvcmRUeXBlW10gfVxuICBwcml2YXRlIHNvcnRlZFN0ZXBLZXl3b3JkczogcmVhZG9ubHkgc3RyaW5nW11cblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IGRlZmF1bHREaWFsZWN0TmFtZTogc3RyaW5nID0gJ2VuJykge1xuICAgIHRoaXMucmVzZXQoKVxuICB9XG5cbiAgY2hhbmdlRGlhbGVjdChuZXdEaWFsZWN0TmFtZTogc3RyaW5nLCBsb2NhdGlvbj86IExvY2F0aW9uKSB7XG4gICAgY29uc3QgbmV3RGlhbGVjdCA9IERJQUxFQ1RfRElDVFtuZXdEaWFsZWN0TmFtZV1cbiAgICBpZiAoIW5ld0RpYWxlY3QpIHtcbiAgICAgIHRocm93IE5vU3VjaExhbmd1YWdlRXhjZXB0aW9uLmNyZWF0ZShuZXdEaWFsZWN0TmFtZSwgbG9jYXRpb24pXG4gICAgfVxuXG4gICAgdGhpcy5kaWFsZWN0TmFtZSA9IG5ld0RpYWxlY3ROYW1lXG4gICAgdGhpcy5kaWFsZWN0ID0gbmV3RGlhbGVjdFxuICAgIHRoaXMuaW5pdGlhbGl6ZUtleXdvcmRUeXBlcygpXG4gICAgdGhpcy5pbml0aWFsaXplU29ydGVkU3RlcEtleXdvcmRzKClcbiAgfVxuXG4gIHJlc2V0KCkge1xuICAgIGlmICh0aGlzLmRpYWxlY3ROYW1lICE9PSB0aGlzLmRlZmF1bHREaWFsZWN0TmFtZSkge1xuICAgICAgdGhpcy5jaGFuZ2VEaWFsZWN0KHRoaXMuZGVmYXVsdERpYWxlY3ROYW1lKVxuICAgIH1cbiAgICB0aGlzLmFjdGl2ZURvY1N0cmluZ1NlcGFyYXRvciA9IG51bGxcbiAgICB0aGlzLmluZGVudFRvUmVtb3ZlID0gMFxuICB9XG5cbiAgaW5pdGlhbGl6ZUtleXdvcmRUeXBlcygpIHtcbiAgICB0aGlzLmtleXdvcmRUeXBlc01hcCA9IHt9XG4gICAgYWRkS2V5d29yZFR5cGVNYXBwaW5ncyh0aGlzLmtleXdvcmRUeXBlc01hcCwgdGhpcy5kaWFsZWN0LmdpdmVuLCBTdGVwS2V5d29yZFR5cGUuQ09OVEVYVClcbiAgICBhZGRLZXl3b3JkVHlwZU1hcHBpbmdzKHRoaXMua2V5d29yZFR5cGVzTWFwLCB0aGlzLmRpYWxlY3Qud2hlbiwgU3RlcEtleXdvcmRUeXBlLkFDVElPTilcbiAgICBhZGRLZXl3b3JkVHlwZU1hcHBpbmdzKHRoaXMua2V5d29yZFR5cGVzTWFwLCB0aGlzLmRpYWxlY3QudGhlbiwgU3RlcEtleXdvcmRUeXBlLk9VVENPTUUpXG4gICAgYWRkS2V5d29yZFR5cGVNYXBwaW5ncyhcbiAgICAgIHRoaXMua2V5d29yZFR5cGVzTWFwLFxuICAgICAgW10uY29uY2F0KHRoaXMuZGlhbGVjdC5hbmQpLmNvbmNhdCh0aGlzLmRpYWxlY3QuYnV0KSxcbiAgICAgIFN0ZXBLZXl3b3JkVHlwZS5DT05KVU5DVElPTlxuICAgIClcbiAgfVxuXG4gIGluaXRpYWxpemVTb3J0ZWRTdGVwS2V5d29yZHMoKSB7XG4gICAgdGhpcy5zb3J0ZWRTdGVwS2V5d29yZHMgPSBbXVxuICAgICAgLmNvbmNhdCh0aGlzLmRpYWxlY3QuZ2l2ZW4pXG4gICAgICAuY29uY2F0KHRoaXMuZGlhbGVjdC53aGVuKVxuICAgICAgLmNvbmNhdCh0aGlzLmRpYWxlY3QudGhlbilcbiAgICAgIC5jb25jYXQodGhpcy5kaWFsZWN0LmFuZClcbiAgICAgIC5jb25jYXQodGhpcy5kaWFsZWN0LmJ1dClcbiAgICAgIC5zb3J0KGNvbXBhcmVTdGVwS2V5d29yZHMpXG4gIH1cblxuICBtYXRjaF9UYWdMaW5lKHRva2VuOiBJVG9rZW48VG9rZW5UeXBlPikge1xuICAgIGlmICh0b2tlbi5saW5lLnN0YXJ0c1dpdGgoJ0AnKSkge1xuICAgICAgdGhpcy5zZXRUb2tlbk1hdGNoZWQoXG4gICAgICAgIHRva2VuLFxuICAgICAgICBUb2tlblR5cGUuVGFnTGluZSxcbiAgICAgICAgbnVsbCxcbiAgICAgICAgbnVsbCxcbiAgICAgICAgbnVsbCxcbiAgICAgICAgbnVsbCxcbiAgICAgICAgdGhpcy5nZXRUYWdzKHRva2VuLmxpbmUpXG4gICAgICApXG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuXG4gIG1hdGNoX0ZlYXR1cmVMaW5lKHRva2VuOiBJVG9rZW48VG9rZW5UeXBlPikge1xuICAgIHJldHVybiB0aGlzLm1hdGNoVGl0bGVMaW5lKHRva2VuLCBUb2tlblR5cGUuRmVhdHVyZUxpbmUsIHRoaXMuZGlhbGVjdC5mZWF0dXJlKVxuICB9XG5cbiAgbWF0Y2hfU2NlbmFyaW9MaW5lKHRva2VuOiBJVG9rZW48VG9rZW5UeXBlPikge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLm1hdGNoVGl0bGVMaW5lKHRva2VuLCBUb2tlblR5cGUuU2NlbmFyaW9MaW5lLCB0aGlzLmRpYWxlY3Quc2NlbmFyaW8pIHx8XG4gICAgICB0aGlzLm1hdGNoVGl0bGVMaW5lKHRva2VuLCBUb2tlblR5cGUuU2NlbmFyaW9MaW5lLCB0aGlzLmRpYWxlY3Quc2NlbmFyaW9PdXRsaW5lKVxuICAgIClcbiAgfVxuXG4gIG1hdGNoX0JhY2tncm91bmRMaW5lKHRva2VuOiBJVG9rZW48VG9rZW5UeXBlPikge1xuICAgIHJldHVybiB0aGlzLm1hdGNoVGl0bGVMaW5lKHRva2VuLCBUb2tlblR5cGUuQmFja2dyb3VuZExpbmUsIHRoaXMuZGlhbGVjdC5iYWNrZ3JvdW5kKVxuICB9XG5cbiAgbWF0Y2hfRXhhbXBsZXNMaW5lKHRva2VuOiBJVG9rZW48VG9rZW5UeXBlPikge1xuICAgIHJldHVybiB0aGlzLm1hdGNoVGl0bGVMaW5lKHRva2VuLCBUb2tlblR5cGUuRXhhbXBsZXNMaW5lLCB0aGlzLmRpYWxlY3QuZXhhbXBsZXMpXG4gIH1cblxuICBtYXRjaF9SdWxlTGluZSh0b2tlbjogSVRva2VuPFRva2VuVHlwZT4pIHtcbiAgICByZXR1cm4gdGhpcy5tYXRjaFRpdGxlTGluZSh0b2tlbiwgVG9rZW5UeXBlLlJ1bGVMaW5lLCB0aGlzLmRpYWxlY3QucnVsZSlcbiAgfVxuXG4gIG1hdGNoX1RhYmxlUm93KHRva2VuOiBJVG9rZW48VG9rZW5UeXBlPikge1xuICAgIGlmICh0b2tlbi5saW5lLnN0YXJ0c1dpdGgoJ3wnKSkge1xuICAgICAgLy8gVE9ETzogaW5kZW50XG4gICAgICB0aGlzLnNldFRva2VuTWF0Y2hlZChcbiAgICAgICAgdG9rZW4sXG4gICAgICAgIFRva2VuVHlwZS5UYWJsZVJvdyxcbiAgICAgICAgbnVsbCxcbiAgICAgICAgbnVsbCxcbiAgICAgICAgbnVsbCxcbiAgICAgICAgbnVsbCxcbiAgICAgICAgdG9rZW4ubGluZS5nZXRUYWJsZUNlbGxzKClcbiAgICAgIClcbiAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgbWF0Y2hfRW1wdHkodG9rZW46IElUb2tlbjxUb2tlblR5cGU+KSB7XG4gICAgaWYgKHRva2VuLmxpbmUuaXNFbXB0eSkge1xuICAgICAgdGhpcy5zZXRUb2tlbk1hdGNoZWQodG9rZW4sIFRva2VuVHlwZS5FbXB0eSwgbnVsbCwgbnVsbCwgMClcbiAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgbWF0Y2hfQ29tbWVudCh0b2tlbjogSVRva2VuPFRva2VuVHlwZT4pIHtcbiAgICBpZiAodG9rZW4ubGluZS5zdGFydHNXaXRoKCcjJykpIHtcbiAgICAgIGNvbnN0IHRleHQgPSB0b2tlbi5saW5lLmdldExpbmVUZXh0KDApIC8vIHRha2UgdGhlIGVudGlyZSBsaW5lLCBpbmNsdWRpbmcgbGVhZGluZyBzcGFjZVxuICAgICAgdGhpcy5zZXRUb2tlbk1hdGNoZWQodG9rZW4sIFRva2VuVHlwZS5Db21tZW50LCB0ZXh0LCBudWxsLCAwKVxuICAgICAgcmV0dXJuIHRydWVcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cblxuICBtYXRjaF9MYW5ndWFnZSh0b2tlbjogSVRva2VuPFRva2VuVHlwZT4pIHtcbiAgICBjb25zdCBtYXRjaCA9IHRva2VuLmxpbmUudHJpbW1lZExpbmVUZXh0Lm1hdGNoKExBTkdVQUdFX1BBVFRFUk4pXG4gICAgaWYgKG1hdGNoKSB7XG4gICAgICBjb25zdCBuZXdEaWFsZWN0TmFtZSA9IG1hdGNoWzFdXG4gICAgICB0aGlzLnNldFRva2VuTWF0Y2hlZCh0b2tlbiwgVG9rZW5UeXBlLkxhbmd1YWdlLCBuZXdEaWFsZWN0TmFtZSlcblxuICAgICAgdGhpcy5jaGFuZ2VEaWFsZWN0KG5ld0RpYWxlY3ROYW1lLCB0b2tlbi5sb2NhdGlvbilcbiAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgbWF0Y2hfRG9jU3RyaW5nU2VwYXJhdG9yKHRva2VuOiBJVG9rZW48VG9rZW5UeXBlPikge1xuICAgIHJldHVybiB0aGlzLmFjdGl2ZURvY1N0cmluZ1NlcGFyYXRvciA9PSBudWxsXG4gICAgICA/IC8vIG9wZW5cbiAgICAgICAgdGhpcy5fbWF0Y2hfRG9jU3RyaW5nU2VwYXJhdG9yKHRva2VuLCAnXCJcIlwiJywgdHJ1ZSkgfHxcbiAgICAgICAgICB0aGlzLl9tYXRjaF9Eb2NTdHJpbmdTZXBhcmF0b3IodG9rZW4sICdgYGAnLCB0cnVlKVxuICAgICAgOiAvLyBjbG9zZVxuICAgICAgICB0aGlzLl9tYXRjaF9Eb2NTdHJpbmdTZXBhcmF0b3IodG9rZW4sIHRoaXMuYWN0aXZlRG9jU3RyaW5nU2VwYXJhdG9yLCBmYWxzZSlcbiAgfVxuXG4gIHB1YmxpYyBfbWF0Y2hfRG9jU3RyaW5nU2VwYXJhdG9yKHRva2VuOiBJVG9rZW48VG9rZW5UeXBlPiwgc2VwYXJhdG9yOiBzdHJpbmcsIGlzT3BlbjogYm9vbGVhbikge1xuICAgIGlmICh0b2tlbi5saW5lLnN0YXJ0c1dpdGgoc2VwYXJhdG9yKSkge1xuICAgICAgbGV0IG1lZGlhVHlwZSA9IG51bGxcbiAgICAgIGlmIChpc09wZW4pIHtcbiAgICAgICAgbWVkaWFUeXBlID0gdG9rZW4ubGluZS5nZXRSZXN0VHJpbW1lZChzZXBhcmF0b3IubGVuZ3RoKVxuICAgICAgICB0aGlzLmFjdGl2ZURvY1N0cmluZ1NlcGFyYXRvciA9IHNlcGFyYXRvclxuICAgICAgICB0aGlzLmluZGVudFRvUmVtb3ZlID0gdG9rZW4ubGluZS5pbmRlbnRcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuYWN0aXZlRG9jU3RyaW5nU2VwYXJhdG9yID0gbnVsbFxuICAgICAgICB0aGlzLmluZGVudFRvUmVtb3ZlID0gMFxuICAgICAgfVxuXG4gICAgICB0aGlzLnNldFRva2VuTWF0Y2hlZCh0b2tlbiwgVG9rZW5UeXBlLkRvY1N0cmluZ1NlcGFyYXRvciwgbWVkaWFUeXBlLCBzZXBhcmF0b3IpXG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuXG4gIG1hdGNoX0VPRih0b2tlbjogSVRva2VuPFRva2VuVHlwZT4pIHtcbiAgICBpZiAodG9rZW4uaXNFb2YpIHtcbiAgICAgIHRoaXMuc2V0VG9rZW5NYXRjaGVkKHRva2VuLCBUb2tlblR5cGUuRU9GKVxuICAgICAgcmV0dXJuIHRydWVcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cblxuICBtYXRjaF9TdGVwTGluZSh0b2tlbjogSVRva2VuPFRva2VuVHlwZT4pIHtcbiAgICBmb3IgKGNvbnN0IGtleXdvcmQgb2YgdGhpcy5zb3J0ZWRTdGVwS2V5d29yZHMpIHtcbiAgICAgIGlmICh0b2tlbi5saW5lLnN0YXJ0c1dpdGgoa2V5d29yZCkpIHtcbiAgICAgICAgY29uc3QgdGl0bGUgPSB0b2tlbi5saW5lLmdldFJlc3RUcmltbWVkKGtleXdvcmQubGVuZ3RoKVxuICAgICAgICBjb25zdCBrZXl3b3JkVHlwZXMgPSB0aGlzLmtleXdvcmRUeXBlc01hcFtrZXl3b3JkXVxuICAgICAgICBsZXQga2V5d29yZFR5cGUgPSBrZXl3b3JkVHlwZXNbMF1cbiAgICAgICAgaWYgKGtleXdvcmRUeXBlcy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAga2V5d29yZFR5cGUgPSBTdGVwS2V5d29yZFR5cGUuVU5LTk9XTlxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zZXRUb2tlbk1hdGNoZWQodG9rZW4sIFRva2VuVHlwZS5TdGVwTGluZSwgdGl0bGUsIGtleXdvcmQsIG51bGwsIGtleXdvcmRUeXBlKVxuICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgbWF0Y2hfT3RoZXIodG9rZW46IElUb2tlbjxUb2tlblR5cGU+KSB7XG4gICAgY29uc3QgdGV4dCA9IHRva2VuLmxpbmUuZ2V0TGluZVRleHQodGhpcy5pbmRlbnRUb1JlbW92ZSkgLy8gdGFrZSB0aGUgZW50aXJlIGxpbmUsIGV4Y2VwdCByZW1vdmluZyBEb2NTdHJpbmcgaW5kZW50c1xuICAgIHRoaXMuc2V0VG9rZW5NYXRjaGVkKHRva2VuLCBUb2tlblR5cGUuT3RoZXIsIHRoaXMudW5lc2NhcGVEb2NTdHJpbmcodGV4dCksIG51bGwsIDApXG4gICAgcmV0dXJuIHRydWVcbiAgfVxuXG4gIGdldFRhZ3MobGluZTogSUdoZXJraW5MaW5lKTogcmVhZG9ubHkgSXRlbVtdIHtcbiAgICBjb25zdCB1bmNvbW1lbnRlZExpbmUgPSBsaW5lLnRyaW1tZWRMaW5lVGV4dC5zcGxpdCgvXFxzIy9nLCAyKVswXVxuICAgIGxldCBjb2x1bW4gPSBsaW5lLmluZGVudCArIDFcbiAgICBjb25zdCBpdGVtcyA9IHVuY29tbWVudGVkTGluZS5zcGxpdCgnQCcpXG4gICAgY29uc3QgdGFnczogSXRlbVtdID0gW11cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGl0ZW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBpdGVtID0gaXRlbXNbaV0udHJpbVJpZ2h0KClcbiAgICAgIGlmIChpdGVtLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuICAgICAgaWYgKCFpdGVtLm1hdGNoKC9eXFxTKyQvKSkge1xuICAgICAgICB0aHJvdyBQYXJzZXJFeGNlcHRpb24uY3JlYXRlKCdBIHRhZyBtYXkgbm90IGNvbnRhaW4gd2hpdGVzcGFjZScsIGxpbmUubGluZU51bWJlciwgY29sdW1uKVxuICAgICAgfVxuICAgICAgY29uc3Qgc3BhbiA9IHsgY29sdW1uLCB0ZXh0OiBgQCR7aXRlbX1gIH1cbiAgICAgIHRhZ3MucHVzaChzcGFuKVxuICAgICAgY29sdW1uICs9IGNvdW50U3ltYm9scyhpdGVtc1tpXSkgKyAxXG4gICAgfVxuICAgIHJldHVybiB0YWdzXG4gIH1cblxuICBwcml2YXRlIG1hdGNoVGl0bGVMaW5lKFxuICAgIHRva2VuOiBJVG9rZW48VG9rZW5UeXBlPixcbiAgICB0b2tlblR5cGU6IFRva2VuVHlwZSxcbiAgICBrZXl3b3JkczogcmVhZG9ubHkgc3RyaW5nW11cbiAgKTogYm9vbGVhbiB7XG4gICAgZm9yIChjb25zdCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgICBpZiAodG9rZW4ubGluZS5zdGFydHNXaXRoVGl0bGVLZXl3b3JkKGtleXdvcmQpKSB7XG4gICAgICAgIGNvbnN0IHRpdGxlID0gdG9rZW4ubGluZS5nZXRSZXN0VHJpbW1lZChrZXl3b3JkLmxlbmd0aCArICc6Jy5sZW5ndGgpXG4gICAgICAgIHRoaXMuc2V0VG9rZW5NYXRjaGVkKHRva2VuLCB0b2tlblR5cGUsIHRpdGxlLCBrZXl3b3JkKVxuICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuXG4gIHByaXZhdGUgc2V0VG9rZW5NYXRjaGVkKFxuICAgIHRva2VuOiBJVG9rZW48VG9rZW5UeXBlPixcbiAgICBtYXRjaGVkVHlwZTogVG9rZW5UeXBlLFxuICAgIHRleHQ/OiBzdHJpbmcsXG4gICAga2V5d29yZD86IHN0cmluZyxcbiAgICBpbmRlbnQ/OiBudW1iZXIsXG4gICAga2V5d29yZFR5cGU/OiBTdGVwS2V5d29yZFR5cGUsXG4gICAgaXRlbXM/OiByZWFkb25seSBJdGVtW11cbiAgKSB7XG4gICAgdG9rZW4ubWF0Y2hlZFR5cGUgPSBtYXRjaGVkVHlwZVxuICAgIHRva2VuLm1hdGNoZWRUZXh0ID0gdGV4dFxuICAgIHRva2VuLm1hdGNoZWRLZXl3b3JkID0ga2V5d29yZFxuICAgIHRva2VuLm1hdGNoZWRLZXl3b3JkVHlwZSA9IGtleXdvcmRUeXBlXG4gICAgdG9rZW4ubWF0Y2hlZEluZGVudCA9XG4gICAgICB0eXBlb2YgaW5kZW50ID09PSAnbnVtYmVyJyA/IGluZGVudCA6IHRva2VuLmxpbmUgPT0gbnVsbCA/IDAgOiB0b2tlbi5saW5lLmluZGVudFxuICAgIHRva2VuLm1hdGNoZWRJdGVtcyA9IGl0ZW1zIHx8IFtdXG5cbiAgICB0b2tlbi5sb2NhdGlvbi5jb2x1bW4gPSB0b2tlbi5tYXRjaGVkSW5kZW50ICsgMVxuICAgIHRva2VuLm1hdGNoZWRHaGVya2luRGlhbGVjdCA9IHRoaXMuZGlhbGVjdE5hbWVcbiAgfVxuXG4gIHByaXZhdGUgdW5lc2NhcGVEb2NTdHJpbmcodGV4dDogc3RyaW5nKSB7XG4gICAgaWYgKHRoaXMuYWN0aXZlRG9jU3RyaW5nU2VwYXJhdG9yID09PSAnXCJcIlwiJykge1xuICAgICAgcmV0dXJuIHRleHQucmVwbGFjZSgnXFxcXFwiXFxcXFwiXFxcXFwiJywgJ1wiXCJcIicpXG4gICAgfVxuICAgIGlmICh0aGlzLmFjdGl2ZURvY1N0cmluZ1NlcGFyYXRvciA9PT0gJ2BgYCcpIHtcbiAgICAgIHJldHVybiB0ZXh0LnJlcGxhY2UoJ1xcXFxgXFxcXGBcXFxcYCcsICdgYGAnKVxuICAgIH1cbiAgICByZXR1cm4gdGV4dFxuICB9XG59XG4iXX0=