5656 lines
737 KiB
JavaScript
Raw Permalink Normal View History

2023-06-29 11:55:02 +08: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.
***************************************************************************** */
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}
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());
});
}
const regEmoji = new RegExp(/[\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF]|[\uFE0E-\uFE0F]/, "g");
function allAlphabets(text) {
return Boolean(text.match(/^[a-zA-Z0-9_-]+$/));
}
function excludeEmoji(text) {
return text.replace(regEmoji, "");
}
function lowerIncludes(one, other) {
return one.toLowerCase().includes(other.toLowerCase());
}
function lowerStartsWith(a, b) {
return a.toLowerCase().startsWith(b.toLowerCase());
}
function capitalizeFirstLetter(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
function* splitRaw(text, regexp) {
let previousIndex = 0;
for (let r of text.matchAll(regexp)) {
if (previousIndex !== r.index) {
yield text.slice(previousIndex, r.index);
}
yield text[r.index];
previousIndex = r.index + 1;
}
if (previousIndex !== text.length) {
yield text.slice(previousIndex, text.length);
}
}
function pickTokens(content, trimPattern) {
return content.split(trimPattern).filter((x) => x !== "");
}
const TRIM_CHAR_PATTERN = /[\n\t\[\]$/:?!=()<>"'.,|;*~ `]/g;
class DefaultTokenizer {
tokenize(content, raw) {
return raw
? Array.from(splitRaw(content, this.getTrimPattern())).filter((x) => x !== " ")
: pickTokens(content, this.getTrimPattern());
}
recursiveTokenize(content) {
const trimIndexes = Array.from(content.matchAll(this.getTrimPattern()))
.sort((a, b) => a.index - b.index)
.map((x) => x.index);
return [
{ word: content, offset: 0 },
...trimIndexes.map((i) => ({
word: content.slice(i + 1),
offset: i + 1,
})),
];
}
getTrimPattern() {
return TRIM_CHAR_PATTERN;
}
shouldIgnore(str) {
return false;
}
}
const ARABIC_TRIM_CHAR_PATTERN = /[\n\t\[\]$/:?!=()<>"'.,|;*~ `،؛]/g;
class ArabicTokenizer extends DefaultTokenizer {
getTrimPattern() {
return ARABIC_TRIM_CHAR_PATTERN;
}
}
// @ts-nocheck
// Because this code is originally javascript code.
// noinspection FunctionTooLongJS,FunctionWithMultipleLoopsJS,EqualityComparisonWithCoercionJS,PointlessBooleanExpressionJS,JSDeclarationsAtScopeStart
// TinySegmenter 0.1 -- Super compact Japanese tokenizer in Javascript
// (c) 2008 Taku Kudo <taku@chasen.org>
// TinySegmenter is freely distributable under the terms of a new BSD licence.
// For details, see http://chasen.org/~taku/software/TinySegmenter/LICENCE.txt
function TinySegmenter() {
var patterns = {
"[一二三四五六七八九十百千万億兆]": "M",
"[一-龠々〆ヵヶ]": "H",
"[ぁ-ん]": "I",
"[ァ-ヴーア-ン゙ー]": "K",
"[a-zA-Z--]": "A",
"[0-9-]": "N",
};
this.chartype_ = [];
for (var i in patterns) {
var regexp = new RegExp();
regexp.compile(i);
this.chartype_.push([regexp, patterns[i]]);
}
this.BIAS__ = -332;
this.BC1__ = { HH: 6, II: 2461, KH: 406, OH: -1378 };
this.BC2__ = {
AA: -3267,
AI: 2744,
AN: -878,
HH: -4070,
HM: -1711,
HN: 4012,
HO: 3761,
IA: 1327,
IH: -1184,
II: -1332,
IK: 1721,
IO: 5492,
KI: 3831,
KK: -8741,
MH: -3132,
MK: 3334,
OO: -2920,
};
this.BC3__ = {
HH: 996,
HI: 626,
HK: -721,
HN: -1307,
HO: -836,
IH: -301,
KK: 2762,
MK: 1079,
MM: 4034,
OA: -1652,
OH: 266,
};
this.BP1__ = { BB: 295, OB: 304, OO: -125, UB: 352 };
this.BP2__ = { BO: 60, OO: -1762 };
this.BQ1__ = {
BHH: 1150,
BHM: 1521,
BII: -1158,
BIM: 886,
BMH: 1208,
BNH: 449,
BOH: -91,
BOO: -2597,
OHI: 451,
OIH: -296,
OKA: 1851,
OKH: -1020,
OKK: 904,
OOO: 2965,
};
this.BQ2__ = {
BHH: 118,
BHI: -1159,
BHM: 466,
BIH: -919,
BKK: -1720,
BKO: 864,
OHH: -1139,
OHM: -181,
OIH: 153,
UHI: -1146,
};
this.BQ3__ = {
BHH: -792,
BHI: 2664,
BII: -299,
BKI: 419,
BMH: 937,
BMM: 8335,
BNN: 998,
BOH: 775,
OHH: 2174,
OHM: 439,
OII: 280,
OKH: 1798,
OKI: -793,
OKO: -2242,
OMH: -2402,
OOO: 11699,
};
this.BQ4__ = {
BHH: -3895,
BIH: 3761,
BII: -4654,
BIK: 1348,
BKK: -1806,
BMI: -3385,
BOO: -12396,
OAH: 926,
OHH: 266,
OHK: -2036,
ONN: -973,
};
this.BW1__ = {
",と": 660,
",同": 727,
B1あ: 1404,
B1同: 542,
"、と": 660,
"、同": 727,
"」と": 1682,
あっ: 1505,
いう: 1743,
いっ: -2055,
いる: 672,
うし: -4817,
うん: 665,
から: 3472,
がら: 600,
こう: -790,
こと: 2083,
こん: -1262,
さら: -4143,
さん: 4573,
した: 2641,
して: 1104,
すで: -3399,
そこ: 1977,
それ: -871,
たち: 1122,
ため: 601,
った: 3463,
つい: -802,
てい: 805,
てき: 1249,
でき: 1127,
です: 3445,
では: 844,
とい: -4915,
とみ: 1922,
どこ: 3887,
ない: 5713,
なっ: 3015,
など: 7379,
なん: -1113,
にし: 2468,
には: 1498,
にも: 1671,
に対: -912,
の一: -501,
の中: 741,
ませ: 2448,
まで: 1711,
まま: 2600,
まる: -2155,
やむ: -1947,
よっ: -2565,
れた: 2369,
れで: -913,
をし: 1860,
を見: 731,
亡く: -1886,
京都: 2558,
取り: -2784,
大き: -2604,
大阪: 1497,
平方: -2314,
引き: -1336,
日本: -195,
本当: -2423,
毎日: -2113,
目指: -724,
B1あ: 1404,
B1同: 542,
"」と": 1682,
};
this.BW2__ = {
"..": -11822,
11: -669,
"――": -5730,
"": -13175,
いう: -1609,
うか: 2490,
かし: -1350,
かも: -602,
から: -7194,
かれ: 4612,
がい: 853,
がら: -3198,
きた: 1941,
くな: -1597,
こと: -8392,
この: -4193,
させ: 4533,
され: 13168,
さん: -3977,
しい: -1819,
しか: -545,
した: 5078,
して: 972,
しな: 939,
その: -3744,
たい: -1253,
たた: -662,
ただ: -3857,
たち: -786,
たと: 1224,
たは: -939,
った: 4589,
って: 1647,
っと: -2094,
てい: 6144,
てき: 3640,
てく: 2551,
ては: -3110,
ても: -3065,
でい: 2666,
でき: -1528,
でし: -3828,
です: -4761,
でも: -4203,
とい: 1890,
とこ: -1746,
とと: -2279,
との: 720,
とみ: 5168,
とも: -3941,
ない: -2488,
なが: -1313,
など: -6509,
なの: 2614,
なん: 3099,
にお: -1615,
にし: 2748,
にな: 2454,
によ: -7236,
に対: -14943,
に従: -4688,
に関: -11388,
のか: 2093,
ので: -7059,
のに: -6041,
のの: -6125,
はい: 1073,
はが: -1033,
はず: -2532,
ばれ: 1813,
まし: -1316,
まで: -6621,
まれ: 5409,
めて: -3153,
もい: 2230,
もの: -10713,
らか: -944,
らし: -1611,
らに: -1897,
りし: 651,
りま: 1620,
れた: 4270,
れて: 849,
れば: 4114,
ろう: 6067,
われ: 7901,
を通: -11877,
んだ: 728,
んな: -4115,
一人: 602,
一方: -1375,
一日: 970,
一部: -1051,
上が: -4479,
会社: -1116,
出て: 2163,
分の: -7758,
同党: 970,
同日: -913,
大阪: -2471,
委員: -1250,
少な: -1050,
年度: -8669,
年間: -1626,
府県: -2363,
手権: -1982,
新聞: -4066,
日新: -722,
日本: -7068,
日米: 3372,
曜日: -601,
朝鮮: -2355,
本人: -2697,
東京: -1543,
然と: -1384,
社会: -1276,
立て: -990,
第に: -1612,
米国: -4268,
"": -669,
};
this.BW3__ = {
あた: -2194,
あり: 719,
ある: 3846,
"い.": -1185,
"い。": -1185,
いい: 5308,
いえ: 2079,
いく: 3029,
いた: 2056,
いっ: 1883,
いる: 5600,
いわ: 1527,
うち: 1117,
うと: 4798,
えと: 1454,
"か.": 2857,
"か。": 2857,
かけ: -743,
かっ: -4098,
かに: -669,
から: 6520,
かり: -2670,
"が,": 1816,
"が、": 1816,
がき: -4855,
がけ: -1127,
がっ: -913,
がら: -4977,
がり: -2064,
きた: 1645,
けど: 1374,
こと: 7397,
この: 1542,
ころ: -2757,
さい: -714,
さを: 976,
"し,": 1557,
"し、": 1557,
しい: -3714,
した: 3562,
して: 1449,
しな: 2608,
しま: 1200,
"す.": -1310,
"す。": -1310,
する: 6521,
"ず,": 3426,
"ず、": 3426,
ずに: 841,
そう: 428,
"た.": 8875,
"た。": 8875,
たい: -594,
たの: 812,
たり: -1183,
たる: -853,
"だ.": 4098,
"だ。": 4098,
だっ: 1004,
った: -4748,
って: 300,
てい: 6240,
てお: 855,
ても: 302,
です: 1437,
でに: -1482,
では: 2295,
とう: -1387,
とし: 2266,
との: 541,
とも: -3543,
どう: 4664,
ない: 1796,
なく: -903,
など: 2135,
"に,": -1021,
"に、": -1021,
にし: 1771,
にな: 1906,
には: 2644,
"の,": -724,
"の、": -724,
の子: -1000,
"は,": 1337,
"は、": 1337,
べき: 2181,
まし: 1113,
ます: 6943,
まっ: -1549,
まで: 6154,
まれ: -793,
らし: 1479,
られ: 6820,
るる: 3818,
"れ,": 854,
"れ、": 854,
れた: 1850,
れて: 1375,
れば: -3246,
れる: 1091,
われ: -605,
んだ: 606,
んで: 798,
カ月: 990,
会議: 860,
入り: 1232,
大会: 2217,
始め: 1681,
: 965,
新聞: -5055,
"日,": 974,
"日、": 974,
社会: 2024,
カ月: 990,
};
this.TC1__ = {
AAA: 1093,
HHH: 1029,
HHM: 580,
HII: 998,
HOH: -390,
HOM: -331,
IHI: 1169,
IOH: -142,
IOI: -1015,
IOM: 467,
MMH: 187,
OOI: -1832,
};
this.TC2__ = {
HHO: 2088,
HII: -1023,
HMM: -1154,
IHI: -1965,
KKH: 703,
OII: -2649,
};
this.TC3__ = {
AAA: -294,
HHH: 346,
HHI: -341,
HII: -1088,
HIK: 731,
HOH: -1486,
IHH: 128,
IHI: -3041,
IHO: -1935,
IIH: -825,
IIM: -1035,
IOI: -542,
KHH: -1216,
KKA: 491,
KKH: -1217,
KOK: -1009,
MHH: -2694,
MHM: -457,
MHO: 123,
MMH: -471,
NNH: -1689,
NNO: 662,
OHO: -3393,
};
this.TC4__ = {
HHH: -203,
HHI: 1344,
HHK: 365,
HHM: -122,
HHN: 182,
HHO: 669,
HIH: 804,
HII: 679,
HOH: 446,
IHH: 695,
IHO: -2324,
IIH: 321,
III: 1497,
IIO: 656,
IOO: 54,
KAK: 4845,
KKA: 3386,
KKK: 3065,
MHH: -405,
MHI: 201,
MMH: -241,
MMM: 661,
MOM: 841,
};
this.TQ1__ = {
BHHH: -227,
BHHI: 316,
BHIH: -132,
BIHH: 60,
BIII: 1595,
BNHH: -744,
BOHH: 225,
BOOO: -908,
OAKK: 482,
OHHH: 281,
OHIH: 249,
OIHI: 200,
OIIH: -68,
};
this.TQ2__ = { BIHH: -1401, BIII: -1033, BKAK: -543, BOOO: -5591 };
this.TQ3__ = {
BHHH: 478,
BHHM: -1073,
BHIH: 222,
BHII: -504,
BIIH: -116,
BIII: -105,
BMHI: -863,
BMHM: -464,
BOMH: 620,
OHHH: 346,
OHHI: 1729,
OHII: 997,
OHMH: 481,
OIHH: 623,
OIIH: 1344,
OKAK: 2792,
OKHH: 587,
OKKA: 679,
OOHH: 110,
OOII: -685,
};
this.TQ4__ = {
BHHH: -721,
BHHM: -3604,
BHII: -966,
BIIH: -607,
BIII: -2181,
OAAA: -2763,
OAKK: 180,
OHHH: -294,
OHHI: 2446,
OHHO: 480,
OHIH: -1573,
OIHH: 1935,
OIHI: -493,
OIIH: 626,
OIII: -4007,
OKAK: -8156,
};
this.TW1__ = { につい: -4681, 東京都: 2026 };
this.TW2__ = {
ある程: -2049,
いった: -1256,
ころが: -2434,
しょう: 3873,
その後: -4430,
だって: -1049,
ていた: 1833,
として: -4657,
ともに: -4517,
もので: 1882,
一気に: -792,
初めて: -1512,
同時に: -8097,
大きな: -1255,
対して: -2721,
社会党: -3216,
};
this.TW3__ = {
いただ: -1734,
してい: 1314,
として: -4314,
につい: -5483,
にとっ: -5989,
に当た: -6247,
"ので,": -727,
"ので、": -727,
のもの: -600,
れから: -3752,
十二月: -2287,
};
this.TW4__ = {
"いう.": 8576,
"いう。": 8576,
からな: -2348,
してい: 2958,
"たが,": 1516,
"たが、": 1516,
ている: 1538,
という: 1349,
ました: 5543,
ません: 1097,
ようと: -4258,
よると: 5865,
};
this.UC1__ = { A: 484, K: 93, M: 645, O: -505 };
this.UC2__ = { A: 819, H: 1059, I: 409, M: 3987, N: 5775, O: 646 };
this.UC3__ = { A: -1370, I: 2311 };
this.UC4__ = {
A: -2643,
H: 1809,
I: -1032,
K: -3450,
M: 3565,
N: 3876,
O: 6646,
};
this.UC5__ = { H: 313, I: -1238, K: -799, M: 539, O: -831 };
this.UC6__ = { H: -506, I: -253, K: 87, M: 247, O: -387 };
this.UP1__ = { O: -214 };
this.UP2__ = { B: 69, O: 935 };
this.UP3__ = { B: 189 };
this.UQ1__ = {
BH: 21,
BI: -12,
BK: -99,
BN: 142,
BO: -56,
OH: -95,
OI: 477,
OK: 410,
OO: -2422,
};
this.UQ2__ = { BH: 216, BI: 113, OK: 1759 };
this.UQ3__ = {
BA: -479,
BH: 42,
BI: 1913,
BK: -7198,
BM: 3160,
BN: 6427,
BO: 14761,
OI: -827,
ON: -3212,
};
this.UW1__ = {
",": 156,
"、": 156,
"「": -463,
: -941,
: -127,
: -553,
: 121,
: 505,
: -201,
: -547,
: -123,
: -789,
: -185,
: -847,
: -466,
: -470,
: 182,
: -292,
: 208,
: 169,
: -446,
: -137,
"・": -135,
: -402,
: -268,
: -912,
: 871,
: -460,
: 561,
: 729,
: -411,
: -141,
: 361,
: -408,
: -386,
: -718,
"「": -463,
"・": -135,
};
this.UW2__ = {
",": -829,
"、": -829,
: 892,
"「": -645,
"」": 3145,
: -538,
: 505,
: 134,
: -502,
: 1454,
: -856,
: -412,
: 1141,
: 878,
: 540,
: 1529,
: -675,
: 300,
: -1011,
: 188,
: 1837,
: -949,
: -291,
: -268,
: -981,
: 1273,
: 1063,
: -1764,
: 130,
: -409,
: -1273,
: 1261,
: 600,
: -1263,
: -402,
: 1639,
: -579,
: -694,
: 571,
: -2516,
: 2095,
: -587,
: 306,
: 568,
: 831,
: -758,
: -2150,
: -302,
: -968,
: -861,
: 492,
: -123,
: 978,
: 362,
: 548,
: -3025,
: -1566,
: -3414,
: -422,
: -1769,
: -865,
: -483,
: -1519,
: 760,
: 1023,
: -2009,
: -813,
: -1060,
: 1067,
: -1519,
: -1033,
: 1522,
: -1355,
: -1682,
: -1815,
: -1462,
: -630,
: -1843,
: -1650,
: -931,
: -665,
: -2378,
: -180,
: -1740,
: 752,
: 529,
: -1584,
: -242,
: -1165,
: -763,
: 810,
: 509,
: -1353,
: 838,
西: -744,
: -3874,
調: 1010,
: 1198,
: 3041,
: 1758,
: -1257,
"「": -645,
"」": 3145,
: 831,
: -587,
: 306,
: 568,
};
this.UW3__ = {
",": 4889,
1: -800,
"": -1723,
"、": 4889,
: -2311,
: 5827,
"」": 2670,
"〓": -3573,
: -2696,
: 1006,
: 2342,
: 1983,
: -4864,
: -1163,
: 3271,
: 1004,
: 388,
: 401,
: -3552,
: -3116,
: -1058,
: -395,
: 584,
: 3685,
: -5228,
: 842,
: -521,
: -1444,
: -1081,
: 6167,
: 2318,
: 1691,
: -899,
: -2788,
: 2745,
: 4056,
: 4555,
: -2171,
: -1798,
: 1199,
: -5516,
: -4384,
: -120,
: 1205,
: 2323,
: -788,
: -202,
: 727,
: 649,
: 5905,
: 2773,
: -1207,
: 6620,
: -518,
: 551,
: 1319,
: 874,
: -1350,
: 521,
: 1109,
: 1591,
: 2201,
: 278,
"・": -3794,
: -1619,
: -1759,
: -2087,
: 3815,
: 653,
: -758,
: -1193,
: 974,
: 2742,
: 792,
: 1889,
: -1368,
: 811,
: 4265,
: -361,
: -2439,
: 4858,
: 3593,
: 1574,
: -3030,
: 755,
: -1880,
: 5807,
: 3095,
: 457,
: 2475,
: 1129,
: 2286,
: 4437,
: 365,
: -949,
: -1872,
: 1327,
: -1038,
: 4646,
: -2309,
: -783,
: -1006,
: 483,
: 1233,
: 3588,
: -241,
: 3906,
: -837,
: 4513,
: 642,
: 1389,
: 1219,
: -241,
: 2016,
: -1356,
: -423,
: -1008,
: 1078,
: -513,
: -3102,
: 1155,
: 3197,
: -1804,
: 2416,
: -1030,
: 1605,
: 1452,
: -2352,
: -3885,
: 1905,
: -1291,
: 1822,
: -488,
: -3973,
: -2013,
: -1479,
: 3222,
: -1489,
: 1764,
: 2099,
: 5792,
: -661,
: -1248,
: -951,
: -937,
: 4125,
: 360,
: 3094,
: 364,
: -805,
: 5156,
: 2438,
: 484,
: 2613,
: -1694,
: -1073,
: 1868,
: -495,
: 979,
: 461,
: -3850,
: -273,
: 914,
: 1215,
: 7313,
: -1835,
: 792,
: 6293,
: -1528,
: 4231,
: 401,
: -960,
: 1201,
: 7767,
: 3066,
: 3663,
: 1384,
: -4229,
: 1163,
: 1255,
: 6457,
: 725,
: -2869,
: 785,
: 1044,
調: -562,
: -733,
: 1777,
: 1835,
: 1375,
: -1504,
: -1136,
: -681,
: 1026,
: 4404,
: 1200,
: 2163,
: 421,
: -1432,
: 1302,
: -1282,
: 2009,
: -1045,
: 2066,
: 1620,
"": -800,
"」": 2670,
"・": -3794,
: -1350,
: 551,
グ: 1319,
: 874,
: 521,
: 1109,
: 1591,
: 2201,
: 278,
};
this.UW4__ = {
",": 3930,
".": 3508,
"―": -4841,
"、": 3930,
"。": 3508,
: 4999,
"「": 1895,
"」": 3798,
"〓": -5156,
: 4752,
: -3435,
: -640,
: -2514,
: 2405,
: 530,
: 6006,
: -4482,
: -3821,
: -3788,
: -4376,
: -4734,
: 2255,
: 1979,
: 2864,
: -843,
: -2506,
: -731,
: 1251,
: 181,
: 4091,
: 5034,
: 5408,
: -3654,
: -5882,
: -1659,
: 3994,
: 7410,
: 4547,
: 5433,
: 6499,
: 1853,
: 1413,
: 7396,
: 8578,
: 1940,
: 4249,
: -4134,
: 1345,
: 6665,
: -744,
: 1464,
: 1051,
: -2082,
: -882,
: -5046,
: 4169,
: -2666,
: 2795,
: -1544,
: 3351,
: -2922,
: -9726,
: -14896,
: -2613,
: -4570,
: -1783,
: 13150,
: -2352,
: 2145,
: 1789,
: 1287,
: -724,
: -403,
: -1635,
: -881,
: -541,
: -856,
: -3637,
"・": -4371,
: -11870,
: -2069,
: 2210,
: 782,
: -190,
: -1768,
: 1036,
: 544,
: 950,
: -1286,
: 530,
: 4292,
: 601,
: -2006,
: -1212,
: 584,
: 788,
: 1347,
: 1623,
: 3879,
: -302,
: -740,
: -2715,
: 776,
: 4517,
: 1013,
: 1555,
: -1834,
: -681,
: -910,
: -851,
: 1500,
: -619,
: -1200,
: 866,
: -1410,
: -2094,
: -1413,
: 1067,
: 571,
: -4802,
: -1397,
: -1057,
: -809,
: 1910,
: -1328,
: -1500,
: -2056,
: -2667,
: 2771,
: 374,
: -4556,
: 456,
: 553,
: 916,
: -1566,
: 856,
: 787,
: 2182,
: 704,
: 522,
: -856,
: 1798,
: 1829,
: 845,
: -9066,
: -485,
: -442,
: -360,
: -1043,
: 5388,
: -2716,
: -910,
: -939,
: -543,
: -735,
: 672,
: -1267,
: -1286,
: -1101,
: -2900,
: 1826,
: 2586,
: 922,
: -3485,
: 2997,
: -867,
: -2112,
: 788,
: 2937,
: 786,
: 2171,
: 1146,
: -1169,
: 940,
: -994,
: 749,
: 2145,
: -730,
: -852,
: -792,
: 792,
: -1184,
: -244,
: -1000,
: 730,
: -1481,
: 1158,
: -1433,
: -3370,
: 929,
: -1291,
: 2596,
: -4866,
: 1192,
: -1100,
: -2213,
: 357,
: -2344,
: -2297,
: -2604,
: -878,
: -1659,
: -792,
: -1984,
: 1749,
: 2120,
"「": 1895,
"」": 3798,
"・": -4371,
: -724,
: -11870,
: 2145,
: 1789,
: 1287,
: -403,
: -1635,
: -881,
: -541,
: -856,
: -3637,
};
this.UW5__ = {
",": 465,
".": -299,
1: -514,
E2: -32768,
"]": -2762,
"、": 465,
"。": -299,
"「": 363,
: 1655,
: 331,
: -503,
: 1199,
: 527,
: 647,
: -421,
: 1624,
: 1971,
: 312,
: -983,
: -1537,
: -1371,
: -852,
: -1186,
: 1093,
: 52,
: 921,
: -18,
: -850,
: -127,
: 1682,
: -787,
: -1224,
: -635,
: -578,
: 1001,
: 502,
: 865,
: 3350,
: 854,
: -208,
: 429,
: 504,
: 419,
: -1264,
: 327,
: 241,
: 451,
: -343,
: -871,
: 722,
: -1153,
: -654,
: 3519,
: -901,
: 848,
: 2104,
: -1296,
: -548,
: 1785,
: -1304,
: -2991,
: 921,
: 1763,
: 872,
: -814,
: 1618,
: -1682,
: 218,
: -4353,
: 932,
: 1356,
: -1508,
: -1347,
: 240,
: -3912,
: -3149,
: 1319,
: -1052,
: -4003,
: -997,
: -278,
: -813,
: 1955,
: -2233,
: 663,
: -1073,
: 1219,
: -1018,
: -368,
: 786,
: 1191,
: 2368,
: -689,
"": -514,
: -32768,
"「": 363,
: 241,
: 451,
: -343,
};
this.UW6__ = {
",": 227,
".": 808,
1: -270,
E1: 306,
"、": 227,
"。": 808,
: -307,
: 189,
: 241,
: -73,
: -121,
: -200,
: 1782,
: 383,
: -428,
: 573,
: -1014,
: 101,
: -105,
: -253,
: -149,
: -417,
: -236,
: -206,
: 187,
: -135,
: 195,
: -673,
: -496,
: -277,
: 201,
: -800,
: 624,
: 302,
: 1792,
: -1212,
: 798,
: -960,
: 887,
: -695,
: 535,
: -697,
: 753,
: -507,
: 974,
: -822,
: 1811,
: 463,
: 1082,
"": -270,
: 306,
: -673,
: -496,
};
return this;
}
TinySegmenter.prototype.ctype_ = function (str) {
for (var i in this.chartype_) {
if (str.match(this.chartype_[i][0])) {
return this.chartype_[i][1];
}
}
return "O";
};
TinySegmenter.prototype.ts_ = function (v) {
if (v) {
return v;
}
return 0;
};
TinySegmenter.prototype.segment = function (input) {
if (input == null || input == undefined || input == "") {
return [];
}
var result = [];
var seg = ["B3", "B2", "B1"];
var ctype = ["O", "O", "O"];
var o = input.split("");
for (i = 0; i < o.length; ++i) {
seg.push(o[i]);
ctype.push(this.ctype_(o[i]));
}
seg.push("E1");
seg.push("E2");
seg.push("E3");
ctype.push("O");
ctype.push("O");
ctype.push("O");
var word = seg[3];
var p1 = "U";
var p2 = "U";
var p3 = "U";
for (var i = 4; i < seg.length - 3; ++i) {
var score = this.BIAS__;
var w1 = seg[i - 3];
var w2 = seg[i - 2];
var w3 = seg[i - 1];
var w4 = seg[i];
var w5 = seg[i + 1];
var w6 = seg[i + 2];
var c1 = ctype[i - 3];
var c2 = ctype[i - 2];
var c3 = ctype[i - 1];
var c4 = ctype[i];
var c5 = ctype[i + 1];
var c6 = ctype[i + 2];
score += this.ts_(this.UP1__[p1]);
score += this.ts_(this.UP2__[p2]);
score += this.ts_(this.UP3__[p3]);
score += this.ts_(this.BP1__[p1 + p2]);
score += this.ts_(this.BP2__[p2 + p3]);
score += this.ts_(this.UW1__[w1]);
score += this.ts_(this.UW2__[w2]);
score += this.ts_(this.UW3__[w3]);
score += this.ts_(this.UW4__[w4]);
score += this.ts_(this.UW5__[w5]);
score += this.ts_(this.UW6__[w6]);
score += this.ts_(this.BW1__[w2 + w3]);
score += this.ts_(this.BW2__[w3 + w4]);
score += this.ts_(this.BW3__[w4 + w5]);
score += this.ts_(this.TW1__[w1 + w2 + w3]);
score += this.ts_(this.TW2__[w2 + w3 + w4]);
score += this.ts_(this.TW3__[w3 + w4 + w5]);
score += this.ts_(this.TW4__[w4 + w5 + w6]);
score += this.ts_(this.UC1__[c1]);
score += this.ts_(this.UC2__[c2]);
score += this.ts_(this.UC3__[c3]);
score += this.ts_(this.UC4__[c4]);
score += this.ts_(this.UC5__[c5]);
score += this.ts_(this.UC6__[c6]);
score += this.ts_(this.BC1__[c2 + c3]);
score += this.ts_(this.BC2__[c3 + c4]);
score += this.ts_(this.BC3__[c4 + c5]);
score += this.ts_(this.TC1__[c1 + c2 + c3]);
score += this.ts_(this.TC2__[c2 + c3 + c4]);
score += this.ts_(this.TC3__[c3 + c4 + c5]);
score += this.ts_(this.TC4__[c4 + c5 + c6]);
// score += this.ts_(this.TC5__[c4 + c5 + c6]);
score += this.ts_(this.UQ1__[p1 + c1]);
score += this.ts_(this.UQ2__[p2 + c2]);
score += this.ts_(this.UQ3__[p3 + c3]);
score += this.ts_(this.BQ1__[p2 + c2 + c3]);
score += this.ts_(this.BQ2__[p2 + c3 + c4]);
score += this.ts_(this.BQ3__[p3 + c2 + c3]);
score += this.ts_(this.BQ4__[p3 + c3 + c4]);
score += this.ts_(this.TQ1__[p2 + c1 + c2 + c3]);
score += this.ts_(this.TQ2__[p2 + c2 + c3 + c4]);
score += this.ts_(this.TQ3__[p3 + c1 + c2 + c3]);
score += this.ts_(this.TQ4__[p3 + c2 + c3 + c4]);
var p = "O";
if (score > 0) {
result.push(word);
word = "";
p = "B";
}
p1 = p2;
p2 = p3;
p3 = p;
word += seg[i];
}
result.push(word);
return result;
};
// @ts-ignore
const segmenter = new TinySegmenter();
function pickTokensAsJapanese(content, trimPattern) {
return content
.split(trimPattern)
.filter((x) => x !== "")
.flatMap((x) => segmenter.segment(x));
}
/**
* Japanese needs original logic.
*/
class JapaneseTokenizer {
tokenize(content, raw) {
return pickTokensAsJapanese(content, raw ? / /g : this.getTrimPattern());
}
recursiveTokenize(content) {
const tokens = segmenter
.segment(content)
// https://github.com/tadashi-aikawa/obsidian-various-complements-plugin/issues/77
.flatMap((x) => x === " " ? x : x.split(" ").map((t) => (t === "" ? " " : t)));
const ret = [];
for (let i = 0; i < tokens.length; i++) {
if (i === 0 ||
tokens[i].length !== 1 ||
!Boolean(tokens[i].match(this.getTrimPattern()))) {
ret.push({
word: tokens.slice(i).join(""),
offset: tokens.slice(0, i).join("").length,
});
}
}
return ret;
}
getTrimPattern() {
return TRIM_CHAR_PATTERN;
}
shouldIgnore(str) {
return Boolean(str.match(/^[ぁ-んa--Z。、ー ]*$/));
}
}
const ENGLISH_PATTERN = /[a-zA-Z0-9_\-\\]/;
class EnglishOnlyTokenizer extends DefaultTokenizer {
tokenize(content, raw) {
const tokenized = Array.from(this._tokenize(content)).filter((x) => x.word.match(ENGLISH_PATTERN));
return raw
? tokenized.map((x) => x.word)
: tokenized
.map((x) => x.word)
.filter((x) => !x.match(this.getTrimPattern()));
}
recursiveTokenize(content) {
const offsets = Array.from(this._tokenize(content))
.filter((x) => !x.word.match(this.getTrimPattern()))
.map((x) => x.offset);
return [
...offsets.map((i) => ({
word: content.slice(i),
offset: i,
})),
];
}
*_tokenize(content) {
let startIndex = 0;
let previousType = "none";
for (let i = 0; i < content.length; i++) {
if (content[i].match(super.getTrimPattern())) {
yield { word: content.slice(startIndex, i), offset: startIndex };
previousType = "trim";
startIndex = i;
continue;
}
if (content[i].match(ENGLISH_PATTERN)) {
if (previousType === "english" || previousType === "none") {
previousType = "english";
continue;
}
yield { word: content.slice(startIndex, i), offset: startIndex };
previousType = "english";
startIndex = i;
continue;
}
if (previousType === "others" || previousType === "none") {
previousType = "others";
continue;
}
yield { word: content.slice(startIndex, i), offset: startIndex };
previousType = "others";
startIndex = i;
}
yield {
word: content.slice(startIndex, content.length),
offset: startIndex,
};
}
}
function createTokenizer(strategy) {
switch (strategy.name) {
case "default":
return new DefaultTokenizer();
case "english-only":
return new EnglishOnlyTokenizer();
case "arabic":
return new ArabicTokenizer();
case "japanese":
return new JapaneseTokenizer();
default:
throw new Error(`Unexpected strategy name: ${strategy}`);
}
}
class TokenizeStrategy {
constructor(name, triggerThreshold) {
this.name = name;
this.triggerThreshold = triggerThreshold;
TokenizeStrategy._values.push(this);
}
static fromName(name) {
return TokenizeStrategy._values.find((x) => x.name === name);
}
static values() {
return TokenizeStrategy._values;
}
}
TokenizeStrategy._values = [];
TokenizeStrategy.DEFAULT = new TokenizeStrategy("default", 3);
TokenizeStrategy.ENGLISH_ONLY = new TokenizeStrategy("english-only", 3);
TokenizeStrategy.JAPANESE = new TokenizeStrategy("japanese", 2);
TokenizeStrategy.ARABIC = new TokenizeStrategy("arabic", 3);
class AppHelper {
constructor(app) {
this.unsafeApp = app;
}
equalsAsEditorPostion(one, other) {
return one.line === other.line && one.ch === other.ch;
}
getAliases(file) {
var _a, _b;
return ((_b = obsidian.parseFrontMatterAliases((_a = this.unsafeApp.metadataCache.getFileCache(file)) === null || _a === void 0 ? void 0 : _a.frontmatter)) !== null && _b !== void 0 ? _b : []);
}
getFrontMatter(file) {
var _a, _b, _c, _d;
const frontMatter = (_a = this.unsafeApp.metadataCache.getFileCache(file)) === null || _a === void 0 ? void 0 : _a.frontmatter;
if (!frontMatter) {
return undefined;
}
// remove #
const tags = (_c = (_b = obsidian.parseFrontMatterTags(frontMatter)) === null || _b === void 0 ? void 0 : _b.map((x) => x.slice(1))) !== null && _c !== void 0 ? _c : [];
const aliases = (_d = obsidian.parseFrontMatterAliases(frontMatter)) !== null && _d !== void 0 ? _d : [];
const rest = __rest(frontMatter, ["position"]);
return Object.assign(Object.assign({}, Object.fromEntries(Object.entries(rest).map(([k, _v]) => [
k,
obsidian.parseFrontMatterStringArray(frontMatter, k),
]))), { tags, tag: tags, aliases, alias: aliases });
}
getMarkdownViewInActiveLeaf() {
if (!this.unsafeApp.workspace.getActiveViewOfType(obsidian.MarkdownView)) {
return null;
}
return this.unsafeApp.workspace.activeLeaf.view;
}
getActiveFile() {
return this.unsafeApp.workspace.getActiveFile();
}
isActiveFile(file) {
var _a;
return ((_a = this.getActiveFile()) === null || _a === void 0 ? void 0 : _a.path) === file.path;
}
getPreviousFile() {
var _a;
const fName = (_a = this.unsafeApp.workspace.getLastOpenFiles()) === null || _a === void 0 ? void 0 : _a[1];
if (!fName) {
return null;
}
return this.getMarkdownFileByPath(fName);
}
getCurrentDirname() {
var _a, _b;
return (_b = (_a = this.getActiveFile()) === null || _a === void 0 ? void 0 : _a.parent.path) !== null && _b !== void 0 ? _b : null;
}
getCurrentEditor() {
var _a, _b;
return (_b = (_a = this.getMarkdownViewInActiveLeaf()) === null || _a === void 0 ? void 0 : _a.editor) !== null && _b !== void 0 ? _b : null;
}
getSelection() {
var _a;
return (_a = this.getCurrentEditor()) === null || _a === void 0 ? void 0 : _a.getSelection();
}
getCurrentOffset(editor) {
return editor.posToOffset(editor.getCursor());
}
getCurrentLine(editor) {
return editor.getLine(editor.getCursor().line);
}
getCurrentLineUntilCursor(editor) {
return this.getCurrentLine(editor).slice(0, editor.getCursor().ch);
}
searchPhantomLinks() {
return Object.entries(this.unsafeApp.metadataCache.unresolvedLinks).flatMap(([path, obj]) => Object.keys(obj).map((link) => ({ path, link })));
}
getMarkdownFileByPath(path) {
if (!path.endsWith(".md")) {
return null;
}
const abstractFile = this.unsafeApp.vault.getAbstractFileByPath(path);
if (!abstractFile) {
return null;
}
return abstractFile;
}
openMarkdownFile(file, newLeaf, offset = 0) {
var _a;
const leaf = this.unsafeApp.workspace.getLeaf(newLeaf);
leaf
.openFile(file, (_a = this.unsafeApp.workspace.activeLeaf) === null || _a === void 0 ? void 0 : _a.getViewState())
.then(() => {
this.unsafeApp.workspace.setActiveLeaf(leaf, true, true);
const viewOfType = this.unsafeApp.workspace.getActiveViewOfType(obsidian.MarkdownView);
if (viewOfType) {
const editor = viewOfType.editor;
const pos = editor.offsetToPos(offset);
editor.setCursor(pos);
editor.scrollIntoView({ from: pos, to: pos }, true);
}
});
}
getCurrentFrontMatter() {
const editor = this.getCurrentEditor();
if (!editor) {
return null;
}
if (!this.getActiveFile()) {
return null;
}
if (editor.getLine(0) !== "---") {
return null;
}
const endPosition = editor.getValue().indexOf("---", 3);
const currentOffset = this.getCurrentOffset(editor);
if (endPosition !== -1 && currentOffset >= endPosition) {
return null;
}
const keyLocations = Array.from(editor.getValue().matchAll(/.+:/g));
if (keyLocations.length === 0) {
return null;
}
const currentKeyLocation = keyLocations
.filter((x) => x.index < currentOffset)
.last();
if (!currentKeyLocation) {
return null;
}
return currentKeyLocation[0].split(":")[0];
}
/**
* Unsafe method
*/
isIMEOn() {
var _a, _b, _c;
if (!this.unsafeApp.workspace.getActiveViewOfType(obsidian.MarkdownView)) {
return false;
}
const markdownView = this.unsafeApp.workspace.activeLeaf
.view;
const cm5or6 = markdownView.editor.cm;
// cm6
if (((_a = cm5or6 === null || cm5or6 === void 0 ? void 0 : cm5or6.inputState) === null || _a === void 0 ? void 0 : _a.composing) > 0) {
return true;
}
// cm5
return !!((_c = (_b = cm5or6 === null || cm5or6 === void 0 ? void 0 : cm5or6.display) === null || _b === void 0 ? void 0 : _b.input) === null || _c === void 0 ? void 0 : _c.composing);
}
writeLog(log) {
return __awaiter(this, void 0, void 0, function* () {
yield this.unsafeApp.vault.adapter.append(obsidian.normalizePath("log.md"), log);
});
}
}
const groupBy = (values, toKey) => values.reduce((prev, cur, _1, _2, k = toKey(cur)) => ((prev[k] || (prev[k] = [])).push(cur), prev), {});
function uniq(values) {
return [...new Set(values)];
}
function uniqBy(values, fn) {
const m = new Map();
values.forEach((x) => {
const k = fn(x);
if (!m.has(k)) {
m.set(k, x);
}
});
return Array.from(m.values());
}
function uniqWith(arr, fn) {
return arr.filter((element, index) => arr.findIndex((step) => fn(element, step)) === index);
}
function mirrorMap(collection, toValue) {
return collection.reduce((p, c) => (Object.assign(Object.assign({}, p), { [toValue(c)]: toValue(c) })), {});
}
class WordTypeMeta {
constructor(type, priority, group) {
this.type = type;
this.priority = priority;
this.group = group;
WordTypeMeta._values.push(this);
WordTypeMeta._dict[type] = this;
}
static of(type) {
return WordTypeMeta._dict[type];
}
static values() {
return WordTypeMeta._values;
}
}
WordTypeMeta._values = [];
WordTypeMeta._dict = {};
WordTypeMeta.FRONT_MATTER = new WordTypeMeta("frontMatter", 100, "frontMatter");
WordTypeMeta.INTERNAL_LINK = new WordTypeMeta("internalLink", 90, "internalLink");
WordTypeMeta.CUSTOM_DICTIONARY = new WordTypeMeta("customDictionary", 80, "suggestion");
WordTypeMeta.CURRENT_FILE = new WordTypeMeta("currentFile", 70, "suggestion");
WordTypeMeta.CURRENT_VAULT = new WordTypeMeta("currentVault", 60, "suggestion");
function pushWord(wordsByFirstLetter, key, word) {
if (wordsByFirstLetter[key] === undefined) {
wordsByFirstLetter[key] = [word];
return;
}
wordsByFirstLetter[key].push(word);
}
// Public for tests
function judge(word, query, queryStartWithUpper) {
var _a;
if (query === "") {
return {
word: Object.assign(Object.assign({}, word), { hit: word.value }),
value: word.value,
alias: false,
};
}
if (lowerStartsWith(word.value, query)) {
if (queryStartWithUpper &&
word.type !== "internalLink" &&
word.type !== "frontMatter") {
const c = capitalizeFirstLetter(word.value);
return {
word: Object.assign(Object.assign({}, word), { value: c, hit: c }),
value: c,
alias: false,
};
}
else {
return {
word: Object.assign(Object.assign({}, word), { hit: word.value }),
value: word.value,
alias: false,
};
}
}
const matchedAlias = (_a = word.aliases) === null || _a === void 0 ? void 0 : _a.find((a) => lowerStartsWith(a, query));
if (matchedAlias) {
return {
word: Object.assign(Object.assign({}, word), { hit: matchedAlias }),
value: matchedAlias,
alias: true,
};
}
return {
word,
alias: false,
};
}
function suggestWords(indexedWords, query, max, frontMatter, selectionHistoryStorage) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
const queryStartWithUpper = capitalizeFirstLetter(query) === query;
const flattenFrontMatterWords = () => {
var _a, _b;
if (frontMatter === "alias" || frontMatter === "aliases") {
return [];
}
if (frontMatter && ((_a = indexedWords.frontMatter) === null || _a === void 0 ? void 0 : _a[frontMatter])) {
return Object.values((_b = indexedWords.frontMatter) === null || _b === void 0 ? void 0 : _b[frontMatter]).flat();
}
return [];
};
const words = queryStartWithUpper
? frontMatter
? flattenFrontMatterWords()
: [
...((_a = indexedWords.currentFile[query.charAt(0)]) !== null && _a !== void 0 ? _a : []),
...((_b = indexedWords.currentFile[query.charAt(0).toLowerCase()]) !== null && _b !== void 0 ? _b : []),
...((_c = indexedWords.currentVault[query.charAt(0)]) !== null && _c !== void 0 ? _c : []),
...((_d = indexedWords.currentVault[query.charAt(0).toLowerCase()]) !== null && _d !== void 0 ? _d : []),
...((_e = indexedWords.customDictionary[query.charAt(0)]) !== null && _e !== void 0 ? _e : []),
...((_f = indexedWords.customDictionary[query.charAt(0).toLowerCase()]) !== null && _f !== void 0 ? _f : []),
...((_g = indexedWords.internalLink[query.charAt(0)]) !== null && _g !== void 0 ? _g : []),
...((_h = indexedWords.internalLink[query.charAt(0).toLowerCase()]) !== null && _h !== void 0 ? _h : []),
]
: frontMatter
? flattenFrontMatterWords()
: [
...((_j = indexedWords.currentFile[query.charAt(0)]) !== null && _j !== void 0 ? _j : []),
...((_k = indexedWords.currentVault[query.charAt(0)]) !== null && _k !== void 0 ? _k : []),
...((_l = indexedWords.customDictionary[query.charAt(0)]) !== null && _l !== void 0 ? _l : []),
...((_m = indexedWords.internalLink[query.charAt(0)]) !== null && _m !== void 0 ? _m : []),
...((_o = indexedWords.internalLink[query.charAt(0).toUpperCase()]) !== null && _o !== void 0 ? _o : []),
];
const candidate = Array.from(words)
.map((x) => judge(x, query, queryStartWithUpper))
.filter((x) => x.value !== undefined)
.sort((a, b) => {
const aWord = a.word;
const bWord = b.word;
const notSameWordType = aWord.type !== bWord.type;
if (frontMatter && notSameWordType) {
return bWord.type === "frontMatter" ? 1 : -1;
}
if (selectionHistoryStorage) {
const ret = selectionHistoryStorage.compare(aWord, bWord);
if (ret !== 0) {
return ret;
}
}
if (a.value.length !== b.value.length) {
return a.value.length > b.value.length ? 1 : -1;
}
if (notSameWordType) {
return WordTypeMeta.of(bWord.type).priority >
WordTypeMeta.of(aWord.type).priority
? 1
: -1;
}
if (a.alias !== b.alias) {
return a.alias ? 1 : -1;
}
return 0;
})
.map((x) => x.word)
.slice(0, max);
// XXX: There is no guarantee that equals with max, but it is important for performance
return uniqWith(candidate, (a, b) => a.value === b.value &&
WordTypeMeta.of(a.type).group === WordTypeMeta.of(b.type).group);
}
// TODO: refactoring
// Public for tests
function judgeByPartialMatch(word, query, queryStartWithUpper) {
var _a, _b;
if (query === "") {
return {
word: Object.assign(Object.assign({}, word), { hit: word.value }),
value: word.value,
alias: false,
};
}
if (lowerStartsWith(word.value, query)) {
if (queryStartWithUpper &&
word.type !== "internalLink" &&
word.type !== "frontMatter") {
const c = capitalizeFirstLetter(word.value);
return { word: Object.assign(Object.assign({}, word), { value: c, hit: c }), value: c, alias: false };
}
else {
return {
word: Object.assign(Object.assign({}, word), { hit: word.value }),
value: word.value,
alias: false,
};
}
}
const matchedAliasStarts = (_a = word.aliases) === null || _a === void 0 ? void 0 : _a.find((a) => lowerStartsWith(a, query));
if (matchedAliasStarts) {
return {
word: Object.assign(Object.assign({}, word), { hit: matchedAliasStarts }),
value: matchedAliasStarts,
alias: true,
};
}
if (lowerIncludes(word.value, query)) {
return {
word: Object.assign(Object.assign({}, word), { hit: word.value }),
value: word.value,
alias: false,
};
}
const matchedAliasIncluded = (_b = word.aliases) === null || _b === void 0 ? void 0 : _b.find((a) => lowerIncludes(a, query));
if (matchedAliasIncluded) {
return {
word: Object.assign(Object.assign({}, word), { hit: matchedAliasIncluded }),
value: matchedAliasIncluded,
alias: true,
};
}
return { word: word, alias: false };
}
function suggestWordsByPartialMatch(indexedWords, query, max, frontMatter, selectionHistoryStorage) {
const queryStartWithUpper = capitalizeFirstLetter(query) === query;
const flatObjectValues = (object) => Object.values(object).flat();
const flattenFrontMatterWords = () => {
var _a, _b;
if (frontMatter === "alias" || frontMatter === "aliases") {
return [];
}
if (frontMatter && ((_a = indexedWords.frontMatter) === null || _a === void 0 ? void 0 : _a[frontMatter])) {
return Object.values((_b = indexedWords.frontMatter) === null || _b === void 0 ? void 0 : _b[frontMatter]).flat();
}
return [];
};
const words = frontMatter
? flattenFrontMatterWords()
: [
...flatObjectValues(indexedWords.currentFile),
...flatObjectValues(indexedWords.currentVault),
...flatObjectValues(indexedWords.customDictionary),
...flatObjectValues(indexedWords.internalLink),
];
const candidate = Array.from(words)
.map((x) => judgeByPartialMatch(x, query, queryStartWithUpper))
.filter((x) => x.value !== undefined)
.sort((a, b) => {
const aWord = a.word;
const bWord = b.word;
const notSameWordType = aWord.type !== bWord.type;
if (frontMatter && notSameWordType) {
return bWord.type === "frontMatter" ? 1 : -1;
}
if (selectionHistoryStorage) {
const ret = selectionHistoryStorage.compare(aWord, bWord);
if (ret !== 0) {
return ret;
}
}
const as = lowerStartsWith(a.value, query);
const bs = lowerStartsWith(b.value, query);
if (as !== bs) {
return bs ? 1 : -1;
}
if (a.value.length !== b.value.length) {
return a.value.length > b.value.length ? 1 : -1;
}
if (notSameWordType) {
return WordTypeMeta.of(bWord.type).priority >
WordTypeMeta.of(aWord.type).priority
? 1
: -1;
}
if (a.alias !== b.alias) {
return a.alias ? 1 : -1;
}
return 0;
})
.map((x) => x.word)
.slice(0, max);
// XXX: There is no guarantee that equals with max, but it is important for performance
return uniqWith(candidate, (a, b) => a.value === b.value &&
WordTypeMeta.of(a.type).group === WordTypeMeta.of(b.type).group);
}
function basename(path, ext) {
var _a, _b;
const name = (_b = (_a = path.match(/.+[\\/]([^\\/]+)[\\/]?$/)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : path;
return ext && name.endsWith(ext) ? name.replace(ext, "") : name;
}
function dirname(path) {
var _a, _b;
return (_b = (_a = path.match(/(.+)[\\/].+$/)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : ".";
}
function isURL(path) {
return Boolean(path.match(new RegExp("^https?://")));
}
function escape(value) {
// This tricky logics for Safari
// https://github.com/tadashi-aikawa/obsidian-various-complements-plugin/issues/56
return value
.replace(/\\/g, "__VariousComplementsEscape__")
.replace(/\n/g, "\\n")
.replace(/\t/g, "\\t")
.replace(/__VariousComplementsEscape__/g, "\\\\");
}
function unescape(value) {
// This tricky logics for Safari
// https://github.com/tadashi-aikawa/obsidian-various-complements-plugin/issues/56
return value
.replace(/\\\\/g, "__VariousComplementsEscape__")
.replace(/\\n/g, "\n")
.replace(/\\t/g, "\t")
.replace(/__VariousComplementsEscape__/g, "\\");
}
function jsonToWords(json, path, systemCaretSymbol) {
return json.words.map((x) => {
var _a;
return ({
value: x.displayed || x.value,
description: x.description,
aliases: x.aliases,
type: "customDictionary",
createdPath: path,
insertedText: x.displayed ? x.value : undefined,
caretSymbol: (_a = json.caretSymbol) !== null && _a !== void 0 ? _a : systemCaretSymbol,
ignoreSpaceAfterCompletion: json.ignoreSpaceAfterCompletion,
});
});
}
function lineToWord(line, delimiter, path, delimiterForDisplay, delimiterForHide, systemCaretSymbol) {
const [v, description, ...aliases] = line.split(delimiter.value);
let value = unescape(v);
let insertedText;
let displayedText = value;
if (delimiterForDisplay && value.includes(delimiterForDisplay)) {
[displayedText, insertedText] = value.split(delimiterForDisplay);
}
if (delimiterForHide && value.includes(delimiterForHide)) {
insertedText = value.replace(delimiterForHide, "");
displayedText = `${value.split(delimiterForHide)[0]} ...`;
}
return {
value: displayedText,
description,
aliases,
type: "customDictionary",
createdPath: path,
insertedText,
caretSymbol: systemCaretSymbol,
};
}
function wordToLine(word, delimiter, dividerForDisplay) {
const value = word.insertedText && dividerForDisplay
? `${word.value}${dividerForDisplay}${word.insertedText}`
: word.value;
const escapedValue = escape(value);
if (!word.description && !word.aliases) {
return escapedValue;
}
if (!word.aliases) {
return [escapedValue, word.description].join(delimiter.value);
}
return [escapedValue, word.description, ...word.aliases].join(delimiter.value);
}
function synonymAliases$1(name) {
const lessEmojiValue = excludeEmoji(name);
return name === lessEmojiValue ? [] : [lessEmojiValue];
}
class CustomDictionaryWordProvider {
constructor(app, appHelper) {
this.words = [];
this.wordByValue = {};
this.wordsByFirstLetter = {};
this.appHelper = appHelper;
this.fileSystemAdapter = app.vault.adapter;
}
get editablePaths() {
return this.paths.filter((x) => !isURL(x) && !x.endsWith(".json"));
}
loadWords(path, option) {
return __awaiter(this, void 0, void 0, function* () {
const contents = isURL(path)
? yield obsidian.request({ url: path })
: yield this.fileSystemAdapter.read(path);
const words = path.endsWith(".json")
? jsonToWords(JSON.parse(contents), path, option.caretSymbol)
: contents
.split(/\r\n|\n/)
.map((x) => x.replace(/%%.*%%/g, ""))
.filter((x) => x)
.map((x) => lineToWord(x, this.delimiter, path, option.delimiterForDisplay, option.delimiterForHide, option.caretSymbol));
return words.filter((x) => !option.regexp || x.value.match(new RegExp(option.regexp)));
});
}
refreshCustomWords(option) {
return __awaiter(this, void 0, void 0, function* () {
this.clearWords();
for (const path of this.paths) {
try {
const words = yield this.loadWords(path, option);
words.forEach((x) => this.words.push(x));
}
catch (e) {
// noinspection ObjectAllocationIgnored
new obsidian.Notice(`⚠ Fail to load ${path} -- Various Complements Plugin -- \n ${e}`, 0);
}
}
this.words.forEach((x) => this.addWord(x));
});
}
addWordWithDictionary(word, dictionaryPath) {
return __awaiter(this, void 0, void 0, function* () {
this.addWord(word);
yield this.fileSystemAdapter.append(dictionaryPath, "\n" + wordToLine(word, this.delimiter, this.dividerForDisplay));
});
}
addWord(word) {
var _a, _b;
// Add aliases as a synonym
const wordWithSynonym = Object.assign(Object.assign({}, word), { aliases: [...((_a = word.aliases) !== null && _a !== void 0 ? _a : []), ...synonymAliases$1(word.value)] });
this.wordByValue[wordWithSynonym.value] = wordWithSynonym;
pushWord(this.wordsByFirstLetter, wordWithSynonym.value.charAt(0), wordWithSynonym);
(_b = wordWithSynonym.aliases) === null || _b === void 0 ? void 0 : _b.forEach((a) => pushWord(this.wordsByFirstLetter, a.charAt(0), wordWithSynonym));
}
clearWords() {
this.words = [];
this.wordByValue = {};
this.wordsByFirstLetter = {};
}
get wordCount() {
return this.words.length;
}
setSettings(paths, delimiter, dividerForDisplay) {
this.paths = paths;
this.delimiter = delimiter;
this.dividerForDisplay = dividerForDisplay;
}
}
class CurrentFileWordProvider {
constructor(app, appHelper) {
this.app = app;
this.appHelper = appHelper;
this.wordsByFirstLetter = {};
this.words = [];
}
refreshWords(onlyEnglish) {
return __awaiter(this, void 0, void 0, function* () {
this.clearWords();
const editor = this.appHelper.getCurrentEditor();
if (!editor) {
return;
}
const file = this.app.workspace.getActiveFile();
if (!file) {
return;
}
const currentToken = this.tokenizer
.tokenize(editor.getLine(editor.getCursor().line).slice(0, editor.getCursor().ch))
.last();
const content = yield this.app.vault.cachedRead(file);
const tokens = onlyEnglish
? this.tokenizer.tokenize(content).filter(allAlphabets)
: this.tokenizer.tokenize(content);
this.words = uniq(tokens)
.filter((x) => x !== currentToken)
.map((x) => ({
value: x,
type: "currentFile",
createdPath: file.path,
}));
this.wordsByFirstLetter = groupBy(this.words, (x) => x.value.charAt(0));
});
}
clearWords() {
this.words = [];
this.wordsByFirstLetter = {};
}
get wordCount() {
return this.words.length;
}
setSettings(tokenizer) {
this.tokenizer = tokenizer;
}
}
class InternalLinkWordProvider {
constructor(app, appHelper) {
this.app = app;
this.appHelper = appHelper;
this.words = [];
this.wordsByFirstLetter = {};
}
refreshWords(wordAsInternalLinkAlias, excludePathPrefixPatterns) {
var _a;
this.clearWords();
const synonymAliases = (name) => {
const lessEmojiValue = excludeEmoji(name);
return name === lessEmojiValue ? [] : [lessEmojiValue];
};
const resolvedInternalLinkWords = this.app.vault
.getMarkdownFiles()
.filter((f) => excludePathPrefixPatterns.every((x) => !f.path.startsWith(x)))
.flatMap((x) => {
const aliases = this.appHelper.getAliases(x);
if (wordAsInternalLinkAlias) {
return [
{
value: x.basename,
type: "internalLink",
createdPath: x.path,
aliases: synonymAliases(x.basename),
description: x.path,
},
...aliases.map((a) => ({
value: a,
type: "internalLink",
createdPath: x.path,
aliases: synonymAliases(a),
description: x.path,
aliasMeta: {
origin: x.basename,
},
})),
];
}
else {
return [
{
value: x.basename,
type: "internalLink",
createdPath: x.path,
aliases: [
...synonymAliases(x.basename),
...aliases,
...aliases.flatMap(synonymAliases),
],
description: x.path,
},
];
}
});
const unresolvedInternalLinkWords = this.appHelper
.searchPhantomLinks()
.map(({ path, link }) => {
return {
value: link,
type: "internalLink",
createdPath: path,
aliases: synonymAliases(link),
description: `Appeared in -> ${path}`,
phantom: true,
};
});
this.words = [...resolvedInternalLinkWords, ...unresolvedInternalLinkWords];
for (const word of this.words) {
pushWord(this.wordsByFirstLetter, word.value.charAt(0), word);
(_a = word.aliases) === null || _a === void 0 ? void 0 : _a.forEach((a) => pushWord(this.wordsByFirstLetter, a.charAt(0), word));
}
}
clearWords() {
this.words = [];
this.wordsByFirstLetter = {};
}
get wordCount() {
return this.words.length;
}
}
class MatchStrategy {
constructor(name, handler) {
this.name = name;
this.handler = handler;
MatchStrategy._values.push(this);
}
static fromName(name) {
return MatchStrategy._values.find((x) => x.name === name);
}
static values() {
return MatchStrategy._values;
}
}
MatchStrategy._values = [];
MatchStrategy.PREFIX = new MatchStrategy("prefix", suggestWords);
MatchStrategy.PARTIAL = new MatchStrategy("partial", suggestWordsByPartialMatch);
class CycleThroughSuggestionsKeys {
constructor(name, nextKey, previousKey) {
this.name = name;
this.nextKey = nextKey;
this.previousKey = previousKey;
CycleThroughSuggestionsKeys._values.push(this);
}
static fromName(name) {
return CycleThroughSuggestionsKeys._values.find((x) => x.name === name);
}
static values() {
return CycleThroughSuggestionsKeys._values;
}
}
CycleThroughSuggestionsKeys._values = [];
CycleThroughSuggestionsKeys.NONE = new CycleThroughSuggestionsKeys("None", { modifiers: [], key: null }, { modifiers: [], key: null });
CycleThroughSuggestionsKeys.TAB = new CycleThroughSuggestionsKeys("Tab, Shift+Tab", { modifiers: [], key: "Tab" }, { modifiers: ["Shift"], key: "Tab" });
CycleThroughSuggestionsKeys.EMACS = new CycleThroughSuggestionsKeys("Ctrl/Cmd+N, Ctrl/Cmd+P", { modifiers: ["Mod"], key: "N" }, { modifiers: ["Mod"], key: "P" });
CycleThroughSuggestionsKeys.VIM = new CycleThroughSuggestionsKeys("Ctrl/Cmd+J, Ctrl/Cmd+K", { modifiers: ["Mod"], key: "J" }, { modifiers: ["Mod"], key: "K" });
class ColumnDelimiter {
constructor(name, value) {
this.name = name;
this.value = value;
ColumnDelimiter._values.push(this);
}
static fromName(name) {
return ColumnDelimiter._values.find((x) => x.name === name);
}
static values() {
return ColumnDelimiter._values;
}
}
ColumnDelimiter._values = [];
ColumnDelimiter.TAB = new ColumnDelimiter("Tab", "\t");
ColumnDelimiter.COMMA = new ColumnDelimiter("Comma", ",");
ColumnDelimiter.PIPE = new ColumnDelimiter("Pipe", "|");
class SelectSuggestionKey {
constructor(name, keyBind) {
this.name = name;
this.keyBind = keyBind;
SelectSuggestionKey._values.push(this);
}
static fromName(name) {
return SelectSuggestionKey._values.find((x) => x.name === name);
}
static values() {
return SelectSuggestionKey._values;
}
}
SelectSuggestionKey._values = [];
SelectSuggestionKey.ENTER = new SelectSuggestionKey("Enter", {
modifiers: [],
key: "Enter",
});
SelectSuggestionKey.TAB = new SelectSuggestionKey("Tab", {
modifiers: [],
key: "Tab",
});
SelectSuggestionKey.MOD_ENTER = new SelectSuggestionKey("Ctrl/Cmd+Enter", {
modifiers: ["Mod"],
key: "Enter",
});
SelectSuggestionKey.ALT_ENTER = new SelectSuggestionKey("Alt+Enter", {
modifiers: ["Alt"],
key: "Enter",
});
SelectSuggestionKey.SHIFT_ENTER = new SelectSuggestionKey("Shift+Enter", {
modifiers: ["Shift"],
key: "Enter",
});
SelectSuggestionKey.SPACE = new SelectSuggestionKey("Space", {
modifiers: [],
key: " ",
});
class CurrentVaultWordProvider {
constructor(app, appHelper) {
this.app = app;
this.appHelper = appHelper;
this.wordsByFirstLetter = {};
this.words = [];
}
refreshWords() {
return __awaiter(this, void 0, void 0, function* () {
this.clearWords();
const currentDirname = this.appHelper.getCurrentDirname();
const markdownFilePaths = this.app.vault
.getMarkdownFiles()
.map((x) => x.path)
.filter((p) => this.includePrefixPatterns.every((x) => p.startsWith(x)))
.filter((p) => this.excludePrefixPatterns.every((x) => !p.startsWith(x)))
.filter((p) => !this.onlyUnderCurrentDirectory || dirname(p) === currentDirname);
let wordByValue = {};
for (const path of markdownFilePaths) {
const content = yield this.app.vault.adapter.read(path);
for (const token of this.tokenizer.tokenize(content)) {
wordByValue[token] = {
value: token,
type: "currentVault",
createdPath: path,
description: path,
};
}
}
this.words = Object.values(wordByValue);
this.wordsByFirstLetter = groupBy(this.words, (x) => x.value.charAt(0));
});
}
clearWords() {
this.words = [];
this.wordsByFirstLetter = {};
}
get wordCount() {
return this.words.length;
}
setSettings(tokenizer, includePrefixPatterns, excludePrefixPatterns, onlyUnderCurrentDirectory) {
this.tokenizer = tokenizer;
this.includePrefixPatterns = includePrefixPatterns;
this.excludePrefixPatterns = excludePrefixPatterns;
this.onlyUnderCurrentDirectory = onlyUnderCurrentDirectory;
}
}
class OpenSourceFileKeys {
constructor(name, keyBind) {
this.name = name;
this.keyBind = keyBind;
OpenSourceFileKeys._values.push(this);
}
static fromName(name) {
return OpenSourceFileKeys._values.find((x) => x.name === name);
}
static values() {
return OpenSourceFileKeys._values;
}
}
OpenSourceFileKeys._values = [];
OpenSourceFileKeys.NONE = new OpenSourceFileKeys("None", {
modifiers: [],
key: null,
});
OpenSourceFileKeys.MOD_ENTER = new OpenSourceFileKeys("Ctrl/Cmd+Enter", {
modifiers: ["Mod"],
key: "Enter",
});
OpenSourceFileKeys.ALT_ENTER = new OpenSourceFileKeys("Alt+Enter", {
modifiers: ["Alt"],
key: "Enter",
});
OpenSourceFileKeys.SHIFT_ENTER = new OpenSourceFileKeys("Shift+Enter", {
modifiers: ["Shift"],
key: "Enter",
});
class DescriptionOnSuggestion {
constructor(name, toDisplay) {
this.name = name;
this.toDisplay = toDisplay;
DescriptionOnSuggestion._values.push(this);
}
static fromName(name) {
return DescriptionOnSuggestion._values.find((x) => x.name === name);
}
static values() {
return DescriptionOnSuggestion._values;
}
}
DescriptionOnSuggestion._values = [];
DescriptionOnSuggestion.NONE = new DescriptionOnSuggestion("None", () => null);
DescriptionOnSuggestion.SHORT = new DescriptionOnSuggestion("Short", (word) => {
if (!word.description) {
return null;
}
return word.type === "customDictionary"
? word.description
: basename(word.description);
});
DescriptionOnSuggestion.FULL = new DescriptionOnSuggestion("Full", (word) => { var _a; return (_a = word.description) !== null && _a !== void 0 ? _a : null; });
function synonymAliases(name) {
const lessEmojiValue = excludeEmoji(name);
return name === lessEmojiValue ? [] : [lessEmojiValue];
}
function frontMatterToWords(file, key, values) {
return values.map((x) => ({
key,
value: x,
type: "frontMatter",
createdPath: file.path,
aliases: synonymAliases(x),
}));
}
function pickWords(file, fm) {
return Object.entries(fm)
.filter(([_key, value]) => value != null &&
(typeof value === "string" || typeof value[0] === "string"))
.flatMap(([key, value]) => frontMatterToWords(file, key, value));
}
// noinspection FunctionWithMultipleLoopsJS
function extractAndUniqWords(wordsByCreatedPath) {
return uniqBy(Object.values(wordsByCreatedPath).flat(), (w) => w.key + w.value.toLowerCase());
}
function indexingWords(words) {
const wordsByKey = groupBy(words, (x) => x.key);
return Object.fromEntries(Object.entries(wordsByKey).map(([key, words]) => [
key,
groupBy(words, (w) => w.value.charAt(0)),
]));
}
class FrontMatterWordProvider {
constructor(app, appHelper) {
this.app = app;
this.appHelper = appHelper;
this.wordsByCreatedPath = {};
}
refreshWords() {
this.clearWords();
this.app.vault.getMarkdownFiles().forEach((f) => {
const fm = this.appHelper.getFrontMatter(f);
if (!fm) {
return;
}
this.wordsByCreatedPath[f.path] = pickWords(f, fm);
});
this.words = extractAndUniqWords(this.wordsByCreatedPath);
this.wordsByFirstLetterByKey = indexingWords(this.words);
}
updateWordIndex(file) {
const fm = this.appHelper.getFrontMatter(file);
if (!fm) {
return;
}
this.wordsByCreatedPath[file.path] = pickWords(file, fm);
}
updateWords() {
this.words = extractAndUniqWords(this.wordsByCreatedPath);
this.wordsByFirstLetterByKey = indexingWords(this.words);
}
clearWords() {
this.wordsByCreatedPath = {};
this.words = [];
this.wordsByFirstLetterByKey = {};
}
get wordCount() {
return this.words.length;
}
}
const neverUsedHandler = (..._args) => [];
class SpecificMatchStrategy {
constructor(name, handler) {
this.name = name;
this.handler = handler;
SpecificMatchStrategy._values.push(this);
}
static fromName(name) {
return SpecificMatchStrategy._values.find((x) => x.name === name);
}
static values() {
return SpecificMatchStrategy._values;
}
}
SpecificMatchStrategy._values = [];
SpecificMatchStrategy.INHERIT = new SpecificMatchStrategy("inherit", neverUsedHandler);
SpecificMatchStrategy.PREFIX = new SpecificMatchStrategy("prefix", suggestWords);
SpecificMatchStrategy.PARTIAL = new SpecificMatchStrategy("partial", suggestWordsByPartialMatch);
const SEC = 1000;
const MIN = SEC * 60;
const HOUR = MIN * 60;
const DAY = HOUR * 24;
const WEEK = DAY * 7;
function calcScore(history) {
if (!history) {
return 0;
}
const behind = Date.now() - history.lastUpdated;
// noinspection IfStatementWithTooManyBranchesJS
if (behind < MIN) {
return 8 * history.count;
}
else if (behind < HOUR) {
return 4 * history.count;
}
else if (behind < DAY) {
return 2 * history.count;
}
else if (behind < WEEK) {
return 0.5 * history.count;
}
else {
return 0.25 * history.count;
}
}
class SelectionHistoryStorage {
constructor(data = {}) {
this.data = data;
const now = Date.now();
this.version = now;
this.persistedVersion = now;
}
// noinspection FunctionWithMultipleLoopsJS
purge() {
for (const hit of Object.keys(this.data)) {
for (const value of Object.keys(this.data[hit])) {
for (const kind of Object.keys(this.data[hit][value])) {
if (Date.now() - this.data[hit][value][kind].lastUpdated > 4 * WEEK) {
delete this.data[hit][value][kind];
}
}
if (Object.isEmpty(this.data[hit][value])) {
delete this.data[hit][value];
}
}
if (Object.isEmpty(this.data[hit])) {
delete this.data[hit];
}
}
}
getSelectionHistory(word) {
var _a, _b;
return (_b = (_a = this.data[word.hit]) === null || _a === void 0 ? void 0 : _a[word.value]) === null || _b === void 0 ? void 0 : _b[word.type];
}
increment(word) {
if (!this.data[word.hit]) {
this.data[word.hit] = {};
}
if (!this.data[word.hit][word.value]) {
this.data[word.hit][word.value] = {};
}
if (this.data[word.hit][word.value][word.type]) {
this.data[word.hit][word.value][word.type] = {
count: this.data[word.hit][word.value][word.type].count + 1,
lastUpdated: Date.now(),
};
}
else {
this.data[word.hit][word.value][word.type] = {
count: 1,
lastUpdated: Date.now(),
};
}
this.version = Date.now();
}
compare(w1, w2) {
const score1 = calcScore(this.getSelectionHistory(w1));
const score2 = calcScore(this.getSelectionHistory(w2));
if (score1 === score2) {
return 0;
}
return score1 > score2 ? -1 : 1;
}
get shouldPersist() {
return this.version > this.persistedVersion;
}
syncPersistVersion() {
this.persistedVersion = this.version;
}
}
function buildLogMessage(message, msec) {
return `${message}: ${Math.round(msec)}[ms]`;
}
class AutoCompleteSuggest extends obsidian.EditorSuggest {
constructor(app, statusBar) {
super(app);
this.previousCurrentLine = "";
this.keymapEventHandler = [];
this.appHelper = new AppHelper(app);
this.statusBar = statusBar;
}
triggerComplete() {
const editor = this.appHelper.getCurrentEditor();
const activeFile = this.app.workspace.getActiveFile();
if (!editor || !activeFile) {
return;
}
// XXX: Unsafe
this.runManually = true;
this.trigger(editor, activeFile, true);
}
static new(app, settings, statusBar, onPersistSelectionHistory) {
return __awaiter(this, void 0, void 0, function* () {
const ins = new AutoCompleteSuggest(app, statusBar);
ins.currentFileWordProvider = new CurrentFileWordProvider(ins.app, ins.appHelper);
ins.currentVaultWordProvider = new CurrentVaultWordProvider(ins.app, ins.appHelper);
ins.customDictionaryWordProvider = new CustomDictionaryWordProvider(ins.app, ins.appHelper);
ins.internalLinkWordProvider = new InternalLinkWordProvider(ins.app, ins.appHelper);
ins.frontMatterWordProvider = new FrontMatterWordProvider(ins.app, ins.appHelper);
ins.selectionHistoryStorage = new SelectionHistoryStorage(settings.selectionHistoryTree);
ins.selectionHistoryStorage.purge();
yield ins.updateSettings(settings);
ins.modifyEventRef = app.vault.on("modify", (_) => __awaiter(this, void 0, void 0, function* () {
var _a;
yield ins.refreshCurrentFileTokens();
if ((_a = ins.selectionHistoryStorage) === null || _a === void 0 ? void 0 : _a.shouldPersist) {
ins.settings.selectionHistoryTree = ins.selectionHistoryStorage.data;
ins.selectionHistoryStorage.syncPersistVersion();
onPersistSelectionHistory();
}
}));
ins.activeLeafChangeRef = app.workspace.on("active-leaf-change", (_) => __awaiter(this, void 0, void 0, function* () {
yield ins.refreshCurrentFileTokens();
ins.refreshInternalLinkTokens();
ins.updateFrontMatterToken();
}));
ins.metadataCacheChangeRef = app.metadataCache.on("changed", (f) => {
ins.updateFrontMatterTokenIndex(f);
if (!ins.appHelper.isActiveFile(f)) {
ins.updateFrontMatterToken();
}
});
// Avoid referring to incorrect cache
const cacheResolvedRef = app.metadataCache.on("resolved", () => __awaiter(this, void 0, void 0, function* () {
ins.refreshInternalLinkTokens();
ins.refreshFrontMatterTokens();
// noinspection ES6MissingAwait
ins.refreshCustomDictionaryTokens();
// noinspection ES6MissingAwait
ins.refreshCurrentVaultTokens();
ins.app.metadataCache.offref(cacheResolvedRef);
}));
return ins;
});
}
predictableComplete() {
const editor = this.appHelper.getCurrentEditor();
if (!editor) {
return;
}
const cursor = editor.getCursor();
const currentToken = this.tokenizer
.tokenize(editor.getLine(cursor.line).slice(0, cursor.ch))
.last();
if (!currentToken) {
return;
}
let suggestion = this.tokenizer
.tokenize(editor.getRange({ line: Math.max(cursor.line - 50, 0), ch: 0 }, cursor))
.reverse()
.slice(1)
.find((x) => x.startsWith(currentToken));
if (!suggestion) {
suggestion = this.tokenizer
.tokenize(editor.getRange(cursor, {
line: Math.min(cursor.line + 50, editor.lineCount() - 1),
ch: 0,
}))
.find((x) => x.startsWith(currentToken));
}
if (!suggestion) {
return;
}
editor.replaceRange(suggestion, { line: cursor.line, ch: cursor.ch - currentToken.length }, { line: cursor.line, ch: cursor.ch });
this.close();
this.debounceClose();
}
unregister() {
this.app.vault.offref(this.modifyEventRef);
this.app.workspace.offref(this.activeLeafChangeRef);
this.app.metadataCache.offref(this.metadataCacheChangeRef);
}
// settings getters
get tokenizerStrategy() {
return TokenizeStrategy.fromName(this.settings.strategy);
}
get matchStrategy() {
return MatchStrategy.fromName(this.settings.matchStrategy);
}
get frontMatterComplementStrategy() {
return SpecificMatchStrategy.fromName(this.settings.frontMatterComplementMatchStrategy);
}
get minNumberTriggered() {
return (this.settings.minNumberOfCharactersTriggered ||
this.tokenizerStrategy.triggerThreshold);
}
get descriptionOnSuggestion() {
return DescriptionOnSuggestion.fromName(this.settings.descriptionOnSuggestion);
}
get excludeInternalLinkPrefixPathPatterns() {
return this.settings.excludeInternalLinkPathPrefixPatterns
.split("\n")
.filter((x) => x);
}
// --- end ---
get indexedWords() {
return {
currentFile: this.currentFileWordProvider.wordsByFirstLetter,
currentVault: this.currentVaultWordProvider.wordsByFirstLetter,
customDictionary: this.customDictionaryWordProvider.wordsByFirstLetter,
internalLink: this.internalLinkWordProvider.wordsByFirstLetter,
frontMatter: this.frontMatterWordProvider.wordsByFirstLetterByKey,
};
}
updateSettings(settings) {
return __awaiter(this, void 0, void 0, function* () {
this.settings = settings;
this.statusBar.setMatchStrategy(this.matchStrategy);
this.tokenizer = createTokenizer(this.tokenizerStrategy);
this.currentFileWordProvider.setSettings(this.tokenizer);
this.currentVaultWordProvider.setSettings(this.tokenizer, settings.includeCurrentVaultPathPrefixPatterns
.split("\n")
.filter((x) => x), settings.excludeCurrentVaultPathPrefixPatterns
.split("\n")
.filter((x) => x), settings.includeCurrentVaultOnlyFilesUnderCurrentDirectory);
this.customDictionaryWordProvider.setSettings(settings.customDictionaryPaths.split("\n").filter((x) => x), ColumnDelimiter.fromName(settings.columnDelimiter), settings.delimiterToDivideSuggestionsForDisplayFromInsertion || null);
this.debounceGetSuggestions = obsidian.debounce((context, cb) => {
const start = performance.now();
this.showDebugLog(() => `[context.query]: ${context.query}`);
const parsedQuery = JSON.parse(context.query);
const words = parsedQuery.queries
.filter((x, i, xs) => parsedQuery.currentFrontMatter ||
(this.settings.minNumberOfWordsTriggeredPhrase + i - 1 <
xs.length &&
x.word.length >= this.minNumberTriggered &&
!this.tokenizer.shouldIgnore(x.word) &&
!x.word.endsWith(" ")))
.map((q) => {
const handler = parsedQuery.currentFrontMatter &&
this.frontMatterComplementStrategy !==
SpecificMatchStrategy.INHERIT
? this.frontMatterComplementStrategy.handler
: this.matchStrategy.handler;
return handler(this.indexedWords, q.word, this.settings.maxNumberOfSuggestions, parsedQuery.currentFrontMatter, this.selectionHistoryStorage).map((word) => (Object.assign(Object.assign({}, word), { offset: q.offset })));
})
.flat();
cb(uniqWith(words, (a, b) => a.value === b.value && a.type === b.type).slice(0, this.settings.maxNumberOfSuggestions));
this.showDebugLog(() => buildLogMessage("Get suggestions", performance.now() - start));
}, this.settings.delayMilliSeconds, true);
this.debounceClose = obsidian.debounce(() => {
this.close();
}, this.settings.delayMilliSeconds + 50);
this.registerKeymaps();
});
}
registerKeymaps() {
// Clear
this.keymapEventHandler.forEach((x) => this.scope.unregister(x));
this.keymapEventHandler = [];
this.scope.unregister(this.scope.keys.find((x) => x.key === "Enter"));
const selectSuggestionKey = SelectSuggestionKey.fromName(this.settings.selectSuggestionKeys);
if (selectSuggestionKey !== SelectSuggestionKey.ENTER) {
this.keymapEventHandler.push(this.scope.register(SelectSuggestionKey.ENTER.keyBind.modifiers, SelectSuggestionKey.ENTER.keyBind.key, () => {
this.close();
return true;
}));
}
if (selectSuggestionKey !== SelectSuggestionKey.TAB) {
this.keymapEventHandler.push(this.scope.register(SelectSuggestionKey.TAB.keyBind.modifiers, SelectSuggestionKey.TAB.keyBind.key, () => {
this.close();
return true;
}));
}
this.keymapEventHandler.push(this.scope.register(selectSuggestionKey.keyBind.modifiers, selectSuggestionKey.keyBind.key, () => {
this.suggestions.useSelectedItem({});
return false;
}));
this.scope.keys.find((x) => x.key === "Escape").func = () => {
this.close();
return this.settings.propagateEsc;
};
const cycleThroughSuggestionsKeys = CycleThroughSuggestionsKeys.fromName(this.settings.additionalCycleThroughSuggestionsKeys);
if (cycleThroughSuggestionsKeys !== CycleThroughSuggestionsKeys.NONE) {
if (cycleThroughSuggestionsKeys === CycleThroughSuggestionsKeys.TAB) {
this.scope.unregister(this.scope.keys.find((x) => x.modifiers === "" && x.key === "Tab"));
}
this.keymapEventHandler.push(this.scope.register(cycleThroughSuggestionsKeys.nextKey.modifiers, cycleThroughSuggestionsKeys.nextKey.key, () => {
this.suggestions.setSelectedItem(this.suggestions.selectedItem + 1, true);
return false;
}), this.scope.register(cycleThroughSuggestionsKeys.previousKey.modifiers, cycleThroughSuggestionsKeys.previousKey.key, () => {
this.suggestions.setSelectedItem(this.suggestions.selectedItem - 1, true);
return false;
}));
}
const openSourceFileKey = OpenSourceFileKeys.fromName(this.settings.openSourceFileKey);
if (openSourceFileKey !== OpenSourceFileKeys.NONE) {
this.keymapEventHandler.push(this.scope.register(openSourceFileKey.keyBind.modifiers, openSourceFileKey.keyBind.key, () => {
const item = this.suggestions.values[this.suggestions.selectedItem];
if (item.type !== "currentVault" &&
item.type !== "internalLink" &&
item.type !== "frontMatter") {
return false;
}
const markdownFile = this.appHelper.getMarkdownFileByPath(item.createdPath);
if (!markdownFile) {
// noinspection ObjectAllocationIgnored
new obsidian.Notice(`Can't open ${item.createdPath}`);
return false;
}
this.appHelper.openMarkdownFile(markdownFile, true);
return false;
}));
}
}
refreshCurrentFileTokens() {
return __awaiter(this, void 0, void 0, function* () {
const start = performance.now();
this.statusBar.setCurrentFileIndexing();
if (!this.settings.enableCurrentFileComplement) {
this.statusBar.setCurrentFileDisabled();
this.currentFileWordProvider.clearWords();
this.showDebugLog(() => buildLogMessage("👢 Skip: Index current file tokens", performance.now() - start));
return;
}
yield this.currentFileWordProvider.refreshWords(this.settings.onlyComplementEnglishOnCurrentFileComplement);
this.statusBar.setCurrentFileIndexed(this.currentFileWordProvider.wordCount);
this.showDebugLog(() => buildLogMessage("Index current file tokens", performance.now() - start));
});
}
refreshCurrentVaultTokens() {
return __awaiter(this, void 0, void 0, function* () {
const start = performance.now();
this.statusBar.setCurrentVaultIndexing();
if (!this.settings.enableCurrentVaultComplement) {
this.statusBar.setCurrentVaultDisabled();
this.currentVaultWordProvider.clearWords();
this.showDebugLog(() => buildLogMessage("👢 Skip: Index current vault tokens", performance.now() - start));
return;
}
yield this.currentVaultWordProvider.refreshWords();
this.statusBar.setCurrentVaultIndexed(this.currentVaultWordProvider.wordCount);
this.showDebugLog(() => buildLogMessage("Index current vault tokens", performance.now() - start));
});
}
refreshCustomDictionaryTokens() {
return __awaiter(this, void 0, void 0, function* () {
const start = performance.now();
this.statusBar.setCustomDictionaryIndexing();
if (!this.settings.enableCustomDictionaryComplement) {
this.statusBar.setCustomDictionaryDisabled();
this.customDictionaryWordProvider.clearWords();
this.showDebugLog(() => buildLogMessage("👢Skip: Index custom dictionary tokens", performance.now() - start));
return;
}
yield this.customDictionaryWordProvider.refreshCustomWords({
regexp: this.settings.customDictionaryWordRegexPattern,
delimiterForHide: this.settings.delimiterToHideSuggestion || undefined,
delimiterForDisplay: this.settings.delimiterToDivideSuggestionsForDisplayFromInsertion ||
undefined,
caretSymbol: this.settings.caretLocationSymbolAfterComplement || undefined,
});
this.statusBar.setCustomDictionaryIndexed(this.customDictionaryWordProvider.wordCount);
this.showDebugLog(() => buildLogMessage("Index custom dictionary tokens", performance.now() - start));
});
}
refreshInternalLinkTokens() {
const start = performance.now();
this.statusBar.setInternalLinkIndexing();
if (!this.settings.enableInternalLinkComplement) {
this.statusBar.setInternalLinkDisabled();
this.internalLinkWordProvider.clearWords();
this.showDebugLog(() => buildLogMessage("👢Skip: Index internal link tokens", performance.now() - start));
return;
}
this.internalLinkWordProvider.refreshWords(this.settings.suggestInternalLinkWithAlias, this.excludeInternalLinkPrefixPathPatterns);
this.statusBar.setInternalLinkIndexed(this.internalLinkWordProvider.wordCount);
this.showDebugLog(() => buildLogMessage("Index internal link tokens", performance.now() - start));
}
refreshFrontMatterTokens() {
const start = performance.now();
this.statusBar.setFrontMatterIndexing();
if (!this.settings.enableFrontMatterComplement) {
this.statusBar.setFrontMatterDisabled();
this.frontMatterWordProvider.clearWords();
this.showDebugLog(() => buildLogMessage("👢Skip: Index front matter tokens", performance.now() - start));
return;
}
this.frontMatterWordProvider.refreshWords();
this.statusBar.setFrontMatterIndexed(this.frontMatterWordProvider.wordCount);
this.showDebugLog(() => buildLogMessage("Index front matter tokens", performance.now() - start));
}
updateFrontMatterTokenIndex(file) {
const start = performance.now();
if (!this.settings.enableFrontMatterComplement) {
this.showDebugLog(() => buildLogMessage("👢Skip: Update front matter token index", performance.now() - start));
return;
}
this.frontMatterWordProvider.updateWordIndex(file);
this.showDebugLog(() => buildLogMessage("Update front matter token index", performance.now() - start));
}
updateFrontMatterToken() {
const start = performance.now();
if (!this.settings.enableFrontMatterComplement) {
this.showDebugLog(() => buildLogMessage("👢Skip: Update front matter token", performance.now() - start));
return;
}
this.frontMatterWordProvider.updateWords();
this.statusBar.setFrontMatterIndexed(this.frontMatterWordProvider.wordCount);
this.showDebugLog(() => buildLogMessage("Update front matter token", performance.now() - start));
}
onTrigger(cursor, editor, file) {
var _a, _b, _c, _d, _e, _f;
const start = performance.now();
if (!this.settings.complementAutomatically &&
!this.isOpen &&
!this.runManually) {
this.showDebugLog(() => "Don't show suggestions");
return null;
}
if (this.settings.disableSuggestionsDuringImeOn &&
this.appHelper.isIMEOn() &&
!this.runManually) {
this.showDebugLog(() => "Don't show suggestions for IME");
return null;
}
const cl = this.appHelper.getCurrentLine(editor);
if (this.previousCurrentLine === cl && !this.runManually) {
this.previousCurrentLine = cl;
this.showDebugLog(() => "Don't show suggestions because there are no changes");
return null;
}
this.previousCurrentLine = cl;
const currentLineUntilCursor = this.appHelper.getCurrentLineUntilCursor(editor);
if (currentLineUntilCursor.startsWith("---")) {
this.showDebugLog(() => "Don't show suggestions because it supposes front matter or horizontal line");
return null;
}
if (currentLineUntilCursor.startsWith("~~~") ||
currentLineUntilCursor.startsWith("```")) {
this.showDebugLog(() => "Don't show suggestions because it supposes front code block");
return null;
}
const tokens = this.tokenizer.tokenize(currentLineUntilCursor, true);
this.showDebugLog(() => `[onTrigger] tokens is ${tokens}`);
const tokenized = this.tokenizer.recursiveTokenize(currentLineUntilCursor);
const currentTokens = tokenized.slice(tokenized.length > this.settings.maxNumberOfWordsAsPhrase
? tokenized.length - this.settings.maxNumberOfWordsAsPhrase
: 0);
this.showDebugLog(() => `[onTrigger] currentTokens is ${JSON.stringify(currentTokens)}`);
const currentToken = (_a = currentTokens[0]) === null || _a === void 0 ? void 0 : _a.word;
this.showDebugLog(() => `[onTrigger] currentToken is ${currentToken}`);
if (!currentToken) {
this.runManually = false;
this.showDebugLog(() => `Don't show suggestions because currentToken is empty`);
return null;
}
const currentTokenSeparatedWhiteSpace = (_b = currentLineUntilCursor.split(" ").last()) !== null && _b !== void 0 ? _b : "";
if (new RegExp(`^[${this.settings.firstCharactersDisableSuggestions}]`).test(currentTokenSeparatedWhiteSpace)) {
this.runManually = false;
this.showDebugLog(() => `Don't show suggestions for avoiding to conflict with the other commands.`);
return null;
}
if (currentToken.length === 1 &&
Boolean(currentToken.match(this.tokenizer.getTrimPattern()))) {
this.runManually = false;
this.showDebugLog(() => `Don't show suggestions because currentToken is TRIM_PATTERN`);
return null;
}
const currentFrontMatter = this.settings.enableFrontMatterComplement
? this.appHelper.getCurrentFrontMatter()
: null;
this.showDebugLog(() => `Current front matter is ${currentFrontMatter}`);
if (!this.runManually && !currentFrontMatter) {
if (currentToken.length < this.minNumberTriggered) {
this.showDebugLog(() => "Don't show suggestions because currentToken is less than minNumberTriggered option");
return null;
}
if (this.tokenizer.shouldIgnore(currentToken)) {
this.showDebugLog(() => "Don't show suggestions because currentToken should ignored");
return null;
}
}
this.showDebugLog(() => buildLogMessage("onTrigger", performance.now() - start));
this.runManually = false;
// Hack implementation for Front matter complement
if (currentFrontMatter && ((_c = currentTokens.last()) === null || _c === void 0 ? void 0 : _c.word.match(/[^ ] $/))) {
currentTokens.push({ word: "", offset: currentLineUntilCursor.length });
}
// For multi-word completion
this.contextStartCh = cursor.ch - currentToken.length;
return {
start: {
ch: cursor.ch - ((_f = (_e = (_d = currentTokens.last()) === null || _d === void 0 ? void 0 : _d.word) === null || _e === void 0 ? void 0 : _e.length) !== null && _f !== void 0 ? _f : 0),
line: cursor.line,
},
end: cursor,
query: JSON.stringify({
currentFrontMatter,
queries: currentTokens.map((x) => (Object.assign(Object.assign({}, x), { offset: x.offset - currentTokens[0].offset }))),
}),
};
}
getSuggestions(context) {
return new Promise((resolve) => {
this.debounceGetSuggestions(context, (words) => {
resolve(words);
});
});
}
renderSuggestion(word, el) {
const base = createDiv();
let text = word.value;
if (word.type === "customDictionary" &&
word.insertedText &&
this.settings.displayedTextSuffix) {
text += this.settings.displayedTextSuffix;
}
base.createDiv({
text,
cls: word.type === "internalLink" && word.aliasMeta
? "various-complements__suggestion-item__content__alias"
: undefined,
});
const description = this.descriptionOnSuggestion.toDisplay(word);
if (description) {
base.createDiv({
cls: "various-complements__suggestion-item__description",
text: `${description}`,
});
}
el.appendChild(base);
el.addClass("various-complements__suggestion-item");
switch (word.type) {
case "currentFile":
el.addClass("various-complements__suggestion-item__current-file");
break;
case "currentVault":
el.addClass("various-complements__suggestion-item__current-vault");
break;
case "customDictionary":
el.addClass("various-complements__suggestion-item__custom-dictionary");
break;
case "internalLink":
el.addClass("various-complements__suggestion-item__internal-link");
if (word.phantom) {
el.addClass("various-complements__suggestion-item__phantom");
}
break;
case "frontMatter":
el.addClass("various-complements__suggestion-item__front-matter");
break;
}
}
selectSuggestion(word, evt) {
var _a, _b;
if (!this.context) {
return;
}
let insertedText = word.value;
if (word.type === "internalLink") {
insertedText =
this.settings.suggestInternalLinkWithAlias && word.aliasMeta
? `[[${word.aliasMeta.origin}|${word.value}]]`
: `[[${word.value}]]`;
}
if (word.type === "frontMatter" &&
this.settings.insertCommaAfterFrontMatterCompletion) {
insertedText = `${insertedText}, `;
}
else {
if (this.settings.insertAfterCompletion &&
!(word.type === "customDictionary" && word.ignoreSpaceAfterCompletion)) {
insertedText = `${insertedText} `;
}
}
let positionToMove = -1;
if (word.type === "customDictionary") {
if (word.insertedText) {
insertedText = word.insertedText;
}
const caret = word.caretSymbol;
if (caret) {
positionToMove = insertedText.indexOf(caret);
insertedText = insertedText.replace(caret, "");
}
}
const editor = this.context.editor;
editor.replaceRange(insertedText, Object.assign(Object.assign({}, this.context.start), { ch: this.contextStartCh + word.offset }), this.context.end);
if (positionToMove !== -1) {
editor.setCursor(editor.offsetToPos(editor.posToOffset(editor.getCursor()) -
insertedText.length +
positionToMove));
}
// The workaround of strange behavior for that cursor doesn't move after completion only if it doesn't input any word.
if (this.appHelper.equalsAsEditorPostion(this.context.start, this.context.end)) {
editor.setCursor(editor.offsetToPos(editor.posToOffset(editor.getCursor()) + insertedText.length));
}
(_a = this.selectionHistoryStorage) === null || _a === void 0 ? void 0 : _a.increment(word);
if (this.settings.showLogAboutPerformanceInConsole) {
console.log("--- history ---");
console.log((_b = this.selectionHistoryStorage) === null || _b === void 0 ? void 0 : _b.data);
}
this.close();
this.debounceClose();
}
showDebugLog(toMessage) {
if (this.settings.showLogAboutPerformanceInConsole) {
console.log(toMessage());
}
}
}
const DEFAULT_SETTINGS = {
// general
strategy: "default",
matchStrategy: "prefix",
maxNumberOfSuggestions: 5,
maxNumberOfWordsAsPhrase: 3,
minNumberOfCharactersTriggered: 0,
minNumberOfWordsTriggeredPhrase: 1,
complementAutomatically: true,
delayMilliSeconds: 0,
disableSuggestionsDuringImeOn: false,
insertAfterCompletion: true,
firstCharactersDisableSuggestions: ":/^",
// appearance
showMatchStrategy: true,
showIndexingStatus: true,
descriptionOnSuggestion: "Short",
// key customization
selectSuggestionKeys: "Enter",
additionalCycleThroughSuggestionsKeys: "None",
openSourceFileKey: "None",
propagateEsc: false,
// current file complement
enableCurrentFileComplement: true,
onlyComplementEnglishOnCurrentFileComplement: false,
// current vault complement
enableCurrentVaultComplement: false,
includeCurrentVaultPathPrefixPatterns: "",
excludeCurrentVaultPathPrefixPatterns: "",
includeCurrentVaultOnlyFilesUnderCurrentDirectory: false,
// custom dictionary complement
enableCustomDictionaryComplement: false,
customDictionaryPaths: `https://raw.githubusercontent.com/first20hours/google-10000-english/master/google-10000-english-no-swears.txt`,
columnDelimiter: "Tab",
customDictionaryWordRegexPattern: "",
delimiterToHideSuggestion: "",
delimiterToDivideSuggestionsForDisplayFromInsertion: "",
caretLocationSymbolAfterComplement: "",
displayedTextSuffix: " => ...",
// internal link complement
enableInternalLinkComplement: true,
suggestInternalLinkWithAlias: false,
excludeInternalLinkPathPrefixPatterns: "",
// front matter complement
enableFrontMatterComplement: true,
frontMatterComplementMatchStrategy: "inherit",
insertCommaAfterFrontMatterCompletion: false,
// debug
showLogAboutPerformanceInConsole: false,
// others
selectionHistoryTree: {},
};
class VariousComplementsSettingTab extends obsidian.PluginSettingTab {
constructor(app, plugin) {
super(app, plugin);
this.plugin = plugin;
}
display() {
let { containerEl } = this;
containerEl.empty();
containerEl.createEl("h2", { text: "Various Complements - Settings" });
this.addMainSettings(containerEl);
this.addAppearanceSettings(containerEl);
this.addKeyCustomizationSettings(containerEl);
this.addCurrentFileComplementSettings(containerEl);
this.addCurrentVaultComplementSettings(containerEl);
this.addCustomDictionaryComplementSettings(containerEl);
this.addInternalLinkComplementSettings(containerEl);
this.addFrontMatterComplementSettings(containerEl);
this.addDebugSettings(containerEl);
}
addMainSettings(containerEl) {
containerEl.createEl("h3", { text: "Main" });
new obsidian.Setting(containerEl).setName("Strategy").addDropdown((tc) => tc
.addOptions(mirrorMap(TokenizeStrategy.values(), (x) => x.name))
.setValue(this.plugin.settings.strategy)
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.strategy = value;
yield this.plugin.saveSettings({
currentFile: true,
currentVault: true,
});
})));
new obsidian.Setting(containerEl).setName("Match strategy").addDropdown((tc) => tc
.addOptions(mirrorMap(MatchStrategy.values(), (x) => x.name))
.setValue(this.plugin.settings.matchStrategy)
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.matchStrategy = value;
yield this.plugin.saveSettings();
this.display();
})));
if (this.plugin.settings.matchStrategy === MatchStrategy.PARTIAL.name) {
containerEl.createEl("div", {
text: "⚠ `partial` is more than 10 times slower than `prefix`",
cls: "various-complements__settings__warning",
});
}
new obsidian.Setting(containerEl)
.setName("Max number of suggestions")
.addSlider((sc) => sc
.setLimits(1, 255, 1)
.setValue(this.plugin.settings.maxNumberOfSuggestions)
.setDynamicTooltip()
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.maxNumberOfSuggestions = value;
yield this.plugin.saveSettings();
})));
new obsidian.Setting(containerEl)
.setName("Max number of words as a phrase")
.setDesc(`[⚠Warning] It makes slower more than N times (N is set value)`)
.addSlider((sc) => sc
.setLimits(1, 10, 1)
.setValue(this.plugin.settings.maxNumberOfWordsAsPhrase)
.setDynamicTooltip()
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.maxNumberOfWordsAsPhrase = value;
yield this.plugin.saveSettings();
})));
new obsidian.Setting(containerEl)
.setName("Min number of characters for trigger")
.setDesc("It uses a default value of Strategy if set 0.")
.addSlider((sc) => sc
.setLimits(0, 10, 1)
.setValue(this.plugin.settings.minNumberOfCharactersTriggered)
.setDynamicTooltip()
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.minNumberOfCharactersTriggered = value;
yield this.plugin.saveSettings();
})));
new obsidian.Setting(containerEl)
.setName("Min number of words for trigger")
.addSlider((sc) => sc
.setLimits(1, 10, 1)
.setValue(this.plugin.settings.minNumberOfWordsTriggeredPhrase)
.setDynamicTooltip()
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.minNumberOfWordsTriggeredPhrase = value;
yield this.plugin.saveSettings();
})));
new obsidian.Setting(containerEl)
.setName("Complement automatically")
.addToggle((tc) => {
tc.setValue(this.plugin.settings.complementAutomatically).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.complementAutomatically = value;
yield this.plugin.saveSettings();
}));
});
new obsidian.Setting(containerEl)
.setName("Delay milli-seconds for trigger")
.addSlider((sc) => sc
.setLimits(0, 1000, 10)
.setValue(this.plugin.settings.delayMilliSeconds)
.setDynamicTooltip()
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.delayMilliSeconds = value;
yield this.plugin.saveSettings();
})));
new obsidian.Setting(containerEl)
.setName("Disable suggestions during IME on")
.addToggle((tc) => {
tc.setValue(this.plugin.settings.disableSuggestionsDuringImeOn).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.disableSuggestionsDuringImeOn = value;
yield this.plugin.saveSettings();
}));
});
new obsidian.Setting(containerEl)
.setName("Insert space after completion")
.addToggle((tc) => {
tc.setValue(this.plugin.settings.insertAfterCompletion).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.insertAfterCompletion = value;
yield this.plugin.saveSettings();
}));
});
new obsidian.Setting(containerEl)
.setName("First characters to disable suggestions")
.addText((cb) => {
cb.setValue(this.plugin.settings.firstCharactersDisableSuggestions).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.firstCharactersDisableSuggestions = value;
yield this.plugin.saveSettings();
}));
});
}
addAppearanceSettings(containerEl) {
containerEl.createEl("h3", { text: "Appearance" });
new obsidian.Setting(containerEl)
.setName("Show Match strategy")
.setDesc("Show Match strategy at the status bar. Changing this option requires a restart to take effect.")
.addToggle((tc) => {
tc.setValue(this.plugin.settings.showMatchStrategy).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.showMatchStrategy = value;
yield this.plugin.saveSettings();
}));
});
new obsidian.Setting(containerEl)
.setName("Show Indexing status")
.setDesc("Show indexing status at the status bar. Changing this option requires a restart to take effect.")
.addToggle((tc) => {
tc.setValue(this.plugin.settings.showIndexingStatus).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.showIndexingStatus = value;
yield this.plugin.saveSettings();
}));
});
new obsidian.Setting(containerEl)
.setName("Description on a suggestion")
.addDropdown((tc) => tc
.addOptions(mirrorMap(DescriptionOnSuggestion.values(), (x) => x.name))
.setValue(this.plugin.settings.descriptionOnSuggestion)
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.descriptionOnSuggestion = value;
yield this.plugin.saveSettings();
})));
}
addKeyCustomizationSettings(containerEl) {
containerEl.createEl("h3", { text: "Key customization" });
new obsidian.Setting(containerEl)
.setName("Select a suggestion key")
.addDropdown((tc) => tc
.addOptions(mirrorMap(SelectSuggestionKey.values(), (x) => x.name))
.setValue(this.plugin.settings.selectSuggestionKeys)
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.selectSuggestionKeys = value;
yield this.plugin.saveSettings();
})));
new obsidian.Setting(containerEl)
.setName("Additional cycle through suggestions keys")
.addDropdown((tc) => tc
.addOptions(mirrorMap(CycleThroughSuggestionsKeys.values(), (x) => x.name))
.setValue(this.plugin.settings.additionalCycleThroughSuggestionsKeys)
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.additionalCycleThroughSuggestionsKeys = value;
yield this.plugin.saveSettings();
})));
new obsidian.Setting(containerEl).setName("Open source file key").addDropdown((tc) => tc
.addOptions(mirrorMap(OpenSourceFileKeys.values(), (x) => x.name))
.setValue(this.plugin.settings.openSourceFileKey)
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.openSourceFileKey = value;
yield this.plugin.saveSettings();
})));
new obsidian.Setting(containerEl)
.setName("Propagate ESC")
.setDesc("It is handy if you use Vim mode because you can switch to Normal mode by one ESC, whether it shows suggestions or not.")
.addToggle((tc) => {
tc.setValue(this.plugin.settings.propagateEsc).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.propagateEsc = value;
yield this.plugin.saveSettings();
}));
});
}
addCurrentFileComplementSettings(containerEl) {
containerEl.createEl("h3", {
text: "Current file complement",
cls: "various-complements__settings__header various-complements__settings__header__current-file",
});
new obsidian.Setting(containerEl)
.setName("Enable Current file complement")
.addToggle((tc) => {
tc.setValue(this.plugin.settings.enableCurrentFileComplement).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.enableCurrentFileComplement = value;
yield this.plugin.saveSettings({ currentFile: true });
this.display();
}));
});
if (this.plugin.settings.enableCurrentFileComplement) {
new obsidian.Setting(containerEl)
.setName("Only complement English on current file complement")
.addToggle((tc) => {
tc.setValue(this.plugin.settings.onlyComplementEnglishOnCurrentFileComplement).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.onlyComplementEnglishOnCurrentFileComplement =
value;
yield this.plugin.saveSettings({ currentFile: true });
}));
});
}
}
addCurrentVaultComplementSettings(containerEl) {
containerEl.createEl("h3", {
text: "Current vault complement",
cls: "various-complements__settings__header various-complements__settings__header__current-vault",
});
new obsidian.Setting(containerEl)
.setName("Enable Current vault complement")
.addToggle((tc) => {
tc.setValue(this.plugin.settings.enableCurrentVaultComplement).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.enableCurrentVaultComplement = value;
yield this.plugin.saveSettings({ currentVault: true });
this.display();
}));
});
if (this.plugin.settings.enableCurrentVaultComplement) {
new obsidian.Setting(containerEl)
.setName("Include prefix path patterns")
.setDesc("Prefix match path patterns to include files.")
.addTextArea((tac) => {
const el = tac
.setValue(this.plugin.settings.includeCurrentVaultPathPrefixPatterns)
.setPlaceholder("Private/")
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.includeCurrentVaultPathPrefixPatterns =
value;
yield this.plugin.saveSettings();
}));
el.inputEl.className =
"various-complements__settings__text-area-path";
return el;
});
new obsidian.Setting(containerEl)
.setName("Exclude prefix path patterns")
.setDesc("Prefix match path patterns to exclude files.")
.addTextArea((tac) => {
const el = tac
.setValue(this.plugin.settings.excludeCurrentVaultPathPrefixPatterns)
.setPlaceholder("Private/")
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.excludeCurrentVaultPathPrefixPatterns =
value;
yield this.plugin.saveSettings();
}));
el.inputEl.className =
"various-complements__settings__text-area-path";
return el;
});
new obsidian.Setting(containerEl)
.setName("Include only files under current directory")
.addToggle((tc) => {
tc.setValue(this.plugin.settings
.includeCurrentVaultOnlyFilesUnderCurrentDirectory).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.includeCurrentVaultOnlyFilesUnderCurrentDirectory =
value;
yield this.plugin.saveSettings();
}));
});
}
}
addCustomDictionaryComplementSettings(containerEl) {
containerEl.createEl("h3", {
text: "Custom dictionary complement",
cls: "various-complements__settings__header various-complements__settings__header__custom-dictionary",
});
new obsidian.Setting(containerEl)
.setName("Enable Custom dictionary complement")
.addToggle((tc) => {
tc.setValue(this.plugin.settings.enableCustomDictionaryComplement).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.enableCustomDictionaryComplement = value;
yield this.plugin.saveSettings({ customDictionary: true });
this.display();
}));
});
if (this.plugin.settings.enableCustomDictionaryComplement) {
new obsidian.Setting(containerEl)
.setName("Custom dictionary paths")
.setDesc("Specify either a relative path from Vault root or URL for each line.")
.addTextArea((tac) => {
const el = tac
.setValue(this.plugin.settings.customDictionaryPaths)
.setPlaceholder("dictionary.md")
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.customDictionaryPaths = value;
yield this.plugin.saveSettings();
}));
el.inputEl.className =
"various-complements__settings__text-area-path";
return el;
});
new obsidian.Setting(containerEl).setName("Column delimiter").addDropdown((tc) => tc
.addOptions(mirrorMap(ColumnDelimiter.values(), (x) => x.name))
.setValue(this.plugin.settings.columnDelimiter)
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.columnDelimiter = value;
yield this.plugin.saveSettings();
})));
new obsidian.Setting(containerEl)
.setName("Word regex pattern")
.setDesc("Only load words that match the regular expression pattern.")
.addText((cb) => {
cb.setValue(this.plugin.settings.customDictionaryWordRegexPattern).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.customDictionaryWordRegexPattern = value;
yield this.plugin.saveSettings();
}));
});
new obsidian.Setting(containerEl)
.setName("Delimiter to hide a suggestion")
.setDesc("If set ';;;', 'abcd;;;efg' is shown as 'abcd' on suggestions, but completes to 'abcdefg'.")
.addText((cb) => {
cb.setValue(this.plugin.settings.delimiterToHideSuggestion).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.delimiterToHideSuggestion = value;
yield this.plugin.saveSettings();
}));
});
new obsidian.Setting(containerEl)
.setName("Delimiter to divide suggestions for display from ones for insertion")
.setDesc("If set ' >>> ', 'displayed >>> inserted' is shown as 'displayed' on suggestions, but completes to 'inserted'.")
.addText((cb) => {
cb.setValue(this.plugin.settings
.delimiterToDivideSuggestionsForDisplayFromInsertion).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.delimiterToDivideSuggestionsForDisplayFromInsertion =
value;
yield this.plugin.saveSettings();
}));
});
new obsidian.Setting(containerEl)
.setName("Caret location symbol after complement")
.setDesc("If set '<CARET>' and there is '<li><CARET></li>' in custom dictionary, it complements '<li></li>' and move a caret where between '<li>' and `</li>`.")
.addText((cb) => {
cb.setValue(this.plugin.settings.caretLocationSymbolAfterComplement).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.caretLocationSymbolAfterComplement = value;
yield this.plugin.saveSettings();
}));
});
new obsidian.Setting(containerEl)
.setName("Displayed text suffix")
.setDesc("It shows as a suffix of displayed text if there is a difference between displayed and inserted")
.addText((cb) => {
cb.setValue(this.plugin.settings.displayedTextSuffix).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.displayedTextSuffix = value;
yield this.plugin.saveSettings();
}));
});
}
}
addInternalLinkComplementSettings(containerEl) {
containerEl.createEl("h3", {
text: "Internal link complement",
cls: "various-complements__settings__header various-complements__settings__header__internal-link",
});
new obsidian.Setting(containerEl)
.setName("Enable Internal link complement")
.addToggle((tc) => {
tc.setValue(this.plugin.settings.enableInternalLinkComplement).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.enableInternalLinkComplement = value;
yield this.plugin.saveSettings({ internalLink: true });
this.display();
}));
});
if (this.plugin.settings.enableInternalLinkComplement) {
new obsidian.Setting(containerEl)
.setName("Suggest with an alias")
.addToggle((tc) => {
tc.setValue(this.plugin.settings.suggestInternalLinkWithAlias).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.suggestInternalLinkWithAlias = value;
yield this.plugin.saveSettings({ internalLink: true });
}));
});
new obsidian.Setting(containerEl)
.setName("Exclude prefix path patterns")
.setDesc("Prefix match path patterns to exclude files.")
.addTextArea((tac) => {
const el = tac
.setValue(this.plugin.settings.excludeInternalLinkPathPrefixPatterns)
.setPlaceholder("Private/")
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.excludeInternalLinkPathPrefixPatterns =
value;
yield this.plugin.saveSettings();
}));
el.inputEl.className =
"various-complements__settings__text-area-path";
return el;
});
}
}
addFrontMatterComplementSettings(containerEl) {
containerEl.createEl("h3", {
text: "Front matter complement",
cls: "various-complements__settings__header various-complements__settings__header__front-matter",
});
new obsidian.Setting(containerEl)
.setName("Enable Front matter complement")
.addToggle((tc) => {
tc.setValue(this.plugin.settings.enableFrontMatterComplement).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.enableFrontMatterComplement = value;
yield this.plugin.saveSettings({ frontMatter: true });
this.display();
}));
});
if (this.plugin.settings.enableFrontMatterComplement) {
new obsidian.Setting(containerEl)
.setName("Match strategy in the front matter")
.addDropdown((tc) => tc
.addOptions(mirrorMap(SpecificMatchStrategy.values(), (x) => x.name))
.setValue(this.plugin.settings.frontMatterComplementMatchStrategy)
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.frontMatterComplementMatchStrategy = value;
yield this.plugin.saveSettings();
})));
new obsidian.Setting(containerEl)
.setName("Insert comma after completion")
.addToggle((tc) => {
tc.setValue(this.plugin.settings.insertCommaAfterFrontMatterCompletion).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.insertCommaAfterFrontMatterCompletion = value;
yield this.plugin.saveSettings();
}));
});
}
}
addDebugSettings(containerEl) {
containerEl.createEl("h3", { text: "Debug" });
new obsidian.Setting(containerEl)
.setName("Show log about performance in a console")
.addToggle((tc) => {
tc.setValue(this.plugin.settings.showLogAboutPerformanceInConsole).onChange((value) => __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.showLogAboutPerformanceInConsole = value;
yield this.plugin.saveSettings();
}));
});
}
toggleMatchStrategy() {
return __awaiter(this, void 0, void 0, function* () {
switch (this.plugin.settings.matchStrategy) {
case "prefix":
this.plugin.settings.matchStrategy = "partial";
break;
case "partial":
this.plugin.settings.matchStrategy = "prefix";
break;
default:
// noinspection ObjectAllocationIgnored
new obsidian.Notice("⚠Unexpected error");
}
yield this.plugin.saveSettings();
});
}
toggleComplementAutomatically() {
return __awaiter(this, void 0, void 0, function* () {
this.plugin.settings.complementAutomatically =
!this.plugin.settings.complementAutomatically;
yield this.plugin.saveSettings();
});
}
ensureCustomDictionaryPath(path, state) {
return __awaiter(this, void 0, void 0, function* () {
const paths = this.plugin.settings.customDictionaryPaths.split("\n");
const exists = paths.some((x) => x === path);
if ((exists && state === "present") || (!exists && state === "absent")) {
return false;
}
const newPaths = state === "present" ? [...paths, path] : paths.filter((x) => x !== path);
this.plugin.settings.customDictionaryPaths = newPaths.join("\n");
yield this.plugin.saveSettings({ customDictionary: true });
return true;
});
}
getPluginSettingsAsJsonString() {
return JSON.stringify({
version: this.plugin.manifest.version,
mobile: this.app.isMobile,
settings: Object.assign(Object.assign({}, this.plugin.settings), { selectionHistoryTree: null }),
}, null, 4);
}
}
class ProviderStatusBar {
constructor(currentFile, currentVault, customDictionary, internalLink, frontMatter, matchStrategy) {
this.currentFile = currentFile;
this.currentVault = currentVault;
this.customDictionary = customDictionary;
this.internalLink = internalLink;
this.frontMatter = frontMatter;
this.matchStrategy = matchStrategy;
}
static new(statusBar, showMatchStrategy, showIndexingStatus) {
const currentFile = showIndexingStatus
? statusBar.createEl("span", {
text: "---",
cls: "various-complements__footer various-complements__footer__current-file",
})
: null;
const currentVault = showIndexingStatus
? statusBar.createEl("span", {
text: "---",
cls: "various-complements__footer various-complements__footer__current-vault",
})
: null;
const customDictionary = showIndexingStatus
? statusBar.createEl("span", {
text: "---",
cls: "various-complements__footer various-complements__footer__custom-dictionary",
})
: null;
const internalLink = showIndexingStatus
? statusBar.createEl("span", {
text: "---",
cls: "various-complements__footer various-complements__footer__internal-link",
})
: null;
const frontMatter = showIndexingStatus
? statusBar.createEl("span", {
text: "---",
cls: "various-complements__footer various-complements__footer__front-matter",
})
: null;
const matchStrategy = showMatchStrategy
? statusBar.createEl("span", {
text: "---",
cls: "various-complements__footer various-complements__footer__match-strategy",
})
: null;
return new ProviderStatusBar(currentFile, currentVault, customDictionary, internalLink, frontMatter, matchStrategy);
}
setOnClickStrategyListener(listener) {
var _a;
(_a = this.matchStrategy) === null || _a === void 0 ? void 0 : _a.addEventListener("click", listener);
}
setCurrentFileDisabled() {
var _a;
(_a = this.currentFile) === null || _a === void 0 ? void 0 : _a.setText("---");
}
setCurrentVaultDisabled() {
var _a;
(_a = this.currentVault) === null || _a === void 0 ? void 0 : _a.setText("---");
}
setCustomDictionaryDisabled() {
var _a;
(_a = this.customDictionary) === null || _a === void 0 ? void 0 : _a.setText("---");
}
setInternalLinkDisabled() {
var _a;
(_a = this.internalLink) === null || _a === void 0 ? void 0 : _a.setText("---");
}
setFrontMatterDisabled() {
var _a;
(_a = this.frontMatter) === null || _a === void 0 ? void 0 : _a.setText("---");
}
setCurrentFileIndexing() {
var _a;
(_a = this.currentFile) === null || _a === void 0 ? void 0 : _a.setText("indexing...");
}
setCurrentVaultIndexing() {
var _a;
(_a = this.currentVault) === null || _a === void 0 ? void 0 : _a.setText("indexing...");
}
setCustomDictionaryIndexing() {
var _a;
(_a = this.customDictionary) === null || _a === void 0 ? void 0 : _a.setText("indexing...");
}
setInternalLinkIndexing() {
var _a;
(_a = this.internalLink) === null || _a === void 0 ? void 0 : _a.setText("indexing...");
}
setFrontMatterIndexing() {
var _a;
(_a = this.frontMatter) === null || _a === void 0 ? void 0 : _a.setText("indexing...");
}
setCurrentFileIndexed(count) {
var _a;
(_a = this.currentFile) === null || _a === void 0 ? void 0 : _a.setText(String(count));
}
setCurrentVaultIndexed(count) {
var _a;
(_a = this.currentVault) === null || _a === void 0 ? void 0 : _a.setText(String(count));
}
setCustomDictionaryIndexed(count) {
var _a;
(_a = this.customDictionary) === null || _a === void 0 ? void 0 : _a.setText(String(count));
}
setInternalLinkIndexed(count) {
var _a;
(_a = this.internalLink) === null || _a === void 0 ? void 0 : _a.setText(String(count));
}
setFrontMatterIndexed(count) {
var _a;
(_a = this.frontMatter) === null || _a === void 0 ? void 0 : _a.setText(String(count));
}
setMatchStrategy(strategy) {
var _a;
(_a = this.matchStrategy) === null || _a === void 0 ? void 0 : _a.setText(strategy.name);
}
}
function noop() { }
function assign(tar, src) {
// @ts-ignore
for (const k in src)
tar[k] = src[k];
return tar;
}
function run(fn) {
return fn();
}
function blank_object() {
return Object.create(null);
}
function run_all(fns) {
fns.forEach(run);
}
function is_function(thing) {
return typeof thing === 'function';
}
function safe_not_equal(a, b) {
return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function');
}
function is_empty(obj) {
return Object.keys(obj).length === 0;
}
function create_slot(definition, ctx, $$scope, fn) {
if (definition) {
const slot_ctx = get_slot_context(definition, ctx, $$scope, fn);
return definition[0](slot_ctx);
}
}
function get_slot_context(definition, ctx, $$scope, fn) {
return definition[1] && fn
? assign($$scope.ctx.slice(), definition[1](fn(ctx)))
: $$scope.ctx;
}
function get_slot_changes(definition, $$scope, dirty, fn) {
if (definition[2] && fn) {
const lets = definition[2](fn(dirty));
if ($$scope.dirty === undefined) {
return lets;
}
if (typeof lets === 'object') {
const merged = [];
const len = Math.max($$scope.dirty.length, lets.length);
for (let i = 0; i < len; i += 1) {
merged[i] = $$scope.dirty[i] | lets[i];
}
return merged;
}
return $$scope.dirty | lets;
}
return $$scope.dirty;
}
function update_slot_base(slot, slot_definition, ctx, $$scope, slot_changes, get_slot_context_fn) {
if (slot_changes) {
const slot_context = get_slot_context(slot_definition, ctx, $$scope, get_slot_context_fn);
slot.p(slot_context, slot_changes);
}
}
function get_all_dirty_from_scope($$scope) {
if ($$scope.ctx.length > 32) {
const dirty = [];
const length = $$scope.ctx.length / 32;
for (let i = 0; i < length; i++) {
dirty[i] = -1;
}
return dirty;
}
return -1;
}
function exclude_internal_props(props) {
const result = {};
for (const k in props)
if (k[0] !== '$')
result[k] = props[k];
return result;
}
function compute_rest_props(props, keys) {
const rest = {};
keys = new Set(keys);
for (const k in props)
if (!keys.has(k) && k[0] !== '$')
rest[k] = props[k];
return rest;
}
function null_to_empty(value) {
return value == null ? '' : value;
}
function append(target, node) {
target.appendChild(node);
}
function append_styles(target, style_sheet_id, styles) {
const append_styles_to = get_root_for_style(target);
if (!append_styles_to.getElementById(style_sheet_id)) {
const style = element('style');
style.id = style_sheet_id;
style.textContent = styles;
append_stylesheet(append_styles_to, style);
}
}
function get_root_for_style(node) {
if (!node)
return document;
const root = node.getRootNode ? node.getRootNode() : node.ownerDocument;
if (root && root.host) {
return root;
}
return node.ownerDocument;
}
function append_stylesheet(node, style) {
append(node.head || node, style);
}
function insert(target, node, anchor) {
target.insertBefore(node, anchor || null);
}
function detach(node) {
node.parentNode.removeChild(node);
}
function destroy_each(iterations, detaching) {
for (let i = 0; i < iterations.length; i += 1) {
if (iterations[i])
iterations[i].d(detaching);
}
}
function element(name) {
return document.createElement(name);
}
function svg_element(name) {
return document.createElementNS('http://www.w3.org/2000/svg', name);
}
function text(data) {
return document.createTextNode(data);
}
function space() {
return text(' ');
}
function listen(node, event, handler, options) {
node.addEventListener(event, handler, options);
return () => node.removeEventListener(event, handler, options);
}
function attr(node, attribute, value) {
if (value == null)
node.removeAttribute(attribute);
else if (node.getAttribute(attribute) !== value)
node.setAttribute(attribute, value);
}
function set_svg_attributes(node, attributes) {
for (const key in attributes) {
attr(node, key, attributes[key]);
}
}
function children(element) {
return Array.from(element.childNodes);
}
function set_data(text, data) {
data = '' + data;
if (text.wholeText !== data)
text.data = data;
}
function set_input_value(input, value) {
input.value = value == null ? '' : value;
}
function set_style(node, key, value, important) {
if (value === null) {
node.style.removeProperty(key);
}
else {
node.style.setProperty(key, value, important ? 'important' : '');
}
}
function select_option(select, value) {
for (let i = 0; i < select.options.length; i += 1) {
const option = select.options[i];
if (option.__value === value) {
option.selected = true;
return;
}
}
select.selectedIndex = -1; // no option should be selected
}
function select_value(select) {
const selected_option = select.querySelector(':checked') || select.options[0];
return selected_option && selected_option.__value;
}
function toggle_class(element, name, toggle) {
element.classList[toggle ? 'add' : 'remove'](name);
}
function custom_event(type, detail, { bubbles = false, cancelable = false } = {}) {
const e = document.createEvent('CustomEvent');
e.initCustomEvent(type, bubbles, cancelable, detail);
return e;
}
let current_component;
function set_current_component(component) {
current_component = component;
}
function get_current_component() {
if (!current_component)
throw new Error('Function called outside component initialization');
return current_component;
}
function onMount(fn) {
get_current_component().$$.on_mount.push(fn);
}
function createEventDispatcher() {
const component = get_current_component();
return (type, detail, { cancelable = false } = {}) => {
const callbacks = component.$$.callbacks[type];
if (callbacks) {
// TODO are there situations where events could be dispatched
// in a server (non-DOM) environment?
const event = custom_event(type, detail, { cancelable });
callbacks.slice().forEach(fn => {
fn.call(component, event);
});
return !event.defaultPrevented;
}
return true;
};
}
const dirty_components = [];
const binding_callbacks = [];
const render_callbacks = [];
const flush_callbacks = [];
const resolved_promise = Promise.resolve();
let update_scheduled = false;
function schedule_update() {
if (!update_scheduled) {
update_scheduled = true;
resolved_promise.then(flush);
}
}
function add_render_callback(fn) {
render_callbacks.push(fn);
}
// flush() calls callbacks in this order:
// 1. All beforeUpdate callbacks, in order: parents before children
// 2. All bind:this callbacks, in reverse order: children before parents.
// 3. All afterUpdate callbacks, in order: parents before children. EXCEPT
// for afterUpdates called during the initial onMount, which are called in
// reverse order: children before parents.
// Since callbacks might update component values, which could trigger another
// call to flush(), the following steps guard against this:
// 1. During beforeUpdate, any updated components will be added to the
// dirty_components array and will cause a reentrant call to flush(). Because
// the flush index is kept outside the function, the reentrant call will pick
// up where the earlier call left off and go through all dirty components. The
// current_component value is saved and restored so that the reentrant call will
// not interfere with the "parent" flush() call.
// 2. bind:this callbacks cannot trigger new flush() calls.
// 3. During afterUpdate, any updated components will NOT have their afterUpdate
// callback called a second time; the seen_callbacks set, outside the flush()
// function, guarantees this behavior.
const seen_callbacks = new Set();
let flushidx = 0; // Do *not* move this inside the flush() function
function flush() {
const saved_component = current_component;
do {
// first, call beforeUpdate functions
// and update components
while (flushidx < dirty_components.length) {
const component = dirty_components[flushidx];
flushidx++;
set_current_component(component);
update(component.$$);
}
set_current_component(null);
dirty_components.length = 0;
flushidx = 0;
while (binding_callbacks.length)
binding_callbacks.pop()();
// then, once components are updated, call
// afterUpdate functions. This may cause
// subsequent updates...
for (let i = 0; i < render_callbacks.length; i += 1) {
const callback = render_callbacks[i];
if (!seen_callbacks.has(callback)) {
// ...so guard against infinite loops
seen_callbacks.add(callback);
callback();
}
}
render_callbacks.length = 0;
} while (dirty_components.length);
while (flush_callbacks.length) {
flush_callbacks.pop()();
}
update_scheduled = false;
seen_callbacks.clear();
set_current_component(saved_component);
}
function update($$) {
if ($$.fragment !== null) {
$$.update();
run_all($$.before_update);
const dirty = $$.dirty;
$$.dirty = [-1];
$$.fragment && $$.fragment.p($$.ctx, dirty);
$$.after_update.forEach(add_render_callback);
}
}
const outroing = new Set();
let outros;
function transition_in(block, local) {
if (block && block.i) {
outroing.delete(block);
block.i(local);
}
}
function transition_out(block, local, detach, callback) {
if (block && block.o) {
if (outroing.has(block))
return;
outroing.add(block);
outros.c.push(() => {
outroing.delete(block);
if (callback) {
if (detach)
block.d(1);
callback();
}
});
block.o(local);
}
}
function get_spread_update(levels, updates) {
const update = {};
const to_null_out = {};
const accounted_for = { $$scope: 1 };
let i = levels.length;
while (i--) {
const o = levels[i];
const n = updates[i];
if (n) {
for (const key in o) {
if (!(key in n))
to_null_out[key] = 1;
}
for (const key in n) {
if (!accounted_for[key]) {
update[key] = n[key];
accounted_for[key] = 1;
}
}
levels[i] = n;
}
else {
for (const key in o) {
accounted_for[key] = 1;
}
}
}
for (const key in to_null_out) {
if (!(key in update))
update[key] = undefined;
}
return update;
}
function create_component(block) {
block && block.c();
}
function mount_component(component, target, anchor, customElement) {
const { fragment, on_mount, on_destroy, after_update } = component.$$;
fragment && fragment.m(target, anchor);
if (!customElement) {
// onMount happens before the initial afterUpdate
add_render_callback(() => {
const new_on_destroy = on_mount.map(run).filter(is_function);
if (on_destroy) {
on_destroy.push(...new_on_destroy);
}
else {
// Edge case - component was destroyed immediately,
// most likely as a result of a binding initialising
run_all(new_on_destroy);
}
component.$$.on_mount = [];
});
}
after_update.forEach(add_render_callback);
}
function destroy_component(component, detaching) {
const $$ = component.$$;
if ($$.fragment !== null) {
run_all($$.on_destroy);
$$.fragment && $$.fragment.d(detaching);
// TODO null out other refs, including component.$$ (but need to
// preserve final state?)
$$.on_destroy = $$.fragment = null;
$$.ctx = [];
}
}
function make_dirty(component, i) {
if (component.$$.dirty[0] === -1) {
dirty_components.push(component);
schedule_update();
component.$$.dirty.fill(0);
}
component.$$.dirty[(i / 31) | 0] |= (1 << (i % 31));
}
function init(component, options, instance, create_fragment, not_equal, props, append_styles, dirty = [-1]) {
const parent_component = current_component;
set_current_component(component);
const $$ = component.$$ = {
fragment: null,
ctx: null,
// state
props,
update: noop,
not_equal,
bound: blank_object(),
// lifecycle
on_mount: [],
on_destroy: [],
on_disconnect: [],
before_update: [],
after_update: [],
context: new Map(options.context || (parent_component ? parent_component.$$.context : [])),
// everything else
callbacks: blank_object(),
dirty,
skip_bound: false,
root: options.target || parent_component.$$.root
};
append_styles && append_styles($$.root);
let ready = false;
$$.ctx = instance
? instance(component, options.props || {}, (i, ret, ...rest) => {
const value = rest.length ? rest[0] : ret;
if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) {
if (!$$.skip_bound && $$.bound[i])
$$.bound[i](value);
if (ready)
make_dirty(component, i);
}
return ret;
})
: [];
$$.update();
ready = true;
run_all($$.before_update);
// `false` as a special case of no DOM component
$$.fragment = create_fragment ? create_fragment($$.ctx) : false;
if (options.target) {
if (options.hydrate) {
const nodes = children(options.target);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
$$.fragment && $$.fragment.l(nodes);
nodes.forEach(detach);
}
else {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
$$.fragment && $$.fragment.c();
}
if (options.intro)
transition_in(component.$$.fragment);
mount_component(component, options.target, options.anchor, options.customElement);
flush();
}
set_current_component(parent_component);
}
/**
* Base class for Svelte components. Used when dev=false.
*/
class SvelteComponent {
$destroy() {
destroy_component(this, 1);
this.$destroy = noop;
}
$on(type, callback) {
const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = []));
callbacks.push(callback);
return () => {
const index = callbacks.indexOf(callback);
if (index !== -1)
callbacks.splice(index, 1);
};
}
$set($$props) {
if (this.$$set && !is_empty($$props)) {
this.$$.skip_bound = true;
this.$$set($$props);
this.$$.skip_bound = false;
}
}
}
/* src/ui/component/ObsidianButton.svelte generated by Svelte v3.48.0 */
function create_fragment$3(ctx) {
let button;
let current;
let mounted;
let dispose;
const default_slot_template = /*#slots*/ ctx[4].default;
const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[3], null);
return {
c() {
button = element("button");
if (default_slot) default_slot.c();
attr(button, "aria-label", /*popup*/ ctx[0]);
button.disabled = /*disabled*/ ctx[1];
toggle_class(button, "mod-cta", !/*disabled*/ ctx[1]);
},
m(target, anchor) {
insert(target, button, anchor);
if (default_slot) {
default_slot.m(button, null);
}
current = true;
if (!mounted) {
dispose = listen(button, "click", /*handleClick*/ ctx[2]);
mounted = true;
}
},
p(ctx, [dirty]) {
if (default_slot) {
if (default_slot.p && (!current || dirty & /*$$scope*/ 8)) {
update_slot_base(
default_slot,
default_slot_template,
ctx,
/*$$scope*/ ctx[3],
!current
? get_all_dirty_from_scope(/*$$scope*/ ctx[3])
: get_slot_changes(default_slot_template, /*$$scope*/ ctx[3], dirty, null),
null
);
}
}
if (!current || dirty & /*popup*/ 1) {
attr(button, "aria-label", /*popup*/ ctx[0]);
}
if (!current || dirty & /*disabled*/ 2) {
button.disabled = /*disabled*/ ctx[1];
}
if (dirty & /*disabled*/ 2) {
toggle_class(button, "mod-cta", !/*disabled*/ ctx[1]);
}
},
i(local) {
if (current) return;
transition_in(default_slot, local);
current = true;
},
o(local) {
transition_out(default_slot, local);
current = false;
},
d(detaching) {
if (detaching) detach(button);
if (default_slot) default_slot.d(detaching);
mounted = false;
dispose();
}
};
}
function instance$3($$self, $$props, $$invalidate) {
let { $$slots: slots = {}, $$scope } = $$props;
let { popup } = $$props;
let { disabled = false } = $$props;
const dispatcher = createEventDispatcher();
const handleClick = () => {
dispatcher("click");
};
$$self.$$set = $$props => {
if ('popup' in $$props) $$invalidate(0, popup = $$props.popup);
if ('disabled' in $$props) $$invalidate(1, disabled = $$props.disabled);
if ('$$scope' in $$props) $$invalidate(3, $$scope = $$props.$$scope);
};
return [popup, disabled, handleClick, $$scope, slots];
}
class ObsidianButton extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance$3, create_fragment$3, safe_not_equal, { popup: 0, disabled: 1 });
}
}
/* node_modules/svelte-lucide-icons/icons/File.svelte generated by Svelte v3.48.0 */
function create_fragment$2(ctx) {
let svg;
let path;
let polyline;
let current;
const default_slot_template = /*#slots*/ ctx[3].default;
const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[2], null);
let svg_levels = [
{ xmlns: "http://www.w3.org/2000/svg" },
{ width: /*size*/ ctx[0] },
{ height: /*size*/ ctx[0] },
{ viewBox: "0 0 24 24" },
{ fill: "none" },
{ stroke: "currentColor" },
{ "stroke-width": "2" },
{ "stroke-linecap": "round" },
{ "stroke-linejoin": "round" },
/*$$restProps*/ ctx[1]
];
let svg_data = {};
for (let i = 0; i < svg_levels.length; i += 1) {
svg_data = assign(svg_data, svg_levels[i]);
}
return {
c() {
svg = svg_element("svg");
if (default_slot) default_slot.c();
path = svg_element("path");
polyline = svg_element("polyline");
attr(path, "d", "M14.5 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V7.5L14.5 2z");
attr(polyline, "points", "14 2 14 8 20 8");
set_svg_attributes(svg, svg_data);
},
m(target, anchor) {
insert(target, svg, anchor);
if (default_slot) {
default_slot.m(svg, null);
}
append(svg, path);
append(svg, polyline);
current = true;
},
p(ctx, [dirty]) {
if (default_slot) {
if (default_slot.p && (!current || dirty & /*$$scope*/ 4)) {
update_slot_base(
default_slot,
default_slot_template,
ctx,
/*$$scope*/ ctx[2],
!current
? get_all_dirty_from_scope(/*$$scope*/ ctx[2])
: get_slot_changes(default_slot_template, /*$$scope*/ ctx[2], dirty, null),
null
);
}
}
set_svg_attributes(svg, svg_data = get_spread_update(svg_levels, [
{ xmlns: "http://www.w3.org/2000/svg" },
(!current || dirty & /*size*/ 1) && { width: /*size*/ ctx[0] },
(!current || dirty & /*size*/ 1) && { height: /*size*/ ctx[0] },
{ viewBox: "0 0 24 24" },
{ fill: "none" },
{ stroke: "currentColor" },
{ "stroke-width": "2" },
{ "stroke-linecap": "round" },
{ "stroke-linejoin": "round" },
dirty & /*$$restProps*/ 2 && /*$$restProps*/ ctx[1]
]));
},
i(local) {
if (current) return;
transition_in(default_slot, local);
current = true;
},
o(local) {
transition_out(default_slot, local);
current = false;
},
d(detaching) {
if (detaching) detach(svg);
if (default_slot) default_slot.d(detaching);
}
};
}
function instance$2($$self, $$props, $$invalidate) {
const omit_props_names = ["size"];
let $$restProps = compute_rest_props($$props, omit_props_names);
let { $$slots: slots = {}, $$scope } = $$props;
let { size = 24 } = $$props;
$$self.$$set = $$new_props => {
$$props = assign(assign({}, $$props), exclude_internal_props($$new_props));
$$invalidate(1, $$restProps = compute_rest_props($$props, omit_props_names));
if ('size' in $$new_props) $$invalidate(0, size = $$new_props.size);
if ('$$scope' in $$new_props) $$invalidate(2, $$scope = $$new_props.$$scope);
};
return [size, $$restProps, $$scope, slots];
}
class File extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance$2, create_fragment$2, safe_not_equal, { size: 0 });
}
}
/* src/ui/component/ObsidianIconButton.svelte generated by Svelte v3.48.0 */
function add_css(target) {
append_styles(target, "svelte-12yh6aw", ".wrapper.svelte-12yh6aw{display:flex;justify-content:center;margin:0}.button-enabled.svelte-12yh6aw:hover{color:var(--interactive-accent)}.button-disabled.svelte-12yh6aw{color:var(--text-muted)}");
}
function create_fragment$1(ctx) {
let div;
let button;
let button_class_value;
let current;
let mounted;
let dispose;
const default_slot_template = /*#slots*/ ctx[4].default;
const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[3], null);
return {
c() {
div = element("div");
button = element("button");
if (default_slot) default_slot.c();
attr(button, "aria-label", /*popup*/ ctx[0]);
button.disabled = /*disabled*/ ctx[1];
attr(button, "class", button_class_value = "" + (null_to_empty(/*disabled*/ ctx[1]
? "button-disabled"
: "button-enabled") + " svelte-12yh6aw"));
set_style(button, "background-color", "transparent");
set_style(button, "padding", "0");
attr(div, "class", "wrapper svelte-12yh6aw");
},
m(target, anchor) {
insert(target, div, anchor);
append(div, button);
if (default_slot) {
default_slot.m(button, null);
}
current = true;
if (!mounted) {
dispose = listen(button, "click", /*handleClick*/ ctx[2]);
mounted = true;
}
},
p(ctx, [dirty]) {
if (default_slot) {
if (default_slot.p && (!current || dirty & /*$$scope*/ 8)) {
update_slot_base(
default_slot,
default_slot_template,
ctx,
/*$$scope*/ ctx[3],
!current
? get_all_dirty_from_scope(/*$$scope*/ ctx[3])
: get_slot_changes(default_slot_template, /*$$scope*/ ctx[3], dirty, null),
null
);
}
}
if (!current || dirty & /*popup*/ 1) {
attr(button, "aria-label", /*popup*/ ctx[0]);
}
if (!current || dirty & /*disabled*/ 2) {
button.disabled = /*disabled*/ ctx[1];
}
if (!current || dirty & /*disabled*/ 2 && button_class_value !== (button_class_value = "" + (null_to_empty(/*disabled*/ ctx[1]
? "button-disabled"
: "button-enabled") + " svelte-12yh6aw"))) {
attr(button, "class", button_class_value);
}
},
i(local) {
if (current) return;
transition_in(default_slot, local);
current = true;
},
o(local) {
transition_out(default_slot, local);
current = false;
},
d(detaching) {
if (detaching) detach(div);
if (default_slot) default_slot.d(detaching);
mounted = false;
dispose();
}
};
}
function instance$1($$self, $$props, $$invalidate) {
let { $$slots: slots = {}, $$scope } = $$props;
let { popup } = $$props;
let { disabled = false } = $$props;
const dispatcher = createEventDispatcher();
const handleClick = () => {
if (!disabled) {
dispatcher("click");
}
};
$$self.$$set = $$props => {
if ('popup' in $$props) $$invalidate(0, popup = $$props.popup);
if ('disabled' in $$props) $$invalidate(1, disabled = $$props.disabled);
if ('$$scope' in $$props) $$invalidate(3, $$scope = $$props.$$scope);
};
return [popup, disabled, handleClick, $$scope, slots];
}
class ObsidianIconButton extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance$1, create_fragment$1, safe_not_equal, { popup: 0, disabled: 1 }, add_css);
}
}
/* src/ui/component/CustomDictionaryWordAdd.svelte generated by Svelte v3.48.0 */
function get_each_context(ctx, list, i) {
const child_ctx = ctx.slice();
child_ctx[26] = list[i];
return child_ctx;
}
// (48:6) {#each dictionaries as dictionary}
function create_each_block(ctx) {
let option;
let t0_value = /*dictionary*/ ctx[26].path + "";
let t0;
let t1;
let option_value_value;
return {
c() {
option = element("option");
t0 = text(t0_value);
t1 = space();
option.__value = option_value_value = /*dictionary*/ ctx[26];
option.value = option.__value;
},
m(target, anchor) {
insert(target, option, anchor);
append(option, t0);
append(option, t1);
},
p(ctx, dirty) {
if (dirty & /*dictionaries*/ 32 && t0_value !== (t0_value = /*dictionary*/ ctx[26].path + "")) set_data(t0, t0_value);
if (dirty & /*dictionaries*/ 32 && option_value_value !== (option_value_value = /*dictionary*/ ctx[26])) {
option.__value = option_value_value;
option.value = option.__value;
}
},
d(detaching) {
if (detaching) detach(option);
}
};
}
// (54:4) <ObsidianIconButton popup="Open the file" on:click={() => onClickFileIcon(selectedDictionary.path)} >
function create_default_slot_1(ctx) {
let file;
let current;
file = new File({});
return {
c() {
create_component(file.$$.fragment);
},
m(target, anchor) {
mount_component(file, target, anchor);
current = true;
},
i(local) {
if (current) return;
transition_in(file.$$.fragment, local);
current = true;
},
o(local) {
transition_out(file.$$.fragment, local);
current = false;
},
d(detaching) {
destroy_component(file, detaching);
}
};
}
// (70:2) {#if enableDisplayedWord}
function create_if_block_1(ctx) {
let label;
let input;
let t;
let mounted;
let dispose;
return {
c() {
label = element("label");
input = element("input");
t = text("\n Distinguish between display and insertion");
attr(input, "type", "checkbox");
},
m(target, anchor) {
insert(target, label, anchor);
append(label, input);
input.checked = /*useDisplayedWord*/ ctx[1];
append(label, t);
if (!mounted) {
dispose = listen(input, "change", /*input_change_handler*/ ctx[21]);
mounted = true;
}
},
p(ctx, dirty) {
if (dirty & /*useDisplayedWord*/ 2) {
input.checked = /*useDisplayedWord*/ ctx[1];
}
},
d(detaching) {
if (detaching) detach(label);
mounted = false;
dispose();
}
};
}
// (77:2) {#if useDisplayedWord}
function create_if_block(ctx) {
let h3;
let t1;
let textarea;
let mounted;
let dispose;
return {
c() {
h3 = element("h3");
h3.textContent = "Displayed Word";
t1 = space();
textarea = element("textarea");
set_style(textarea, "width", "100%");
attr(textarea, "rows", "3");
},
m(target, anchor) {
insert(target, h3, anchor);
insert(target, t1, anchor);
insert(target, textarea, anchor);
set_input_value(textarea, /*displayedWord*/ ctx[3]);
/*textarea_binding*/ ctx[23](textarea);
if (!mounted) {
dispose = listen(textarea, "input", /*textarea_input_handler*/ ctx[22]);
mounted = true;
}
},
p(ctx, dirty) {
if (dirty & /*displayedWord*/ 8) {
set_input_value(textarea, /*displayedWord*/ ctx[3]);
}
},
d(detaching) {
if (detaching) detach(h3);
if (detaching) detach(t1);
if (detaching) detach(textarea);
/*textarea_binding*/ ctx[23](null);
mounted = false;
dispose();
}
};
}
// (94:4) <ObsidianButton disabled={!enableSubmit} on:click={handleSubmit} >
function create_default_slot(ctx) {
let t;
return {
c() {
t = text("Submit");
},
m(target, anchor) {
insert(target, t, anchor);
},
d(detaching) {
if (detaching) detach(t);
}
};
}
function create_fragment(ctx) {
let div2;
let h2;
let t1;
let h30;
let t3;
let div0;
let select;
let t4;
let obsidianiconbutton;
let t5;
let h31;
let t6;
let t7;
let textarea0;
let t8;
let t9;
let t10;
let h32;
let t12;
let input;
let t13;
let h33;
let t15;
let textarea1;
let t16;
let div1;
let obsidianbutton;
let current;
let mounted;
let dispose;
let each_value = /*dictionaries*/ ctx[5];
let each_blocks = [];
for (let i = 0; i < each_value.length; i += 1) {
each_blocks[i] = create_each_block(get_each_context(ctx, each_value, i));
}
obsidianiconbutton = new ObsidianIconButton({
props: {
popup: "Open the file",
$$slots: { default: [create_default_slot_1] },
$$scope: { ctx }
}
});
obsidianiconbutton.$on("click", /*click_handler*/ ctx[18]);
let if_block0 = /*enableDisplayedWord*/ ctx[11] && create_if_block_1(ctx);
let if_block1 = /*useDisplayedWord*/ ctx[1] && create_if_block(ctx);
obsidianbutton = new ObsidianButton({
props: {
disabled: !/*enableSubmit*/ ctx[12],
$$slots: { default: [create_default_slot] },
$$scope: { ctx }
}
});
obsidianbutton.$on("click", /*handleSubmit*/ ctx[13]);
return {
c() {
div2 = element("div");
h2 = element("h2");
h2.textContent = "Add a word to a custom dictionary";
t1 = space();
h30 = element("h3");
h30.textContent = "Dictionary";
t3 = space();
div0 = element("div");
select = element("select");
for (let i = 0; i < each_blocks.length; i += 1) {
each_blocks[i].c();
}
t4 = space();
create_component(obsidianiconbutton.$$.fragment);
t5 = space();
h31 = element("h3");
t6 = text(/*firstWordTitle*/ ctx[10]);
t7 = space();
textarea0 = element("textarea");
t8 = space();
if (if_block0) if_block0.c();
t9 = space();
if (if_block1) if_block1.c();
t10 = space();
h32 = element("h3");
h32.textContent = "Description";
t12 = space();
input = element("input");
t13 = space();
h33 = element("h3");
h33.textContent = "Aliases (for each line)";
t15 = space();
textarea1 = element("textarea");
t16 = space();
div1 = element("div");
create_component(obsidianbutton.$$.fragment);
attr(select, "class", "dropdown");
if (/*selectedDictionary*/ ctx[2] === void 0) add_render_callback(() => /*select_change_handler*/ ctx[17].call(select));
set_style(div0, "display", "flex");
set_style(div0, "gap", "10px");
set_style(textarea0, "width", "100%");
attr(textarea0, "rows", "3");
attr(input, "type", "text");
set_style(input, "width", "100%");
set_style(textarea1, "width", "100%");
attr(textarea1, "rows", "3");
set_style(div1, "text-align", "center");
set_style(div1, "width", "100%");
set_style(div1, "padding-top", "15px");
},
m(target, anchor) {
insert(target, div2, anchor);
append(div2, h2);
append(div2, t1);
append(div2, h30);
append(div2, t3);
append(div2, div0);
append(div0, select);
for (let i = 0; i < each_blocks.length; i += 1) {
each_blocks[i].m(select, null);
}
select_option(select, /*selectedDictionary*/ ctx[2]);
append(div0, t4);
mount_component(obsidianiconbutton, div0, null);
append(div2, t5);
append(div2, h31);
append(h31, t6);
append(div2, t7);
append(div2, textarea0);
set_input_value(textarea0, /*word*/ ctx[0]);
/*textarea0_binding*/ ctx[20](textarea0);
append(div2, t8);
if (if_block0) if_block0.m(div2, null);
append(div2, t9);
if (if_block1) if_block1.m(div2, null);
append(div2, t10);
append(div2, h32);
append(div2, t12);
append(div2, input);
set_input_value(input, /*description*/ ctx[4]);
append(div2, t13);
append(div2, h33);
append(div2, t15);
append(div2, textarea1);
set_input_value(textarea1, /*aliasesStr*/ ctx[8]);
append(div2, t16);
append(div2, div1);
mount_component(obsidianbutton, div1, null);
current = true;
if (!mounted) {
dispose = [
listen(select, "change", /*select_change_handler*/ ctx[17]),
listen(textarea0, "input", /*textarea0_input_handler*/ ctx[19]),
listen(input, "input", /*input_input_handler*/ ctx[24]),
listen(textarea1, "input", /*textarea1_input_handler*/ ctx[25])
];
mounted = true;
}
},
p(ctx, [dirty]) {
if (dirty & /*dictionaries*/ 32) {
each_value = /*dictionaries*/ ctx[5];
let i;
for (i = 0; i < each_value.length; i += 1) {
const child_ctx = get_each_context(ctx, each_value, i);
if (each_blocks[i]) {
each_blocks[i].p(child_ctx, dirty);
} else {
each_blocks[i] = create_each_block(child_ctx);
each_blocks[i].c();
each_blocks[i].m(select, null);
}
}
for (; i < each_blocks.length; i += 1) {
each_blocks[i].d(1);
}
each_blocks.length = each_value.length;
}
if (dirty & /*selectedDictionary, dictionaries*/ 36) {
select_option(select, /*selectedDictionary*/ ctx[2]);
}
const obsidianiconbutton_changes = {};
if (dirty & /*$$scope*/ 536870912) {
obsidianiconbutton_changes.$$scope = { dirty, ctx };
}
obsidianiconbutton.$set(obsidianiconbutton_changes);
if (!current || dirty & /*firstWordTitle*/ 1024) set_data(t6, /*firstWordTitle*/ ctx[10]);
if (dirty & /*word*/ 1) {
set_input_value(textarea0, /*word*/ ctx[0]);
}
if (/*enableDisplayedWord*/ ctx[11]) {
if (if_block0) {
if_block0.p(ctx, dirty);
} else {
if_block0 = create_if_block_1(ctx);
if_block0.c();
if_block0.m(div2, t9);
}
} else if (if_block0) {
if_block0.d(1);
if_block0 = null;
}
if (/*useDisplayedWord*/ ctx[1]) {
if (if_block1) {
if_block1.p(ctx, dirty);
} else {
if_block1 = create_if_block(ctx);
if_block1.c();
if_block1.m(div2, t10);
}
} else if (if_block1) {
if_block1.d(1);
if_block1 = null;
}
if (dirty & /*description*/ 16 && input.value !== /*description*/ ctx[4]) {
set_input_value(input, /*description*/ ctx[4]);
}
if (dirty & /*aliasesStr*/ 256) {
set_input_value(textarea1, /*aliasesStr*/ ctx[8]);
}
const obsidianbutton_changes = {};
if (dirty & /*enableSubmit*/ 4096) obsidianbutton_changes.disabled = !/*enableSubmit*/ ctx[12];
if (dirty & /*$$scope*/ 536870912) {
obsidianbutton_changes.$$scope = { dirty, ctx };
}
obsidianbutton.$set(obsidianbutton_changes);
},
i(local) {
if (current) return;
transition_in(obsidianiconbutton.$$.fragment, local);
transition_in(obsidianbutton.$$.fragment, local);
current = true;
},
o(local) {
transition_out(obsidianiconbutton.$$.fragment, local);
transition_out(obsidianbutton.$$.fragment, local);
current = false;
},
d(detaching) {
if (detaching) detach(div2);
destroy_each(each_blocks, detaching);
destroy_component(obsidianiconbutton);
/*textarea0_binding*/ ctx[20](null);
if (if_block0) if_block0.d();
if (if_block1) if_block1.d();
destroy_component(obsidianbutton);
mounted = false;
run_all(dispose);
}
};
}
function instance($$self, $$props, $$invalidate) {
let enableSubmit;
let enableDisplayedWord;
let firstWordTitle;
let { dictionaries } = $$props;
let { selectedDictionary } = $$props;
let { word = "" } = $$props;
let { useDisplayedWord = false } = $$props;
let { displayedWord = "" } = $$props;
let { description = "" } = $$props;
let { aliases = [] } = $$props;
let { dividerForDisplay = "" } = $$props;
let { onSubmit } = $$props;
let { onClickFileIcon } = $$props;
let aliasesStr = aliases.join("\n");
let wordRef = null;
let displayedWordRef = null;
const handleSubmit = () => {
onSubmit(selectedDictionary.path, {
value: displayedWord || word,
description,
aliases: aliasesStr.split("\n"),
type: "customDictionary",
createdPath: selectedDictionary.path,
insertedText: displayedWord ? word : undefined
});
};
onMount(() => {
setTimeout(() => wordRef.focus(), 50);
});
function select_change_handler() {
selectedDictionary = select_value(this);
$$invalidate(2, selectedDictionary);
$$invalidate(5, dictionaries);
}
const click_handler = () => onClickFileIcon(selectedDictionary.path);
function textarea0_input_handler() {
word = this.value;
$$invalidate(0, word);
}
function textarea0_binding($$value) {
binding_callbacks[$$value ? 'unshift' : 'push'](() => {
wordRef = $$value;
$$invalidate(9, wordRef);
});
}
function input_change_handler() {
useDisplayedWord = this.checked;
$$invalidate(1, useDisplayedWord);
}
function textarea_input_handler() {
displayedWord = this.value;
$$invalidate(3, displayedWord);
}
function textarea_binding($$value) {
binding_callbacks[$$value ? 'unshift' : 'push'](() => {
displayedWordRef = $$value;
$$invalidate(7, displayedWordRef);
});
}
function input_input_handler() {
description = this.value;
$$invalidate(4, description);
}
function textarea1_input_handler() {
aliasesStr = this.value;
$$invalidate(8, aliasesStr);
}
$$self.$$set = $$props => {
if ('dictionaries' in $$props) $$invalidate(5, dictionaries = $$props.dictionaries);
if ('selectedDictionary' in $$props) $$invalidate(2, selectedDictionary = $$props.selectedDictionary);
if ('word' in $$props) $$invalidate(0, word = $$props.word);
if ('useDisplayedWord' in $$props) $$invalidate(1, useDisplayedWord = $$props.useDisplayedWord);
if ('displayedWord' in $$props) $$invalidate(3, displayedWord = $$props.displayedWord);
if ('description' in $$props) $$invalidate(4, description = $$props.description);
if ('aliases' in $$props) $$invalidate(14, aliases = $$props.aliases);
if ('dividerForDisplay' in $$props) $$invalidate(15, dividerForDisplay = $$props.dividerForDisplay);
if ('onSubmit' in $$props) $$invalidate(16, onSubmit = $$props.onSubmit);
if ('onClickFileIcon' in $$props) $$invalidate(6, onClickFileIcon = $$props.onClickFileIcon);
};
$$self.$$.update = () => {
if ($$self.$$.dirty & /*word*/ 1) {
$$invalidate(12, enableSubmit = word.length > 0);
}
if ($$self.$$.dirty & /*dividerForDisplay*/ 32768) {
$$invalidate(11, enableDisplayedWord = Boolean(dividerForDisplay));
}
if ($$self.$$.dirty & /*useDisplayedWord*/ 2) {
$$invalidate(10, firstWordTitle = useDisplayedWord ? "Inserted word" : "Word");
}
if ($$self.$$.dirty & /*useDisplayedWord, displayedWordRef*/ 130) {
{
if (useDisplayedWord) {
displayedWordRef === null || displayedWordRef === void 0
? void 0
: displayedWordRef.focus();
}
}
}
};
return [
word,
useDisplayedWord,
selectedDictionary,
displayedWord,
description,
dictionaries,
onClickFileIcon,
displayedWordRef,
aliasesStr,
wordRef,
firstWordTitle,
enableDisplayedWord,
enableSubmit,
handleSubmit,
aliases,
dividerForDisplay,
onSubmit,
select_change_handler,
click_handler,
textarea0_input_handler,
textarea0_binding,
input_change_handler,
textarea_input_handler,
textarea_binding,
input_input_handler,
textarea1_input_handler
];
}
class CustomDictionaryWordAdd extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance, create_fragment, safe_not_equal, {
dictionaries: 5,
selectedDictionary: 2,
word: 0,
useDisplayedWord: 1,
displayedWord: 3,
description: 4,
aliases: 14,
dividerForDisplay: 15,
onSubmit: 16,
onClickFileIcon: 6
});
}
}
class CustomDictionaryWordAddModal extends obsidian.Modal {
constructor(app, dictionaryPaths, initialValue = "", dividerForDisplay = "", onSubmit) {
super(app);
const appHelper = new AppHelper(app);
const dictionaries = dictionaryPaths.map((x) => ({ id: x, path: x }));
const { contentEl } = this;
this.component = new CustomDictionaryWordAdd({
target: contentEl,
props: {
dictionaries,
selectedDictionary: dictionaries[0],
word: initialValue,
dividerForDisplay,
onSubmit: onSubmit,
onClickFileIcon: (dictionaryPath) => {
const markdownFile = appHelper.getMarkdownFileByPath(dictionaryPath);
if (!markdownFile) {
// noinspection ObjectAllocationIgnored
new obsidian.Notice(`Can't open ${dictionaryPath}`);
return;
}
this.close();
appHelper.openMarkdownFile(markdownFile, true);
},
},
});
}
onClose() {
super.onClose();
this.component.$destroy();
}
}
class VariousComponents extends obsidian.Plugin {
onunload() {
super.onunload();
this.suggester.unregister();
}
onload() {
return __awaiter(this, void 0, void 0, function* () {
this.appHelper = new AppHelper(this.app);
this.registerEvent(this.app.workspace.on("editor-menu", (menu) => {
if (!this.appHelper.getSelection()) {
return;
}
menu.addItem((item) => item
.setTitle("Add to custom dictionary")
.setIcon("stacked-levels")
.onClick(() => {
this.addWordToCustomDictionary();
}));
}));
yield this.loadSettings();
this.settingTab = new VariousComplementsSettingTab(this.app, this);
this.addSettingTab(this.settingTab);
this.statusBar = ProviderStatusBar.new(this.addStatusBarItem(), this.settings.showMatchStrategy, this.settings.showIndexingStatus);
this.statusBar.setOnClickStrategyListener(() => __awaiter(this, void 0, void 0, function* () {
yield this.settingTab.toggleMatchStrategy();
}));
const debouncedSaveData = obsidian.debounce(() => __awaiter(this, void 0, void 0, function* () {
yield this.saveData(this.settings);
}), 5000);
this.suggester = yield AutoCompleteSuggest.new(this.app, this.settings, this.statusBar, debouncedSaveData);
this.registerEditorSuggest(this.suggester);
this.addCommand({
id: "reload-custom-dictionaries",
name: "Reload custom dictionaries",
hotkeys: [{ modifiers: ["Mod", "Shift"], key: "r" }],
callback: () => __awaiter(this, void 0, void 0, function* () {
yield this.suggester.refreshCustomDictionaryTokens();
}),
});
this.addCommand({
id: "reload-current-vault",
name: "Reload current vault",
callback: () => __awaiter(this, void 0, void 0, function* () {
yield this.suggester.refreshCurrentVaultTokens();
}),
});
this.addCommand({
id: "toggle-match-strategy",
name: "Toggle Match strategy",
callback: () => __awaiter(this, void 0, void 0, function* () {
yield this.settingTab.toggleMatchStrategy();
}),
});
this.addCommand({
id: "toggle-complement-automatically",
name: "Toggle Complement automatically",
callback: () => __awaiter(this, void 0, void 0, function* () {
yield this.settingTab.toggleComplementAutomatically();
}),
});
this.addCommand({
id: "show-suggestions",
name: "Show suggestions",
hotkeys: [{ modifiers: ["Mod"], key: " " }],
callback: () => __awaiter(this, void 0, void 0, function* () {
this.suggester.triggerComplete();
}),
});
this.addCommand({
id: "add-word-custom-dictionary",
name: "Add a word to a custom dictionary",
hotkeys: [{ modifiers: ["Mod", "Shift"], key: " " }],
callback: () => __awaiter(this, void 0, void 0, function* () {
this.addWordToCustomDictionary();
}),
});
this.addCommand({
id: "predictable-complements",
name: "Predictable complement",
callback: () => __awaiter(this, void 0, void 0, function* () {
this.suggester.predictableComplete();
}),
});
this.addCommand({
id: "copy-plugin-settings",
name: "Copy plugin settings",
callback: () => __awaiter(this, void 0, void 0, function* () {
yield navigator.clipboard.writeText(this.settingTab.getPluginSettingsAsJsonString());
// noinspection ObjectAllocationIgnored
new obsidian.Notice("Copy settings of Various Complements");
}),
});
});
}
loadSettings() {
return __awaiter(this, void 0, void 0, function* () {
this.settings = Object.assign(Object.assign({}, DEFAULT_SETTINGS), (yield this.loadData()));
});
}
saveSettings(needUpdateTokens = {}) {
return __awaiter(this, void 0, void 0, function* () {
yield this.saveData(this.settings);
yield this.suggester.updateSettings(this.settings);
if (needUpdateTokens.currentFile) {
yield this.suggester.refreshCurrentFileTokens();
}
if (needUpdateTokens.currentVault) {
yield this.suggester.refreshCurrentVaultTokens();
}
if (needUpdateTokens.customDictionary) {
yield this.suggester.refreshCustomDictionaryTokens();
}
if (needUpdateTokens.internalLink) {
yield this.suggester.refreshInternalLinkTokens();
}
if (needUpdateTokens.frontMatter) {
yield this.suggester.refreshFrontMatterTokens();
}
});
}
addWordToCustomDictionary() {
const selectedWord = this.appHelper.getSelection();
const provider = this.suggester.customDictionaryWordProvider;
const modal = new CustomDictionaryWordAddModal(this.app, provider.editablePaths, selectedWord, this.settings.delimiterToDivideSuggestionsForDisplayFromInsertion, (dictionaryPath, word) => __awaiter(this, void 0, void 0, function* () {
if (provider.wordByValue[word.value]) {
// noinspection ObjectAllocationIgnored
new obsidian.Notice(`${word.value} already exists`, 0);
return;
}
yield provider.addWordWithDictionary(word, dictionaryPath);
// noinspection ObjectAllocationIgnored
new obsidian.Notice(`Added ${word.value}`);
modal.close();
}));
modal.open();
}
}
module.exports = VariousComponents;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsInNyYy91dGlsL3N0cmluZ3MudHMiLCJzcmMvdG9rZW5pemVyL3Rva2VuaXplcnMvRGVmYXVsdFRva2VuaXplci50cyIsInNyYy90b2tlbml6ZXIvdG9rZW5pemVycy9BcmFiaWNUb2tlbml6ZXIudHMiLCJzcmMvZXh0ZXJuYWwvdGlueS1zZWdtZW50ZXIudHMiLCJzcmMvdG9rZW5pemVyL3Rva2VuaXplcnMvSmFwYW5lc2VUb2tlbml6ZXIudHMiLCJzcmMvdG9rZW5pemVyL3Rva2VuaXplcnMvRW5nbGlzaE9ubHlUb2tlbml6ZXIudHMiLCJzcmMvdG9rZW5pemVyL3Rva2VuaXplci50cyIsInNyYy90b2tlbml6ZXIvVG9rZW5pemVTdHJhdGVneS50cyIsInNyYy9hcHAtaGVscGVyLnRzIiwic3JjL3V0aWwvY29sbGVjdGlvbi1oZWxwZXIudHMiLCJzcmMvbW9kZWwvV29yZC50cyIsInNyYy9wcm92aWRlci9zdWdnZXN0ZXIudHMiLCJzcmMvdXRpbC9wYXRoLnRzIiwic3JjL3Byb3ZpZGVyL0N1c3RvbURpY3Rpb25hcnlXb3JkUHJvdmlkZXIudHMiLCJzcmMvcHJvdmlkZXIvQ3VycmVudEZpbGVXb3JkUHJvdmlkZXIudHMiLCJzcmMvcHJvdmlkZXIvSW50ZXJuYWxMaW5rV29yZFByb3ZpZGVyLnRzIiwic3JjL3Byb3ZpZGVyL01hdGNoU3RyYXRlZ3kudHMiLCJzcmMvb3B0aW9uL0N5Y2xlVGhyb3VnaFN1Z2dlc3Rpb25zS2V5cy50cyIsInNyYy9vcHRpb24vQ29sdW1uRGVsaW1pdGVyLnRzIiwic3JjL29wdGlvbi9TZWxlY3RTdWdnZXN0aW9uS2V5LnRzIiwic3JjL3Byb3ZpZGVyL0N1cnJlbnRWYXVsdFdvcmRQcm92aWRlci50cyIsInNyYy9vcHRpb24vT3BlblNvdXJjZUZpbGVLZXlzLnRzIiwic3JjL29wdGlvbi9EZXNjcmlwdGlvbk9uU3VnZ2VzdGlvbi50cyIsInNyYy9wcm92aWRlci9Gcm9udE1hdHRlcldvcmRQcm92aWRlci50cyIsInNyYy9wcm92aWRlci9TcGVjaWZpY01hdGNoU3RyYXRlZ3kudHMiLCJzcmMvc3RvcmFnZS9TZWxlY3Rpb25IaXN0b3J5U3RvcmFnZS50cyIsInNyYy91aS9BdXRvQ29tcGxldGVTdWdnZXN0LnRzIiwic3JjL3NldHRpbmcvc2V0dGluZ3MudHMiLCJzcmMvdWkvUHJvdmlkZXJTdGF0dXNCYXIudHMiLCJub2RlX21vZHVsZXMvc3ZlbHRlL2ludGVybmFsL2luZGV4Lm1qcyIsInNyYy91aS9jb21wb25lbnQvT2JzaWRpYW5CdXR0b24uc3ZlbHRlIiwibm9kZV9tb2R1bGVzL3N2ZWx0ZS1sdWNpZGUtaWNvbnMvaWNvbnMvRmlsZS5zdmVsdGUiLCJzcmMvdWkvY29tcG9uZW50L09ic2lkaWFuSWNvbkJ1dHRvbi5zdmVsdGUiLCJzcmMvdWkvY29tcG9uZW50L0N1c3RvbURpY3Rpb25hcnlXb3JkQWRkLnN2ZWx0ZSIsInNyYy91aS9DdXN0b21EaWN0aW9uYXJ5V29yZEFkZE1vZGFsLnRzIiwic3JjL21haW4udHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi5cclxuXHJcblBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZC9vciBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmUgZm9yIGFueVxyXG5wdXJwb3NlIHdpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQuXHJcblxyXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiIEFORCBUSEUgQVVUSE9SIERJU0NMQUlNUyBBTEwgV0FSUkFOVElFUyBXSVRIXHJcblJFR0FSRCBUTyBUSElTIFNPRlRXQVJFIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWVxyXG5BTkQgRklUTkVTUy4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBESVJFQ1QsXHJcbklORElSRUNULCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTVxyXG5MT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUlxyXG5PVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SXHJcblBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlICovXHJcblxyXG52YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcclxuICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XHJcbiAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcclxuICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXh0ZW5kcyhkLCBiKSB7XHJcbiAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxyXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcclxuICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcclxufVxyXG5cclxuZXhwb3J0IHZhciBfX2F