astx
Version:
super powerful structural search and replace for JavaScript and TypeScript to automate your refactoring
250 lines (228 loc) • 21.2 kB
JavaScript
import { mergeCaptures } from './index.mjs'
import convertToJSXIdentifierName from '../convertReplacement/convertToJSXIdentifierName.mjs'
export function unescapeIdentifier(identifier) {
return identifier.replace(/^\$_/, '$')
}
export function getPlaceholder(identifier) {
var _exec
return (_exec = /^\$([a-z0-9]+.*)?$/i.exec(identifier)) === null ||
_exec === void 0
? void 0
: _exec[0]
}
export function getArrayPlaceholder(identifier) {
var _exec2
return (_exec2 = /^\${2}([a-z0-9]+.*)?$/i.exec(identifier)) === null ||
_exec2 === void 0
? void 0
: _exec2[0]
}
export function getRestPlaceholder(identifier) {
var _exec3
return (_exec3 = /^\${3}([a-z0-9]+.*)?$/i.exec(identifier)) === null ||
_exec3 === void 0
? void 0
: _exec3[0]
}
export function isPlaceholder(identifier) {
var _exec4
return (_exec4 = /^\${1,3}([a-z0-9]+.*)?$/i.exec(identifier)) === null ||
_exec4 === void 0
? void 0
: _exec4[0]
}
export function isCapturePlaceholder(identifier) {
return /[^$]/.test(identifier)
}
export function compileArrayPlaceholderMatcher(
pattern,
identifier, // eslint-disable-next-line @typescript-eslint/no-unused-vars
compileOptions,
otherOptions
) {
const arrayPlaceholder = getArrayPlaceholder(identifier)
if (arrayPlaceholder) {
return {
pattern,
arrayPlaceholder,
nodeType:
otherOptions === null || otherOptions === void 0
? void 0
: otherOptions.nodeType,
match: () => {
throw new Error(
`array capture placeholder ${arrayPlaceholder} is in an invalid position`
)
},
}
}
}
export function compileRestPlaceholderMatcher(
pattern,
identifier, // eslint-disable-next-line @typescript-eslint/no-unused-vars
compileOptions,
otherOptions
) {
const restPlaceholder = getRestPlaceholder(identifier)
if (restPlaceholder) {
return {
pattern,
restPlaceholder,
nodeType:
otherOptions === null || otherOptions === void 0
? void 0
: otherOptions.nodeType,
match: () => {
throw new Error(
`rest capture placeholder ${restPlaceholder} is in an invalid position`
)
},
}
}
}
export function capturesAreEquivalent(backend, a, b) {
if (backend.t.astNodesAreEquivalent(a, b)) return true
const aIdent = convertToJSXIdentifierName(a)
const bIdent = convertToJSXIdentifierName(b)
return aIdent ? aIdent === bIdent : false
}
export default function compilePlaceholderMatcher(
pattern,
identifier,
compileOptions,
otherOptions
) {
const { debug } = compileOptions
const placeholder = getPlaceholder(identifier)
if (placeholder) {
var _compileOptions$where, _otherOptions$getCond
const whereCondition =
placeholder === '$'
? undefined
: compileOptions === null || compileOptions === void 0
? void 0
: (_compileOptions$where = compileOptions.where) === null ||
_compileOptions$where === void 0
? void 0
: _compileOptions$where[placeholder]
const condition =
(otherOptions === null || otherOptions === void 0
? void 0
: (_otherOptions$getCond = otherOptions.getCondition) === null ||
_otherOptions$getCond === void 0
? void 0
: _otherOptions$getCond.call(otherOptions)) || (() => true)
const nodeType =
otherOptions === null || otherOptions === void 0
? void 0
: otherOptions.nodeType
return {
pattern,
placeholder,
nodeType,
match: (path, matchSoFar) => {
var _matchSoFar$captures
if (path.value == null) return null
debug('Placeholder', placeholder)
if (!condition(path)) {
debug(' condition returned false')
return null
}
if (placeholder === '$') return matchSoFar || {}
const existingCapture =
matchSoFar === null || matchSoFar === void 0
? void 0
: (_matchSoFar$captures = matchSoFar.captures) === null ||
_matchSoFar$captures === void 0
? void 0
: _matchSoFar$captures[placeholder]
if (existingCapture) {
return capturesAreEquivalent(
compileOptions.backend,
existingCapture.node,
path.value
)
? matchSoFar
: null
}
if (whereCondition && !whereCondition(path)) {
debug(' where condition returned false')
return null
}
debug(' captured as %s', placeholder)
return mergeCaptures(matchSoFar, {
captures: {
[placeholder]: path,
},
})
},
}
}
return (
compileArrayPlaceholderMatcher(
pattern,
identifier,
compileOptions,
otherOptions
) ||
compileRestPlaceholderMatcher(
pattern,
identifier,
compileOptions,
otherOptions
)
)
}
export function compileStringPlaceholderMatcher(
pattern,
getString,
compileOptions,
otherOptions
) {
const { debug } = compileOptions
const string = getString(pattern.value)
if (!string) return
const placeholder = getPlaceholder(string)
const nodeType =
otherOptions === null || otherOptions === void 0
? void 0
: otherOptions.nodeType
if (placeholder) {
return {
pattern,
placeholder,
nodeType,
match: (path, matchSoFar) => {
var _path$value, _matchSoFar$stringCap
if (
((_path$value = path.value) === null || _path$value === void 0
? void 0
: _path$value.type) !== pattern.value.type
)
return null
debug('String Placeholder', placeholder)
const string = getString(path.value)
if (!string) return null
const existingCapture =
matchSoFar === null || matchSoFar === void 0
? void 0
: (_matchSoFar$stringCap = matchSoFar.stringCaptures) === null ||
_matchSoFar$stringCap === void 0
? void 0
: _matchSoFar$stringCap[placeholder]
if (existingCapture) {
return string === existingCapture ? matchSoFar : null
}
debug(' captured as %s', placeholder)
return mergeCaptures(matchSoFar, {
captures: {
[placeholder]: path,
},
stringCaptures: {
[placeholder]: string,
},
})
},
}
}
} //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJtZXJnZUNhcHR1cmVzIiwiY29udmVydFRvSlNYSWRlbnRpZmllck5hbWUiLCJ1bmVzY2FwZUlkZW50aWZpZXIiLCJpZGVudGlmaWVyIiwicmVwbGFjZSIsImdldFBsYWNlaG9sZGVyIiwiZXhlYyIsImdldEFycmF5UGxhY2Vob2xkZXIiLCJnZXRSZXN0UGxhY2Vob2xkZXIiLCJpc1BsYWNlaG9sZGVyIiwiaXNDYXB0dXJlUGxhY2Vob2xkZXIiLCJ0ZXN0IiwiY29tcGlsZUFycmF5UGxhY2Vob2xkZXJNYXRjaGVyIiwicGF0dGVybiIsImNvbXBpbGVPcHRpb25zIiwib3RoZXJPcHRpb25zIiwiYXJyYXlQbGFjZWhvbGRlciIsIm5vZGVUeXBlIiwibWF0Y2giLCJFcnJvciIsImNvbXBpbGVSZXN0UGxhY2Vob2xkZXJNYXRjaGVyIiwicmVzdFBsYWNlaG9sZGVyIiwiY2FwdHVyZXNBcmVFcXVpdmFsZW50IiwiYmFja2VuZCIsImEiLCJiIiwidCIsImFzdE5vZGVzQXJlRXF1aXZhbGVudCIsImFJZGVudCIsImJJZGVudCIsImNvbXBpbGVQbGFjZWhvbGRlck1hdGNoZXIiLCJkZWJ1ZyIsInBsYWNlaG9sZGVyIiwid2hlcmVDb25kaXRpb24iLCJ1bmRlZmluZWQiLCJ3aGVyZSIsImNvbmRpdGlvbiIsImdldENvbmRpdGlvbiIsInBhdGgiLCJtYXRjaFNvRmFyIiwidmFsdWUiLCJleGlzdGluZ0NhcHR1cmUiLCJjYXB0dXJlcyIsIm5vZGUiLCJjb21waWxlU3RyaW5nUGxhY2Vob2xkZXJNYXRjaGVyIiwiZ2V0U3RyaW5nIiwic3RyaW5nIiwidHlwZSIsInN0cmluZ0NhcHR1cmVzIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbXBpbGVNYXRjaGVyL1BsYWNlaG9sZGVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBpbGVPcHRpb25zLCBNYXRjaFJlc3VsdCwgbWVyZ2VDYXB0dXJlcywgQ29tcGlsZWRNYXRjaGVyIH0gZnJvbSAnLidcbmltcG9ydCB7IE5vZGUsIE5vZGVQYXRoLCBOb2RlVHlwZSB9IGZyb20gJy4uL3R5cGVzJ1xuaW1wb3J0IGNvbnZlcnRUb0pTWElkZW50aWZpZXJOYW1lIGZyb20gJy4uL2NvbnZlcnRSZXBsYWNlbWVudC9jb252ZXJ0VG9KU1hJZGVudGlmaWVyTmFtZSdcbmltcG9ydCB7IEJhY2tlbmQgfSBmcm9tICcuLi9iYWNrZW5kL0JhY2tlbmQnXG5cbmV4cG9ydCBmdW5jdGlvbiB1bmVzY2FwZUlkZW50aWZpZXIoaWRlbnRpZmllcjogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGlkZW50aWZpZXIucmVwbGFjZSgvXlxcJF8vLCAnJCcpXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRQbGFjZWhvbGRlcihpZGVudGlmaWVyOiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICByZXR1cm4gL15cXCQoW2EtejAtOV0rLiopPyQvaS5leGVjKGlkZW50aWZpZXIpPy5bMF1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEFycmF5UGxhY2Vob2xkZXIoaWRlbnRpZmllcjogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIC9eXFwkezJ9KFthLXowLTldKy4qKT8kL2kuZXhlYyhpZGVudGlmaWVyKT8uWzBdXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRSZXN0UGxhY2Vob2xkZXIoaWRlbnRpZmllcjogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIC9eXFwkezN9KFthLXowLTldKy4qKT8kL2kuZXhlYyhpZGVudGlmaWVyKT8uWzBdXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1BsYWNlaG9sZGVyKGlkZW50aWZpZXI6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiAvXlxcJHsxLDN9KFthLXowLTldKy4qKT8kL2kuZXhlYyhpZGVudGlmaWVyKT8uWzBdXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0NhcHR1cmVQbGFjZWhvbGRlcihpZGVudGlmaWVyOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIC9bXiRdLy50ZXN0KGlkZW50aWZpZXIpXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjb21waWxlQXJyYXlQbGFjZWhvbGRlck1hdGNoZXIoXG4gIHBhdHRlcm46IE5vZGVQYXRoLFxuICBpZGVudGlmaWVyOiBzdHJpbmcsXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgY29tcGlsZU9wdGlvbnM6IENvbXBpbGVPcHRpb25zLFxuICBvdGhlck9wdGlvbnM/OiB7XG4gICAgbm9kZVR5cGU/OiBOb2RlVHlwZSB8IE5vZGVUeXBlW11cbiAgICBjb25kaXRpb24/OiAocGF0aDogTm9kZVBhdGgpID0+IGJvb2xlYW5cbiAgfVxuKTogQ29tcGlsZWRNYXRjaGVyIHwgdm9pZCB7XG4gIGNvbnN0IGFycmF5UGxhY2Vob2xkZXIgPSBnZXRBcnJheVBsYWNlaG9sZGVyKGlkZW50aWZpZXIpXG4gIGlmIChhcnJheVBsYWNlaG9sZGVyKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHBhdHRlcm4sXG4gICAgICBhcnJheVBsYWNlaG9sZGVyLFxuICAgICAgbm9kZVR5cGU6IG90aGVyT3B0aW9ucz8ubm9kZVR5cGUsXG4gICAgICBtYXRjaDogKCk6IE1hdGNoUmVzdWx0ID0+IHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBhcnJheSBjYXB0dXJlIHBsYWNlaG9sZGVyICR7YXJyYXlQbGFjZWhvbGRlcn0gaXMgaW4gYW4gaW52YWxpZCBwb3NpdGlvbmBcbiAgICAgICAgKVxuICAgICAgfSxcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbXBpbGVSZXN0UGxhY2Vob2xkZXJNYXRjaGVyKFxuICBwYXR0ZXJuOiBOb2RlUGF0aCxcbiAgaWRlbnRpZmllcjogc3RyaW5nLFxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIGNvbXBpbGVPcHRpb25zOiBDb21waWxlT3B0aW9ucyxcbiAgb3RoZXJPcHRpb25zPzoge1xuICAgIG5vZGVUeXBlPzogTm9kZVR5cGUgfCBOb2RlVHlwZVtdXG4gICAgY29uZGl0aW9uPzogKHBhdGg6IE5vZGVQYXRoKSA9PiBib29sZWFuXG4gIH1cbik6IENvbXBpbGVkTWF0Y2hlciB8IHZvaWQge1xuICBjb25zdCByZXN0UGxhY2Vob2xkZXIgPSBnZXRSZXN0UGxhY2Vob2xkZXIoaWRlbnRpZmllcilcbiAgaWYgKHJlc3RQbGFjZWhvbGRlcikge1xuICAgIHJldHVybiB7XG4gICAgICBwYXR0ZXJuLFxuICAgICAgcmVzdFBsYWNlaG9sZGVyLFxuICAgICAgbm9kZVR5cGU6IG90aGVyT3B0aW9ucz8ubm9kZVR5cGUsXG4gICAgICBtYXRjaDogKCk6IE1hdGNoUmVzdWx0ID0+IHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGByZXN0IGNhcHR1cmUgcGxhY2Vob2xkZXIgJHtyZXN0UGxhY2Vob2xkZXJ9IGlzIGluIGFuIGludmFsaWQgcG9zaXRpb25gXG4gICAgICAgIClcbiAgICAgIH0sXG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjYXB0dXJlc0FyZUVxdWl2YWxlbnQoXG4gIGJhY2tlbmQ6IEJhY2tlbmQsXG4gIGE6IE5vZGUsXG4gIGI6IE5vZGVcbik6IGJvb2xlYW4ge1xuICBpZiAoYmFja2VuZC50LmFzdE5vZGVzQXJlRXF1aXZhbGVudChhLCBiKSkgcmV0dXJuIHRydWVcbiAgY29uc3QgYUlkZW50ID0gY29udmVydFRvSlNYSWRlbnRpZmllck5hbWUoYSlcbiAgY29uc3QgYklkZW50ID0gY29udmVydFRvSlNYSWRlbnRpZmllck5hbWUoYilcbiAgcmV0dXJuIGFJZGVudCA/IGFJZGVudCA9PT0gYklkZW50IDogZmFsc2Vcbn1cblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gY29tcGlsZVBsYWNlaG9sZGVyTWF0Y2hlcihcbiAgcGF0dGVybjogTm9kZVBhdGgsXG4gIGlkZW50aWZpZXI6IHN0cmluZyxcbiAgY29tcGlsZU9wdGlvbnM6IENvbXBpbGVPcHRpb25zLFxuICBvdGhlck9wdGlvbnM/OiB7XG4gICAgbm9kZVR5cGU/OiBOb2RlVHlwZSB8IE5vZGVUeXBlW11cbiAgICBnZXRDb25kaXRpb24/OiAoKSA9PiAoKHBhdGg6IE5vZGVQYXRoKSA9PiBib29sZWFuKSB8IHVuZGVmaW5lZFxuICB9XG4pOiBDb21waWxlZE1hdGNoZXIgfCB2b2lkIHtcbiAgY29uc3QgeyBkZWJ1ZyB9ID0gY29tcGlsZU9wdGlvbnNcbiAgY29uc3QgcGxhY2Vob2xkZXIgPSBnZXRQbGFjZWhvbGRlcihpZGVudGlmaWVyKVxuICBpZiAocGxhY2Vob2xkZXIpIHtcbiAgICBjb25zdCB3aGVyZUNvbmRpdGlvbiA9XG4gICAgICBwbGFjZWhvbGRlciA9PT0gJyQnID8gdW5kZWZpbmVkIDogY29tcGlsZU9wdGlvbnM/LndoZXJlPy5bcGxhY2Vob2xkZXJdXG4gICAgY29uc3QgY29uZGl0aW9uID0gb3RoZXJPcHRpb25zPy5nZXRDb25kaXRpb24/LigpIHx8ICgoKSA9PiB0cnVlKVxuICAgIGNvbnN0IG5vZGVUeXBlID0gb3RoZXJPcHRpb25zPy5ub2RlVHlwZVxuICAgIHJldHVybiB7XG4gICAgICBwYXR0ZXJuLFxuICAgICAgcGxhY2Vob2xkZXIsXG4gICAgICBub2RlVHlwZSxcbiAgICAgIG1hdGNoOiAocGF0aDogTm9kZVBhdGgsIG1hdGNoU29GYXI6IE1hdGNoUmVzdWx0KTogTWF0Y2hSZXN1bHQgPT4ge1xuICAgICAgICBpZiAocGF0aC52YWx1ZSA9PSBudWxsKSByZXR1cm4gbnVsbFxuICAgICAgICBkZWJ1ZygnUGxhY2Vob2xkZXInLCBwbGFjZWhvbGRlcilcbiAgICAgICAgaWYgKCFjb25kaXRpb24ocGF0aCkpIHtcbiAgICAgICAgICBkZWJ1ZygnICBjb25kaXRpb24gcmV0dXJuZWQgZmFsc2UnKVxuICAgICAgICAgIHJldHVybiBudWxsXG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBsYWNlaG9sZGVyID09PSAnJCcpIHJldHVybiBtYXRjaFNvRmFyIHx8IHt9XG4gICAgICAgIGNvbnN0IGV4aXN0aW5nQ2FwdHVyZSA9IG1hdGNoU29GYXI/LmNhcHR1cmVzPy5bcGxhY2Vob2xkZXJdXG4gICAgICAgIGlmIChleGlzdGluZ0NhcHR1cmUpIHtcbiAgICAgICAgICByZXR1cm4gY2FwdHVyZXNBcmVFcXVpdmFsZW50KFxuICAgICAgICAgICAgY29tcGlsZU9wdGlvbnMuYmFja2VuZCxcbiAgICAgICAgICAgIGV4aXN0aW5nQ2FwdHVyZS5ub2RlLFxuICAgICAgICAgICAgcGF0aC52YWx1ZVxuICAgICAgICAgIClcbiAgICAgICAgICAgID8gbWF0Y2hTb0ZhclxuICAgICAgICAgICAgOiBudWxsXG4gICAgICAgIH1cbiAgICAgICAgaWYgKHdoZXJlQ29uZGl0aW9uICYmICF3aGVyZUNvbmRpdGlvbihwYXRoKSkge1xuICAgICAgICAgIGRlYnVnKCcgIHdoZXJlIGNvbmRpdGlvbiByZXR1cm5lZCBmYWxzZScpXG4gICAgICAgICAgcmV0dXJuIG51bGxcbiAgICAgICAgfVxuICAgICAgICBkZWJ1ZygnICBjYXB0dXJlZCBhcyAlcycsIHBsYWNlaG9sZGVyKVxuICAgICAgICByZXR1cm4gbWVyZ2VDYXB0dXJlcyhtYXRjaFNvRmFyLCB7IGNhcHR1cmVzOiB7IFtwbGFjZWhvbGRlcl06IHBhdGggfSB9KVxuICAgICAgfSxcbiAgICB9XG4gIH1cbiAgcmV0dXJuIChcbiAgICBjb21waWxlQXJyYXlQbGFjZWhvbGRlck1hdGNoZXIoXG4gICAgICBwYXR0ZXJuLFxuICAgICAgaWRlbnRpZmllcixcbiAgICAgIGNvbXBpbGVPcHRpb25zLFxuICAgICAgb3RoZXJPcHRpb25zXG4gICAgKSB8fFxuICAgIGNvbXBpbGVSZXN0UGxhY2Vob2xkZXJNYXRjaGVyKFxuICAgICAgcGF0dGVybixcbiAgICAgIGlkZW50aWZpZXIsXG4gICAgICBjb21waWxlT3B0aW9ucyxcbiAgICAgIG90aGVyT3B0aW9uc1xuICAgIClcbiAgKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gY29tcGlsZVN0cmluZ1BsYWNlaG9sZGVyTWF0Y2hlcjxOIGV4dGVuZHMgTm9kZT4oXG4gIHBhdHRlcm46IE5vZGVQYXRoPE4+LFxuICBnZXRTdHJpbmc6IChub2RlOiBOKSA9PiBzdHJpbmcgfCBudWxsLFxuICBjb21waWxlT3B0aW9uczogQ29tcGlsZU9wdGlvbnMsXG4gIG90aGVyT3B0aW9ucz86IHtcbiAgICBub2RlVHlwZT86IE5vZGVUeXBlIHwgTm9kZVR5cGVbXVxuICB9XG4pOiBDb21waWxlZE1hdGNoZXIgfCB2b2lkIHtcbiAgY29uc3QgeyBkZWJ1ZyB9ID0gY29tcGlsZU9wdGlvbnNcbiAgY29uc3Qgc3RyaW5nID0gZ2V0U3RyaW5nKHBhdHRlcm4udmFsdWUpXG4gIGlmICghc3RyaW5nKSByZXR1cm5cbiAgY29uc3QgcGxhY2Vob2xkZXIgPSBnZXRQbGFjZWhvbGRlcihzdHJpbmcpXG4gIGNvbnN0IG5vZGVUeXBlID0gb3RoZXJPcHRpb25zPy5ub2RlVHlwZVxuICBpZiAocGxhY2Vob2xkZXIpIHtcbiAgICByZXR1cm4ge1xuICAgICAgcGF0dGVybixcbiAgICAgIHBsYWNlaG9sZGVyLFxuICAgICAgbm9kZVR5cGUsXG4gICAgICBtYXRjaDogKHBhdGg6IE5vZGVQYXRoLCBtYXRjaFNvRmFyOiBNYXRjaFJlc3VsdCk6IE1hdGNoUmVzdWx0ID0+IHtcbiAgICAgICAgaWYgKHBhdGgudmFsdWU/LnR5cGUgIT09IHBhdHRlcm4udmFsdWUudHlwZSkgcmV0dXJuIG51bGxcbiAgICAgICAgZGVidWcoJ1N0cmluZyBQbGFjZWhvbGRlcicsIHBsYWNlaG9sZGVyKVxuICAgICAgICBjb25zdCBzdHJpbmcgPSBnZXRTdHJpbmcoKHBhdGggYXMgTm9kZVBhdGg8Tj4pLnZhbHVlKVxuICAgICAgICBpZiAoIXN0cmluZykgcmV0dXJuIG51bGxcbiAgICAgICAgY29uc3QgZXhpc3RpbmdDYXB0dXJlID0gbWF0Y2hTb0Zhcj8uc3RyaW5nQ2FwdHVyZXM/LltwbGFjZWhvbGRlcl1cbiAgICAgICAgaWYgKGV4aXN0aW5nQ2FwdHVyZSkge1xuICAgICAgICAgIHJldHVybiBzdHJpbmcgPT09IGV4aXN0aW5nQ2FwdHVyZSA/IG1hdGNoU29GYXIgOiBudWxsXG4gICAgICAgIH1cbiAgICAgICAgZGVidWcoJyAgY2FwdHVyZWQgYXMgJXMnLCBwbGFjZWhvbGRlcilcbiAgICAgICAgcmV0dXJuIG1lcmdlQ2FwdHVyZXMobWF0Y2hTb0Zhciwge1xuICAgICAgICAgIGNhcHR1cmVzOiB7IFtwbGFjZWhvbGRlcl06IHBhdGggfSxcbiAgICAgICAgICBzdHJpbmdDYXB0dXJlczogeyBbcGxhY2Vob2xkZXJdOiBzdHJpbmcgfSxcbiAgICAgICAgfSlcbiAgICAgIH0sXG4gICAgfVxuICB9XG59XG4iXSwibWFwcGluZ3MiOiJBQUFBLFNBQXNDQSxhQUF0QyxRQUE0RSxHQUE1RTs7QUFFQSxPQUFPQywwQkFBUCxNQUF1QyxrREFBdkM7OztBQUdBLE9BQU8sU0FBU0Msa0JBQVQsQ0FBNEJDLFVBQTVCLEVBQXdEO0VBQzdELE9BQU9BLFVBQVUsQ0FBQ0MsT0FBWCxDQUFtQixNQUFuQixFQUEyQixHQUEzQixDQUFQO0FBQ0Q7O0FBRUQsT0FBTyxTQUFTQyxjQUFULENBQXdCRixVQUF4QixFQUFnRTtFQUNyRSxnQkFBTyxzQkFBc0JHLElBQXRCLENBQTJCSCxVQUEzQixDQUFQLDBDQUFPLE1BQXlDLENBQXpDLENBQVA7QUFDRDs7QUFFRCxPQUFPLFNBQVNJLG1CQUFULENBQTZCSixVQUE3QixFQUFxRTtFQUMxRSxpQkFBTyx5QkFBeUJHLElBQXpCLENBQThCSCxVQUE5QixDQUFQLDJDQUFPLE9BQTRDLENBQTVDLENBQVA7QUFDRDs7QUFFRCxPQUFPLFNBQVNLLGtCQUFULENBQTRCTCxVQUE1QixFQUFvRTtFQUN6RSxpQkFBTyx5QkFBeUJHLElBQXpCLENBQThCSCxVQUE5QixDQUFQLDJDQUFPLE9BQTRDLENBQTVDLENB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