This commit is contained in:
oscar.plaisant@icloud.com
2024-01-07 19:26:57 +01:00
parent 489c2cd097
commit 14378a3bec
268 changed files with 81843 additions and 109871 deletions

View File

@@ -808,20 +808,40 @@ function joinNumberWithSymbol(tokens) {
return ret;
}
// src/errors.ts
var ExhaustiveError = class extends Error {
constructor(value, message = `Unsupported type: ${value}`) {
super(message);
}
};
// src/tokenizer/tokenizers/DefaultTokenizer.ts
function pickTokens(content, trimPattern) {
return content.split(trimPattern).filter((x) => x !== "");
}
var TRIM_CHAR_PATTERN = /[\n\t\[\]$/:?!=()<>"',|;*~ `_“„«»”]/g;
var INPUT_TRIM_CHAR_PATTERN = /[\n\t\[\]$/:?!=()<>"',|;*~ `_“„«»”]/g;
var INDEXING_TRIM_CHAR_PATTERN = /[\n\t\[\]/:?!=()<>"',|;*~ `_“„«»”]/g;
function getTrimPattern(target) {
switch (target) {
case "input":
return INPUT_TRIM_CHAR_PATTERN;
case "indexing":
return INDEXING_TRIM_CHAR_PATTERN;
default:
throw new ExhaustiveError(target);
}
}
var DefaultTokenizer = class {
tokenize(content, raw) {
const tokens = raw ? Array.from(splitRaw(content, this.getTrimPattern())).filter(
const tokens = raw ? Array.from(splitRaw(content, this.getTrimPattern("indexing"))).filter(
(x) => x !== " "
) : pickTokens(content, this.getTrimPattern());
) : pickTokens(content, this.getTrimPattern("indexing"));
return tokens.map((x) => x.replace(/\.+$/g, ""));
}
recursiveTokenize(content) {
const trimIndexes = Array.from(content.matchAll(this.getTrimPattern())).sort((a, b) => a.index - b.index).map((x) => x.index);
const trimIndexes = Array.from(
content.matchAll(this.getTrimPattern("input"))
).sort((a, b) => a.index - b.index).map((x) => x.index);
return [
{ word: content, offset: 0 },
...trimIndexes.map((i) => ({
@@ -830,8 +850,8 @@ var DefaultTokenizer = class {
}))
];
}
getTrimPattern() {
return TRIM_CHAR_PATTERN;
getTrimPattern(target) {
return getTrimPattern(target);
}
shouldIgnoreOnCurrent(str) {
return false;
@@ -839,10 +859,18 @@ var DefaultTokenizer = class {
};
// src/tokenizer/tokenizers/ArabicTokenizer.ts
var ARABIC_TRIM_CHAR_PATTERN = /[\n\t\[\]$/:?!=()<>"'.,|;*~ `،؛]/g;
var INPUT_ARABIC_TRIM_CHAR_PATTERN = /[\n\t\[\]/:?!=()<>"'.,|;*~ `،؛]/g;
var INDEXING_ARABIC_TRIM_CHAR_PATTERN = /[\n\t\[\]$/:?!=()<>"'.,|;*~ `،؛]/g;
var ArabicTokenizer = class extends DefaultTokenizer {
getTrimPattern() {
return ARABIC_TRIM_CHAR_PATTERN;
getTrimPattern(target) {
switch (target) {
case "input":
return INPUT_ARABIC_TRIM_CHAR_PATTERN;
case "indexing":
return INDEXING_ARABIC_TRIM_CHAR_PATTERN;
default:
throw new ExhaustiveError(target);
}
}
};
@@ -2341,13 +2369,14 @@ var tiny_segmenter_default = TinySegmenter;
// src/tokenizer/tokenizers/JapaneseTokenizer.ts
var segmenter = new tiny_segmenter_default();
function pickTokensAsJapanese(content, trimPattern) {
return joinNumberWithSymbol(
content.split(trimPattern).filter((x) => x !== "").flatMap((x) => segmenter.segment(x))
);
return content.split(trimPattern).filter((x) => x !== "").flatMap((x) => joinNumberWithSymbol(segmenter.segment(x)));
}
var JapaneseTokenizer = class {
tokenize(content, raw) {
return pickTokensAsJapanese(content, raw ? / /g : this.getTrimPattern());
return pickTokensAsJapanese(
content,
raw ? / /g : this.getTrimPattern("indexing")
);
}
recursiveTokenize(content) {
const tokens = joinNumberWithSymbol(
@@ -2366,8 +2395,8 @@ var JapaneseTokenizer = class {
}
return ret;
}
getTrimPattern() {
return TRIM_CHAR_PATTERN;
getTrimPattern(target) {
return getTrimPattern(target);
}
shouldIgnoreOnCurrent(str) {
return Boolean(str.match(/^[ぁ-んa--Z。、ー ]*$/));
@@ -2378,13 +2407,13 @@ var JapaneseTokenizer = class {
var ENGLISH_PATTERN = /[a-zA-Z0-9_\-\\]/;
var EnglishOnlyTokenizer = class extends DefaultTokenizer {
tokenize(content, raw) {
const tokenized = Array.from(this._tokenize(content)).filter(
const tokenized = Array.from(this._tokenize(content, "indexing")).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()));
return raw ? tokenized.map((x) => x.word) : tokenized.map((x) => x.word).filter((x) => !x.match(this.getTrimPattern("indexing")));
}
recursiveTokenize(content) {
const offsets = Array.from(this._tokenize(content)).filter((x) => !x.word.match(this.getTrimPattern())).map((x) => x.offset);
const offsets = Array.from(this._tokenize(content, "input")).filter((x) => !x.word.match(this.getTrimPattern("input"))).map((x) => x.offset);
return [
...offsets.map((i) => ({
word: content.slice(i),
@@ -2392,11 +2421,11 @@ var EnglishOnlyTokenizer = class extends DefaultTokenizer {
}))
];
}
*_tokenize(content) {
*_tokenize(content, target) {
let startIndex = 0;
let previousType = "none";
for (let i = 0; i < content.length; i++) {
if (content[i].match(super.getTrimPattern())) {
if (content[i].match(super.getTrimPattern(target))) {
yield { word: content.slice(startIndex, i), offset: startIndex };
previousType = "trim";
startIndex = i;
@@ -2436,13 +2465,13 @@ var ChineseTokenizer = class {
return ins;
}
tokenize(content, raw) {
return content.split(raw ? / /g : this.getTrimPattern()).filter((x) => x !== "").flatMap((x) => this._tokenize(x)).map((x) => x.text);
return content.split(raw ? / /g : this.getTrimPattern("indexing")).filter((x) => x !== "").flatMap((x) => this._tokenize(x)).map((x) => x.text);
}
recursiveTokenize(content) {
const tokens = this._tokenize(content).map((x) => x.text);
const ret = [];
for (let i = 0; i < tokens.length; i++) {
if (i === 0 || tokens[i].length !== 1 || !Boolean(tokens[i].match(this.getTrimPattern()))) {
if (i === 0 || tokens[i].length !== 1 || !Boolean(tokens[i].match(this.getTrimPattern("input")))) {
ret.push({
word: tokens.slice(i).join(""),
offset: tokens.slice(0, i).join("").length
@@ -2451,8 +2480,8 @@ var ChineseTokenizer = class {
}
return ret;
}
getTrimPattern() {
return TRIM_CHAR_PATTERN;
getTrimPattern(target) {
return getTrimPattern(target);
}
shouldIgnoreOnCurrent(str) {
return false;
@@ -4326,7 +4355,7 @@ var AutoCompleteSuggest = class extends import_obsidian4.EditorSuggest {
);
}
onTrigger(cursor, editor) {
var _a, _b, _c, _d, _e, _f;
var _a, _b, _c, _d, _e;
const start = performance.now();
const showDebugLog = (message) => {
this.showDebugLog(() => `[onTrigger] ${message}`);
@@ -4372,14 +4401,14 @@ var AutoCompleteSuggest = class extends import_obsidian4.EditorSuggest {
const tokens = this.tokenizer.tokenize(currentLineUntilCursor, true);
showDebugLog(`tokens is ${tokens}`);
const tokenized = this.tokenizer.recursiveTokenize(currentLineUntilCursor);
const currentTokens = tokenized.slice(
let currentTokens = tokenized.slice(
tokenized.length > this.settings.maxNumberOfWordsAsPhrase ? tokenized.length - this.settings.maxNumberOfWordsAsPhrase : 0
);
showDebugLog(`currentTokens is ${JSON.stringify(currentTokens)}`);
const currentToken = (_a = currentTokens[0]) == null ? void 0 : _a.word;
showDebugLog(`currentToken is ${currentToken}`);
if (!currentToken) {
onReturnNull(`Don't show suggestions because currentToken is empty`);
const currentPhrase = (_a = currentTokens.first()) == null ? void 0 : _a.word;
showDebugLog(`currentPhrase is ${currentPhrase}`);
if (!currentPhrase) {
onReturnNull(`Don't show suggestions because currentPhrase is empty`);
return null;
}
const currentTokenSeparatedWhiteSpace = (_b = currentLineUntilCursor.split(" ").last()) != null ? _b : "";
@@ -4398,15 +4427,15 @@ var AutoCompleteSuggest = class extends import_obsidian4.EditorSuggest {
);
return null;
}
if (currentToken.length === 1 && Boolean(currentToken.match(this.tokenizer.getTrimPattern()))) {
if (currentPhrase.length === 1 && Boolean(currentPhrase.match(this.tokenizer.getTrimPattern("input")))) {
onReturnNull(
`Don't show suggestions because currentToken is TRIM_PATTERN`
`Don't show suggestions because currentPhrase is TRIM_PATTERN`
);
return null;
}
if (!this.runManually && !currentFrontMatter && currentToken.length < this.minNumberTriggered) {
if (!this.runManually && !currentFrontMatter && currentPhrase.length < this.minNumberTriggered) {
onReturnNull(
"Don't show suggestions because currentToken is less than minNumberTriggered option"
"Don't show suggestions because currentPhrase is less than minNumberTriggered option"
);
return null;
}
@@ -4417,19 +4446,30 @@ var AutoCompleteSuggest = class extends import_obsidian4.EditorSuggest {
}
showDebugLog(buildLogMessage("onTrigger", performance.now() - start));
this.runManually = false;
if (currentFrontMatter && ((_c = currentTokens.last()) == null ? void 0 : _c.word.match(/[^ ] $/))) {
const patterns = this.settings.phrasePatternsToSuppressTrigger;
const suppressedTokens = patterns.length === 0 || currentFrontMatter ? currentTokens : currentTokens.filter(
(t) => patterns.every((p) => !new RegExp(`^${p}$`).test(t.word))
);
if (suppressedTokens.length === 0) {
onReturnNull(
`Don't show suggestions because all tokens are ignored by token pattern: ${String.raw`^[\u3040-\u309F\u30A0-\u30FF]{1,2}$`}`
);
return null;
}
const currentToken = currentTokens.last().word;
if (currentFrontMatter && currentToken.match(/[^ ] $/)) {
currentTokens.push({ word: "", offset: currentLineUntilCursor.length });
}
this.contextStartCh = cursor.ch - currentToken.length;
this.contextStartCh = cursor.ch - currentPhrase.length;
return {
start: {
ch: cursor.ch - ((_f = (_e = (_d = currentTokens.last()) == null ? void 0 : _d.word) == null ? void 0 : _e.length) != null ? _f : 0),
ch: cursor.ch - ((_e = (_d = (_c = currentTokens.last()) == null ? void 0 : _c.word) == null ? void 0 : _d.length) != null ? _e : 0),
line: cursor.line
},
end: cursor,
query: JSON.stringify({
currentFrontMatter,
queries: currentTokens.map((x) => ({
queries: suppressedTokens.map((x) => ({
...x,
offset: x.offset - currentTokens[0].offset
}))
@@ -4660,6 +4700,7 @@ var DEFAULT_SETTINGS = {
insertAfterCompletion: true,
firstCharactersDisableSuggestions: ":/^",
patternsToSuppressTrigger: ["^~~~.*", "^```.*"],
phrasePatternsToSuppressTrigger: [],
noAutoFocusUntilCycle: false,
showMatchStrategy: true,
showComplementAutomatically: true,
@@ -4854,7 +4895,9 @@ var VariousComplementsSettingTab = class extends import_obsidian6.PluginSettingT
await this.plugin.saveSettings();
})
);
new import_obsidian6.Setting(containerEl).setName("Min number of characters for trigger").setDesc("It uses a default value of Strategy if set 0.").addSlider(
new import_obsidian6.Setting(containerEl).setName("Min number of characters for trigger").setDesc(
"Setting the value to 0 does not mean the suggestion will be triggered without any inputted character. Instead, a designated value will be used depending on the Strategy you choose."
).addSlider(
(sc) => sc.setLimits(0, 10, 1).setValue(this.plugin.settings.minNumberOfCharactersTriggered).setDynamicTooltip().onChange(async (value) => {
this.plugin.settings.minNumberOfCharactersTriggered = value;
await this.plugin.saveSettings();
@@ -4904,14 +4947,28 @@ var VariousComplementsSettingTab = class extends import_obsidian6.PluginSettingT
await this.plugin.saveSettings();
});
});
new import_obsidian6.Setting(containerEl).setName("Patterns to suppress trigger").setDesc(
"RegExp line patterns until the cursor, which suppresses the auto-completion trigger. It can set multi patterns by line breaks."
).addTextArea(
(tc) => tc.setValue(this.plugin.settings.patternsToSuppressTrigger.join("\n")).onChange(async (value) => {
new import_obsidian6.Setting(containerEl).setName("Line patterns to suppress trigger").setDesc(
"Regular expression line patterns (partial match) until the cursor, that suppresses the activation of autocomplete. Multiple patterns can be defined with line breaks."
).addTextArea((tc) => {
const el = tc.setValue(this.plugin.settings.patternsToSuppressTrigger.join("\n")).onChange(async (value) => {
this.plugin.settings.patternsToSuppressTrigger = smartLineBreakSplit(value);
await this.plugin.saveSettings();
})
);
});
el.inputEl.className = "various-complements__settings__text-area-path-dense";
return el;
});
new import_obsidian6.Setting(containerEl).setName("Phrase patterns to suppress trigger").setDesc(
"Regular expression patterns (exact match) that suppress the activation of autocomplete. Multiple patterns can be defined with line breaks."
).addTextArea((tc) => {
const el = tc.setValue(
this.plugin.settings.phrasePatternsToSuppressTrigger.join("\n")
).onChange(async (value) => {
this.plugin.settings.phrasePatternsToSuppressTrigger = smartLineBreakSplit(value);
await this.plugin.saveSettings();
});
el.inputEl.className = "various-complements__settings__text-area-path-dense";
return el;
});
new import_obsidian6.Setting(containerEl).setName("No auto-focus until the cycle").setDesc("No focus on the suggestions until the cycle key is pressed.").addToggle((tc) => {
tc.setValue(this.plugin.settings.noAutoFocusUntilCycle).onChange(
async (value) => {