1
0
Fork 0
digital-art-composition-book/.obsidian/plugins/obsidian-sort-and-permute-lines/main.js

393 lines
80 KiB
JavaScript
Raw Normal View History

2024-09-14 15:25:13 +00:00
'use strict';
var obsidian = require('obsidian');
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
function __generator(thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
}
/** @deprecated */
function __spreadArrays() {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
}
var checkboxRegex = /^(\s*)- \[[^ ]\]/gi;
var MyPlugin = /** @class */ (function (_super) {
__extends(MyPlugin, _super);
function MyPlugin() {
return _super !== null && _super.apply(this, arguments) || this;
}
MyPlugin.prototype.onload = function () {
return __awaiter(this, void 0, void 0, function () {
var compare, comp;
var _this = this;
return __generator(this, function (_a) {
console.log('loading ' + this.manifest.name);
compare = new Intl.Collator(navigator.language, {
usage: 'sort',
sensitivity: 'base',
numeric: true,
ignorePunctuation: true,
}).compare;
this.compare = compare;
this.addCommand({
id: 'sort-alphabetically-with-checkboxes',
name: 'Sort alphabetically with checkboxes',
callback: (function () { return _this.sortAlphabetically(false, false); }),
});
this.addCommand({
id: 'sort-list-alphabetically-with-checkboxes',
name: 'Sort current list alphabetically with checkboxes',
callback: (function () { return _this.sortAlphabetically(true, false); }),
});
this.addCommand({
id: 'sort-alphabetically',
name: 'Sort alphabetically',
callback: (function () { return _this.sortAlphabetically(false, true); }),
});
this.addCommand({
id: 'sort-list-alphabetically',
name: 'Sort current list alphabetically',
callback: (function () { return _this.sortAlphabetically(true, true); }),
});
this.addCommand({
id: 'sort-checkboxes',
name: 'Sort current list by checkboxes',
callback: function () { return _this.sortListRecursively(true, function (a, b) {
if (checkboxRegex.test(a.title.source) && !checkboxRegex.test(b.title.source))
return 1;
if (!checkboxRegex.test(a.title.source) && checkboxRegex.test(b.title.source))
return -1;
return 0;
}); },
});
this.addCommand({
id: 'sort-length',
name: 'Sort by length of line',
callback: (function () { return _this.sortLengthOfLine(); }),
});
this.addCommand({
id: 'sort-headings',
name: 'Sort headings',
callback: (function () { return _this.sortHeadings(); }),
});
this.addCommand({
id: 'permute-reverse',
name: 'Reverse lines',
callback: (function () { return _this.permuteReverse(); }),
});
this.addCommand({
id: 'permute-shuffle',
name: 'Shuffle lines',
callback: (function () { return _this.permuteShuffle(); }),
});
comp = function (a, b) { return _this.compare(a.title.formatted.trim(), b.title.formatted.trim()); };
this.addCommand({
id: 'sort-list-recursively',
name: 'Sort current list recursively',
callback: (function () { return _this.sortListRecursively(true, comp); }),
});
this.addCommand({
id: 'sort-list-recursively-with-checkboxes',
name: 'Sort current list recursively with checkboxes',
callback: (function () { return _this.sortListRecursively(false, comp); }),
});
return [2 /*return*/];
});
});
};
MyPlugin.prototype.onunload = function () {
console.log('unloading ' + this.manifest.name);
};
MyPlugin.prototype.sortAlphabetically = function (fromCurrentList, ignoreCheckboxes) {
var _this = this;
if (fromCurrentList === void 0) { fromCurrentList = false; }
if (ignoreCheckboxes === void 0) { ignoreCheckboxes = true; }
var lines = this.getLines(fromCurrentList, ignoreCheckboxes);
if (lines.length === 0)
return;
var sortFunc = function (a, b) { return _this.compare(a.formatted.trim(), b.formatted.trim()); };
lines.sort(sortFunc);
this.setLines(lines, fromCurrentList);
};
MyPlugin.prototype.sortListRecursively = function (ignoreCheckboxes, compareFn) {
var _this = this;
var inputLines = this.getLines(true, ignoreCheckboxes);
if (inputLines.length === 0 || inputLines.find(function (line) { return line.source.trim() == ""; }))
return;
var firstLineNumber = inputLines.first().lineNumber;
var lines = __spreadArrays(new Array(firstLineNumber).fill(undefined), inputLines);
var index = firstLineNumber;
var cache = this.app.metadataCache.getFileCache(this.app.workspace.getActiveFile());
var children = [];
while (index < lines.length) {
var newChild = this.getSortedListParts(lines, cache.listItems, index, compareFn);
children.push(newChild);
index = newChild.lastLine;
index++;
}
children.sort(compareFn);
var res = children.reduce(function (acc, cur) { return acc.concat(_this.listPartToList(cur)); }, []);
this.setLines(res, true);
};
MyPlugin.prototype.getLineCacheFromLine = function (line, linesCache) {
return linesCache.find(function (cacheItem) { return cacheItem.position.start.line === line; });
};
MyPlugin.prototype.getSortedListParts = function (lines, linesCache, index, compareFn) {
var _a, _b, _c, _d, _e;
var children = [];
var startListCache = this.getLineCacheFromLine(index, linesCache);
var title = lines[index];
while (startListCache.parent < ((_a = this.getLineCacheFromLine(index + 1, linesCache)) === null || _a === void 0 ? void 0 : _a.parent) || (startListCache.parent < 0 && ((_b = this.getLineCacheFromLine(index + 1, linesCache)) === null || _b === void 0 ? void 0 : _b.parent) >= 0)) {
index++;
var newChild = this.getSortedListParts(lines, linesCache, index, compareFn);
index = (_c = newChild.lastLine) !== null && _c !== void 0 ? _c : index;
children.push(newChild);
}
var lastLine = (_e = (_d = children.last()) === null || _d === void 0 ? void 0 : _d.lastLine) !== null && _e !== void 0 ? _e : index;
children.sort(compareFn);
return {
children: children,
title: title,
lastLine: lastLine,
};
};
MyPlugin.prototype.listPartToList = function (list) {
var _this = this;
return list.children.reduce(function (acc, cur) { return acc.concat(_this.listPartToList(cur)); }, [list.title]);
};
MyPlugin.prototype.sortHeadings = function () {
var lines = this.getLines();
var res = this.getSortedHeadings(lines, 0, { headingLevel: 0, formatted: "", source: "", lineNumber: -1 });
this.setLines(this.headingsToString(res).slice(1));
};
MyPlugin.prototype.headingsToString = function (heading) {
var _this = this;
var list = __spreadArrays([
heading.title
], heading.lines);
heading.headings.forEach(function (e) { return list.push.apply(list, _this.headingsToString(e)); });
return list;
};
MyPlugin.prototype.getSortedHeadings = function (lines, from, heading) {
var _this = this;
var headings = [];
var contentLines = [];
var currentIndex = from;
while (currentIndex < lines.length) {
var current = lines[currentIndex];
if (current.headingLevel <= heading.headingLevel) {
break;
}
if (current.headingLevel) {
headings.push(this.getSortedHeadings(lines, currentIndex + 1, current));
currentIndex = headings.last().to;
}
else {
contentLines.push(current);
}
currentIndex++;
}
return {
lines: contentLines,
to: headings.length > 0 ? headings.last().to : (currentIndex - 1),
headings: headings.sort(function (a, b) {
//First sort by heading level then alphabetically
var res = a.title.headingLevel - b.title.headingLevel;
if (res == 0) {
return _this.compare(a.title.formatted.trim(), b.title.formatted.trim());
}
else {
return res;
}
}),
title: heading,
};
};
MyPlugin.prototype.sortLengthOfLine = function () {
var lines = this.getLines();
if (lines.length === 0)
return;
lines.sort(function (a, b) { return a.formatted.length - b.formatted.length; });
this.setLines(lines);
};
MyPlugin.prototype.permuteReverse = function () {
var lines = this.getLines();
if (lines.length === 0)
return;
lines.reverse();
this.setLines(lines);
};
MyPlugin.prototype.permuteShuffle = function () {
var lines = this.getLines();
if (lines.length === 0)
return;
lines.shuffle();
this.setLines(lines);
};
MyPlugin.prototype.getLines = function (fromCurrentList, ignoreCheckboxes) {
var _a, _b;
if (fromCurrentList === void 0) { fromCurrentList = false; }
if (ignoreCheckboxes === void 0) { ignoreCheckboxes = true; }
var view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
if (!view)
return;
var editor = view.editor;
var file = view.file;
var lines = editor.getValue().split("\n");
var cache = this.app.metadataCache.getFileCache(file);
var _c = this.getPosition(view, fromCurrentList), start = _c.start, end = _c.end;
var headings = cache.headings;
var links = __spreadArrays((_a = cache === null || cache === void 0 ? void 0 : cache.links) !== null && _a !== void 0 ? _a : [], (_b = cache === null || cache === void 0 ? void 0 : cache.embeds) !== null && _b !== void 0 ? _b : []);
var myLines = lines.map(function (line, index) {
var myLine = { source: line, formatted: line, headingLevel: undefined, lineNumber: index };
links.forEach(function (e) {
if (e.position.start.line != index)
return;
var start = e.position.start;
var end = e.position.end;
myLine.formatted = myLine.formatted.replace(line.substring(start.col, end.col), e.displayText);
});
// Regex of cehckbox styles
if (ignoreCheckboxes) {
myLine.formatted = myLine.formatted.replace(checkboxRegex, "$1");
}
else {
// Just a little bit dirty...
myLine.formatted = myLine.formatted.replace(checkboxRegex, "$1ZZZZZZZZZZZZZZZZZZZZZZZZZ");
}
return myLine;
});
headings === null || headings === void 0 ? void 0 : headings.map(function (heading) { return myLines[heading.position.start.line].headingLevel = heading.level; });
if (start != end) {
return myLines.slice(start, end + 1);
}
else {
return myLines;
}
};
MyPlugin.prototype.setLines = function (lines, fromCurrentList) {
if (fromCurrentList === void 0) { fromCurrentList = false; }
var view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
var res = this.getPosition(view, fromCurrentList);
var editor = view.editor;
if (res.start != res.end) {
editor.replaceRange(lines.map(function (e) { return e.source; }).join("\n"), { line: res.start, ch: 0 }, { line: res.end, ch: res.endLineLength });
}
else {
editor.setValue(lines.map(function (e) { return e.source; }).join("\n"));
}
};
MyPlugin.prototype.getPosition = function (view, fromCurrentList) {
var _a, _b, _c;
if (fromCurrentList === void 0) { fromCurrentList = false; }
var cache = this.app.metadataCache.getFileCache(view.file);
var editor = view.editor;
var cursorStart = editor.getCursor("from").line;
var cursorEnd = editor.getCursor("to").line;
if (fromCurrentList) {
var list = cache.sections.find(function (e) {
return e.position.start.line <= cursorStart && e.position.end.line >= cursorEnd;
});
if (list) {
cursorStart = list.position.start.line;
cursorEnd = list.position.end.line;
}
}
var curserEndLineLength = editor.getLine(cursorEnd).length;
var frontStart = ((_c = (_b = (_a = cache.frontmatter) === null || _a === void 0 ? void 0 : _a.position) === null || _b === void 0 ? void 0 : _b.end) === null || _c === void 0 ? void 0 : _c.line) + 1;
if (isNaN(frontStart)) {
frontStart = 0;
}
var frontEnd = editor.lastLine();
var frontEndLineLength = editor.getLine(frontEnd).length;
if (cursorStart != cursorEnd) {
return {
start: cursorStart,
end: cursorEnd,
endLineLength: curserEndLineLength,
};
}
else {
return {
start: frontStart,
end: frontEnd,
endLineLength: frontEndLineLength,
};
}
};
return MyPlugin;
}(obsidian.Plugin));
module.exports = MyPlugin;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsIm1haW4udHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi5cclxuXHJcblBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZC9vciBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmUgZm9yIGFueVxyXG5wdXJwb3NlIHdpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQuXHJcblxyXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiIEFORCBUSEUgQVVUSE9SIERJU0NMQUlNUyBBTEwgV0FSUkFOVElFUyBXSVRIXHJcblJFR0FSRCBUTyBUSElTIFNPRlRXQVJFIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWVxyXG5BTkQgRklUTkVTUy4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBESVJFQ1QsXHJcbklORElSRUNULCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTVxyXG5MT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUlxyXG5PVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SXHJcblBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlICovXHJcblxyXG52YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcclxuICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XHJcbiAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcclxuICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXh0ZW5kcyhkLCBiKSB7XHJcbiAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxyXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcclxuICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcclxufVxyXG5cclxuZXhwb3J0IHZhciBfX2Fzc2lnbiA9IGZ1bmN0aW9uKCkge1xyXG4gICAgX19hc3NpZ24gPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uIF9fYXNzaWduKHQpIHtcclxuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcclxuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcclxuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKSB0W3BdID0gc1twXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHQ7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gX19hc3NpZ24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVzdChzLCBlKSB7XHJcbiAgICB2YXIgdCA9IHt9O1xyXG4gICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApICYmIGUuaW5kZXhPZihwKSA8IDApXHJcbiAgICAgICAgdFtwXSA9IHNbcF07XHJcbiAgICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSBcImZ1bmN0aW9uXCIpXHJcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIHAgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHMpOyBpIDwgcC5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBpZiAoZS5pbmRleE9mKHBbaV0pIDwgMCAmJiBPYmplY3QucHJvdG90eXBlLnByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwocywgcFtpXSkpXHJcbiAgICAgICAgICAgICAgICB0W3BbaV1dID0gc1twW2ldXTtcclxuICAgICAgICB9XHJcbiAgICByZXR1cm4gdDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcclxuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xyXG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA