UNPKG

@cucumber/tag-expressions

Version:
226 lines 24.4 kB
const OPERAND = 'operand'; const OPERATOR = 'operator'; const PREC = { '(': -2, ')': -1, or: 0, and: 1, not: 2, }; const ASSOC = { or: 'left', and: 'left', not: 'right', }; /** * Parses infix boolean expression (using Dijkstra's Shunting Yard algorithm) * and builds a tree of expressions. The root node of the expression is returned. * * This expression can be evaluated by passing in an array of literals that resolve to true */ export function parse(infix) { const tokens = tokenize(infix); if (tokens.length === 0) { return new True(); } const expressions = []; const operators = []; let expectedTokenType = OPERAND; tokens.forEach((token) => { if (isUnary(token)) { check(expectedTokenType, OPERAND); operators.push(token); expectedTokenType = OPERAND; } else if (isBinary(token)) { check(expectedTokenType, OPERATOR); while (operators.length > 0 && isOp(peek(operators)) && ((ASSOC[token] === 'left' && PREC[token] <= PREC[peek(operators)]) || (ASSOC[token] === 'right' && PREC[token] < PREC[peek(operators)]))) { pushExpr(operators.pop(), expressions); } operators.push(token); expectedTokenType = OPERAND; } else if ('(' === token) { check(expectedTokenType, OPERAND); operators.push(token); expectedTokenType = OPERAND; } else if (')' === token) { check(expectedTokenType, OPERATOR); while (operators.length > 0 && peek(operators) !== '(') { pushExpr(operators.pop(), expressions); } if (operators.length === 0) { throw new Error(`Tag expression "${infix}" could not be parsed because of syntax error: Unmatched ).`); } if (peek(operators) === '(') { operators.pop(); } expectedTokenType = OPERATOR; } else { check(expectedTokenType, OPERAND); pushExpr(token, expressions); expectedTokenType = OPERATOR; } }); while (operators.length > 0) { if (peek(operators) === '(') { throw new Error(`Tag expression "${infix}" could not be parsed because of syntax error: Unmatched (.`); } pushExpr(operators.pop(), expressions); } return expressions.pop(); function check(expectedTokenType, tokenType) { if (expectedTokenType !== tokenType) { throw new Error(`Tag expression "${infix}" could not be parsed because of syntax error: Expected ${expectedTokenType}.`); } } function pushExpr(token, stack) { if (token === 'and') { const rightAndExpr = popOperand(stack); stack.push(new And(popOperand(stack), rightAndExpr)); } else if (token === 'or') { const rightOrExpr = popOperand(stack); stack.push(new Or(popOperand(stack), rightOrExpr)); } else if (token === 'not') { stack.push(new Not(popOperand(stack))); } else { stack.push(new Literal(token)); } } function popOperand(stack) { if (stack.length === 0) { throw new Error(`Tag expression "${infix}" could not be parsed because of syntax error: Expected operand.`); } return stack.pop(); } } function tokenize(expr) { const tokens = []; let isEscaped = false; let token = []; for (let i = 0; i < expr.length; i++) { const c = expr.charAt(i); if (isEscaped) { if (c === '(' || c === ')' || c === '\\' || /\s/.test(c)) { token.push(c); isEscaped = false; } else { throw new Error(`Tag expression "${expr}" could not be parsed because of syntax error: Illegal escape before "${c}".`); } } else if (c === '\\') { isEscaped = true; } else if (c === '(' || c === ')' || /\s/.test(c)) { if (token.length > 0) { tokens.push(token.join('')); token = []; } if (!/\s/.test(c)) { tokens.push(c); } } else { token.push(c); } } if (token.length > 0) { tokens.push(token.join('')); } return tokens; } function isUnary(token) { return 'not' === token; } function isBinary(token) { return 'or' === token || 'and' === token; } function isOp(token) { return ASSOC[token] !== undefined; } function peek(stack) { return stack[stack.length - 1]; } class Literal { value; constructor(value) { this.value = value; } evaluate(variables) { return variables.indexOf(this.value) !== -1; } toString() { return this.value .replace(/\\/g, '\\\\') .replace(/\(/g, '\\(') .replace(/\)/g, '\\)') .replace(/\s/g, '\\ '); } } class Or { leftExpr; rightExpr; constructor(leftExpr, rightExpr) { this.leftExpr = leftExpr; this.rightExpr = rightExpr; } evaluate(variables) { return this.leftExpr.evaluate(variables) || this.rightExpr.evaluate(variables); } toString() { return `( ${this.leftExpr.toString()} or ${this.rightExpr.toString()} )`; } } class And { leftExpr; rightExpr; constructor(leftExpr, rightExpr) { this.leftExpr = leftExpr; this.rightExpr = rightExpr; } evaluate(variables) { return this.leftExpr.evaluate(variables) && this.rightExpr.evaluate(variables); } toString() { return `( ${this.leftExpr.toString()} and ${this.rightExpr.toString()} )`; } } class Not { expr; constructor(expr) { this.expr = expr; } evaluate(variables) { return !this.expr.evaluate(variables); } toString() { if (this.expr instanceof And || this.expr instanceof Or) { // -- HINT: Binary Operators already have already '( ... )'. return `not ${this.expr.toString()}`; } // -- OTHERWISE: return `not ( ${this.expr.toString()} )`; } } class True { evaluate(_variables) { return true; } toString() { return ''; } } /** * @deprecated Use the named export `parse` instead: `import { parse } from '@cucumber/tag-expressions'` */ export default parse; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxPQUFPLEdBQUcsU0FBUyxDQUFBO0FBQ3pCLE1BQU0sUUFBUSxHQUFHLFVBQVUsQ0FBQTtBQUMzQixNQUFNLElBQUksR0FBOEI7SUFDdEMsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUNQLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDUCxFQUFFLEVBQUUsQ0FBQztJQUNMLEdBQUcsRUFBRSxDQUFDO0lBQ04sR0FBRyxFQUFFLENBQUM7Q0FDUCxDQUFBO0FBQ0QsTUFBTSxLQUFLLEdBQThCO0lBQ3ZDLEVBQUUsRUFBRSxNQUFNO0lBQ1YsR0FBRyxFQUFFLE1BQU07SUFDWCxHQUFHLEVBQUUsT0FBTztDQUNiLENBQUE7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxLQUFLLENBQUMsS0FBYTtJQUNqQyxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUE7SUFDOUIsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3hCLE9BQU8sSUFBSSxJQUFJLEVBQUUsQ0FBQTtJQUNuQixDQUFDO0lBQ0QsTUFBTSxXQUFXLEdBQVcsRUFBRSxDQUFBO0lBQzlCLE1BQU0sU0FBUyxHQUFhLEVBQUUsQ0FBQTtJQUM5QixJQUFJLGlCQUFpQixHQUFHLE9BQU8sQ0FBQTtJQUUvQixNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7UUFDdkIsSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUNuQixLQUFLLENBQUMsaUJBQWlCLEVBQUUsT0FBTyxDQUFDLENBQUE7WUFDakMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQTtZQUNyQixpQkFBaUIsR0FBRyxPQUFPLENBQUE7UUFDN0IsQ0FBQzthQUFNLElBQUksUUFBUSxDQUFDLEtB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SUFBSSxJQUFJLENBQUMsSUFBSSxZQUFZLEVBQUUsRUFBRSxDQUFDO1lBQ3hELDREQUE0RDtZQUM1RCxPQUFPLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFBO1FBQ3RDLENBQUM7UUFDRCxnQkFBZ0I7UUFDaEIsT0FBTyxTQUFTLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQTtJQUMxQyxDQUFDO0NBQ0Y7QUFFRCxNQUFNLElBQUk7SUFDRCxRQUFRLENBQUMsVUFBb0I7UUFDbEMsT0FBTyxJQUFJLENBQUE7SUFDYixDQUFDO0lBRU0sUUFBUTtRQUNiLE9BQU8sRUFBRSxDQUFBO0lBQ1gsQ0FBQztDQUNGO0FBRUQ7O0dBRUc7QUFDSCxlQUFlLEtBQUssQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IE9QRVJBTkQgPSAnb3BlcmFuZCdcbmNvbnN0IE9QRVJBVE9SID0gJ29wZXJhdG9yJ1xuY29uc3QgUFJFQzogeyBba2V5OiBzdHJpbmddOiBudW1iZXIgfSA9IHtcbiAgJygnOiAtMixcbiAgJyknOiAtMSxcbiAgb3I6IDAsXG4gIGFuZDogMSxcbiAgbm90OiAyLFxufVxuY29uc3QgQVNTT0M6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7XG4gIG9yOiAnbGVmdCcsXG4gIGFuZDogJ2xlZnQnLFxuICBub3Q6ICdyaWdodCcsXG59XG5cbi8qKlxuICogUGFyc2VzIGluZml4IGJvb2xlYW4gZXhwcmVzc2lvbiAodXNpbmcgRGlqa3N0cmEncyBTaHVudGluZyBZYXJkIGFsZ29yaXRobSlcbiAqIGFuZCBidWlsZHMgYSB0cmVlIG9mIGV4cHJlc3Npb25zLiBUaGUgcm9vdCBub2RlIG9mIHRoZSBleHByZXNzaW9uIGlzIHJldHVybmVkLlxuICpcbiAqIFRoaXMgZXhwcmVzc2lvbiBjYW4gYmUgZXZhbHVhdGVkIGJ5IHBhc3NpbmcgaW4gYW4gYXJyYXkgb2YgbGl0ZXJhbHMgdGhhdCByZXNvbHZlIHRvIHRydWVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlKGluZml4OiBzdHJpbmcpOiBOb2RlIHtcbiAgY29uc3QgdG9rZW5zID0gdG9rZW5pemUoaW5maXgpXG4gIGlmICh0b2tlbnMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIG5ldyBUcnVlKClcbiAgfVxuICBjb25zdCBleHByZXNzaW9uczogTm9kZVtdID0gW11cbiAgY29uc3Qgb3BlcmF0b3JzOiBzdHJpbmdbXSA9IFtdXG4gIGxldCBleHBlY3RlZFRva2VuVHlwZSA9IE9QRVJBTkRcblxuICB0b2tlbnMuZm9yRWFjaCgodG9rZW4pID0+IHtcbiAgICBpZiAoaXNVbmFyeSh0b2tlbikpIHtcbiAgICAgIGNoZWNrKGV4cGVjdGVkVG9rZW5UeXBlLCBPUEVSQU5EKVxuICAgICAgb3BlcmF0b3JzLnB1c2godG9rZW4pXG4gICAgICBleHBlY3RlZFRva2VuVHlwZSA9IE9QRVJBTkRcbiAgICB9IGVsc2UgaWYgKGlzQmluYXJ5KHRva2VuKSkge1xuICAgICAgY2hlY2soZXhwZWN0ZWRUb2tlblR5cGUsIE9QRVJBVE9SKVxuICAgICAgd2hpbGUgKFxuICAgICAgICBvcGVyYXRvcnMubGVuZ3RoID4gMCAmJlxuICAgICAgICBpc09wKHBlZWsob3BlcmF0b3JzKSkgJiZcbiAgICAgICAgKChBU1NPQ1t0b2tlbl0gPT09ICdsZWZ0JyAmJiBQUkVDW3Rva2VuXSA8PSBQUkVDW3BlZWsob3BlcmF0b3JzKV0pIHx8XG4gICAgICAgICAgKEFTU09DW3Rva2VuXSA9PT0gJ3JpZ2h0JyAmJiBQUkVDW3Rva2VuXSA8IFBSRUNbcGVlayhvcGVyYXRvcnMpXSkpXG4gICAgICApIHtcbiAgICAgICAgcHVzaEV4cHIob3BlcmF0b3JzLnBvcCgpIGFzIHN0cmluZywgZXhwcmVzc2lvbnMpXG4gICAgICB9XG4gICAgICBvcGVyYXRvcnMucHVzaCh0b2tlbilcbiAgICAgIGV4cGVjdGVkVG9rZW5UeXBlID0gT1BFUkFORFxuICAgIH0gZWxzZSBpZiAoJygnID09PSB0b2tlbikge1xuICAgICAgY2hlY2soZXhwZWN0ZWRUb2tlblR5cGUsIE9QRVJBTkQpXG4gICAgICBvcGVyYXRvcnMucHVzaCh0b2tlbilcbiAgICAgIGV4cGVjdGVkVG9rZW5UeXBlID0gT1BFUkFORFxuICAgIH0gZWxzZSBpZiAoJyknID09PSB0b2tlbikge1xuICAgICAgY2hlY2soZXhwZWN0ZWRUb2tlblR5cGUsIE9QRVJBVE9SKVxuICAgICAgd2hpbGUgKG9wZXJhdG9ycy5sZW5ndGggPiAwICYmIHBlZWsob3BlcmF0b3JzKSAhPT0gJygnKSB7XG4gICAgICAgIHB1c2hFeHByKG9wZXJhdG9ycy5wb3AoKSBhcyBzdHJpbmcsIGV4cHJlc3Npb25zKVxuICAgICAgfVxuICAgICAgaWYgKG9wZXJhdG9ycy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBUYWcgZXhwcmVzc2lvbiBcIiR7aW5maXh9XCIgY291bGQgbm90IGJlIHBhcnNlZCBiZWNhdXNlIG9mIHN5bnRheCBlcnJvcjogVW5tYXRjaGVkICkuYFxuICAgICAgICApXG4gICAgICB9XG4gICAgICBpZiAocGVlayhvcGVyYXRvcnMpID09PSAnKCcpIHtcbiAgICAgICAgb3BlcmF0b3JzLnBvcCgpXG4gICAgICB9XG4gICAgICBleHBlY3RlZFRva2VuVHlwZSA9IE9QRVJBVE9SXG4gICAgfSBlbHNlIHtcbiAgICAgIGNoZWNrKGV4cGVjdGVkVG9rZW5UeXBlLCBPUEVSQU5EKVxuICAgICAgcHVzaEV4cHIodG9rZW4sIGV4cHJlc3Npb25zKVxuICAgICAgZXhwZWN0ZWRUb2tlblR5cGUgPSBPUEVSQVRPUlxuICAgIH1cbiAgfSlcblxuICB3aGlsZSAob3BlcmF0b3JzLmxlbmd0aCA+IDApIHtcbiAgICBpZiAocGVlayhvcGVyYXRvcnMpID09PSAnKCcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFRhZyBleHByZXNzaW9uIFwiJHtpbmZpeH1cIiBjb3VsZCBub3QgYmUgcGFyc2VkIGJlY2F1c2Ugb2Ygc3ludGF4IGVycm9yOiBVbm1hdGNoZWQgKC5gXG4gICAgICApXG4gICAgfVxuICAgIHB1c2hFeHByKG9wZXJhdG9ycy5wb3AoKSBhcyBzdHJpbmcsIGV4cHJlc3Npb25zKVxuICB9XG5cbiAgcmV0dXJuIGV4cHJlc3Npb25zLnBvcCgpIGFzIE5vZGVcblxuICBmdW5jdGlvbiBjaGVjayhleHBlY3RlZFRva2VuVHlwZTogc3RyaW5nLCB0b2tlblR5cGU6IHN0cmluZykge1xuICAgIGlmIChleHBlY3RlZFRva2VuVHlwZSAhPT0gdG9rZW5UeXBlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBUYWcgZXhwcmVzc2lvbiBcIiR7aW5maXh9XCIgY291bGQgbm90IGJlIHBhcnNlZCBiZWNhdXNlIG9mIHN5bnRheCBlcnJvcjogRXhwZWN0ZWQgJHtleHBlY3RlZFRva2VuVHlwZX0uYFxuICAgICAgKVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHB1c2hFeHByKHRva2VuOiBzdHJpbmcsIHN0YWNrOiBOb2RlW10pIHtcbiAgICBpZiAodG9rZW4gPT09ICdhbmQnKSB7XG4gICAgICBjb25zdCByaWdodEFuZEV4cHIgPSBwb3BPcGVyYW5kKHN0YWNrKVxuICAgICAgc3RhY2sucHVzaChuZXcgQW5kKHBvcE9wZXJhbmQoc3RhY2spLCByaWdodEFuZEV4cHIpKVxuICAgIH0gZWxzZSBpZiAodG9rZW4gPT09ICdvcicpIHtcbiAgICAgIGNvbnN0IHJpZ2h0T3JFeHByID0gcG9wT3BlcmFuZChzdGFjaylcbiAgICAgIHN0YWNrLnB1c2gobmV3IE9yKHBvcE9wZXJhbmQoc3RhY2spLCByaWdodE9yRXhwcikpXG4gICAgfSBlbHNlIGlmICh0b2tlbiA9PT0gJ25vdCcpIHtcbiAgICAgIHN0YWNrLnB1c2gobmV3IE5vdChwb3BPcGVyYW5kKHN0YWNrKSkpXG4gICAgfSBlbHNlIHtcbiAgICAgIHN0YWNrLnB1c2gobmV3IExpdGVyYWwodG9rZW4pKVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHBvcE9wZXJhbmQ8VD4oc3RhY2s6IFRbXSk6IFQge1xuICAgIGlmIChzdGFjay5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFRhZyBleHByZXNzaW9uIFwiJHtpbmZpeH1cIiBjb3VsZCBub3QgYmUgcGFyc2VkIGJlY2F1c2Ugb2Ygc3ludGF4IGVycm9yOiBFeHBlY3RlZCBvcGVyYW5kLmBcbiAgICAgIClcbiAgICB9XG4gICAgcmV0dXJuIHN0YWNrLnBvcCgpIGFzIFRcbiAgfVxufVxuXG5mdW5jdGlvbiB0b2tlbml6ZShleHByOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIGNvbnN0IHRva2VucyA9IFtdXG4gIGxldCBpc0VzY2FwZWQgPSBmYWxzZVxuICBsZXQgdG9rZW46IHN0cmluZ1tdID0gW11cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBleHByLmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgYyA9IGV4cHIuY2hhckF0KGkpXG4gICAgaWYgKGlzRXNjYXBlZCkge1xuICAgICAgaWYgKGMgPT09ICcoJyB8fCBjID09PSAnKScgfHwgYyA9PT0gJ1xcXFwnIHx8IC9cXHMvLnRlc3QoYykpIHtcbiAgICAgICAgdG9rZW4ucHVzaChjKVxuICAgICAgICBpc0VzY2FwZWQgPSBmYWxzZVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBUYWcgZXhwcmVzc2lvbiBcIiR7ZXhwcn1cIiBjb3VsZCBub3QgYmUgcGFyc2VkIGJlY2F1c2Ugb2Ygc3ludGF4IGVycm9yOiBJbGxlZ2FsIGVzY2FwZSBiZWZvcmUgXCIke2N9XCIuYFxuICAgICAgICApXG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChjID09PSAnXFxcXCcpIHtcbiAgICAgIGlzRXNjYXBlZCA9IHRydWVcbiAgICB9IGVsc2UgaWYgKGMgPT09ICcoJyB8fCBjID09PSAnKScgfHwgL1xccy8udGVzdChjKSkge1xuICAgICAgaWYgKHRva2VuLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdG9rZW5zLnB1c2godG9rZW4uam9pbignJykpXG4gICAgICAgIHRva2VuID0gW11cbiAgICAgIH1cbiAgICAgIGlmICghL1xccy8udGVzdChjKSkge1xuICAgICAgICB0b2tlbnMucHVzaChjKVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0b2tlbi5wdXNoKGMpXG4gICAgfVxuICB9XG4gIGlmICh0b2tlbi5sZW5ndGggPiAwKSB7XG4gICAgdG9rZW5zLnB1c2godG9rZW4uam9pbignJykpXG4gIH1cbiAgcmV0dXJuIHRva2Vuc1xufVxuXG5mdW5jdGlvbiBpc1VuYXJ5KHRva2VuOiBzdHJpbmcpIHtcbiAgcmV0dXJuICdub3QnID09PSB0b2tlblxufVxuXG5mdW5jdGlvbiBpc0JpbmFyeSh0b2tlbjogc3RyaW5nKSB7XG4gIHJldHVybiAnb3InID09PSB0b2tlbiB8fCAnYW5kJyA9PT0gdG9rZW5cbn1cblxuZnVuY3Rpb24gaXNPcCh0b2tlbjogc3RyaW5nKSB7XG4gIHJldHVybiBBU1NPQ1t0b2tlbl0gIT09IHVuZGVmaW5lZFxufVxuXG5mdW5jdGlvbiBwZWVrKHN0YWNrOiBzdHJpbmdbXSkge1xuICByZXR1cm4gc3RhY2tbc3RhY2subGVuZ3RoIC0gMV1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBOb2RlIHtcbiAgZXZhbHVhdGUodmFyaWFibGVzOiBzdHJpbmdbXSk6IGJvb2xlYW5cbn1cblxuY2xhc3MgTGl0ZXJhbCBpbXBsZW1lbnRzIE5vZGUge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHZhbHVlOiBzdHJpbmcpIHt9XG5cbiAgcHVibGljIGV2YWx1YXRlKHZhcmlhYmxlczogc3RyaW5nW10pIHtcbiAgICByZXR1cm4gdmFyaWFibGVzLmluZGV4T2YodGhpcy52YWx1ZSkgIT09IC0xXG4gIH1cblxuICBwdWJsaWMgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVcbiAgICAgIC5yZXBsYWNlKC9cXFxcL2csICdcXFxcXFxcXCcpXG4gICAgICAucmVwbGFjZSgvXFwoL2csICdcXFxcKCcpXG4gICAgICAucmVwbGFjZSgvXFwpL2csICdcXFxcKScpXG4gICAgICAucmVwbGFjZSgvXFxzL2csICdcXFxcICcpXG4gIH1cbn1cblxuY2xhc3MgT3IgaW1wbGVtZW50cyBOb2RlIHtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBsZWZ0RXhwcjogTm9kZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHJpZ2h0RXhwcjogTm9kZVxuICApIHt9XG5cbiAgcHVibGljIGV2YWx1YXRlKHZhcmlhYmxlczogc3RyaW5nW10pIHtcbiAgICByZXR1cm4gdGhpcy5sZWZ0RXhwci5ldmFsdWF0ZSh2YXJpYWJsZXMpIHx8IHRoaXMucmlnaHRFeHByLmV2YWx1YXRlKHZhcmlhYmxlcylcbiAgfVxuXG4gIHB1YmxpYyB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gYCggJHt0aGlzLmxlZnRFeHByLnRvU3RyaW5nKCl9IG9yICR7dGhpcy5yaWdodEV4cHIudG9TdHJpbmcoKX0gKWBcbiAgfVxufVxuXG5jbGFzcyBBbmQgaW1wbGVtZW50cyBOb2RlIHtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBsZWZ0RXhwcjogTm9kZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHJpZ2h0RXhwcjogTm9kZVxuICApIHt9XG5cbiAgcHVibGljIGV2YWx1YXRlKHZhcmlhYmxlczogc3RyaW5nW10pIHtcbiAgICByZXR1cm4gdGhpcy5sZWZ0RXhwci5ldmFsdWF0ZSh2YXJpYWJsZXMpICYmIHRoaXMucmlnaHRFeHByLmV2YWx1YXRlKHZhcmlhYmxlcylcbiAgfVxuXG4gIHB1YmxpYyB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gYCggJHt0aGlzLmxlZnRFeHByLnRvU3RyaW5nKCl9IGFuZCAke3RoaXMucmlnaHRFeHByLnRvU3RyaW5nKCl9IClgXG4gIH1cbn1cblxuY2xhc3MgTm90IGltcGxlbWVudHMgTm9kZSB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgZXhwcjogTm9kZSkge31cblxuICBwdWJsaWMgZXZhbHVhdGUodmFyaWFibGVzOiBzdHJpbmdbXSkge1xuICAgIHJldHVybiAhdGhpcy5leHByLmV2YWx1YXRlKHZhcmlhYmxlcylcbiAgfVxuXG4gIHB1YmxpYyB0b1N0cmluZygpIHtcbiAgICBpZiAodGhpcy5leHByIGluc3RhbmNlb2YgQW5kIHx8IHRoaXMuZXhwciBpbnN0YW5jZW9mIE9yKSB7XG4gICAgICAvLyAtLSBISU5UOiBCaW5hcnkgT3BlcmF0b3JzIGFscmVhZHkgaGF2ZSBhbHJlYWR5ICcoIC4uLiApJy5cbiAgICAgIHJldHVybiBgbm90ICR7dGhpcy5leHByLnRvU3RyaW5nKCl9YFxuICAgIH1cbiAgICAvLyAtLSBPVEhFUldJU0U6XG4gICAgcmV0dXJuIGBub3QgKCAke3RoaXMuZXhwci50b1N0cmluZygpfSApYFxuICB9XG59XG5cbmNsYXNzIFRydWUgaW1wbGVtZW50cyBOb2RlIHtcbiAgcHVibGljIGV2YWx1YXRlKF92YXJpYWJsZXM6IHN0cmluZ1tdKSB7XG4gICAgcmV0dXJuIHRydWVcbiAgfVxuXG4gIHB1YmxpYyB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gJydcbiAgfVxufVxuXG4vKipcbiAqIEBkZXByZWNhdGVkIFVzZSB0aGUgbmFtZWQgZXhwb3J0IGBwYXJzZWAgaW5zdGVhZDogYGltcG9ydCB7IHBhcnNlIH0gZnJvbSAnQGN1Y3VtYmVyL3RhZy1leHByZXNzaW9ucydgXG4gKi9cbmV4cG9ydCBkZWZhdWx0IHBhcnNlXG4iXX0=