mirror of
https://github.com/fancive/obsidian-parallel-reader.git
synced 2026-07-22 06:53:43 +00:00
fix: address all required issues from Obsidian plugin review bot
- Remove `parallel-reader-` prefix from command IDs (Obsidian auto-namespaces) - Remove default hotkeys to avoid conflicts with user keybindings - Replace `as TFile` casts with `instanceof TFile` checks - Make onunload sync, remove detachLeavesOfType (preserves leaf positions) - Use `vault.configDir` instead of hardcoded `.obsidian` - Replace `window.confirm` with Obsidian Modal dialog - Fix unhandled promises with `void` or `await` - Remove unnecessary `async` from methods without `await` - Use `new Setting().setHeading()` instead of raw HTML headings - Fix promise-returning callbacks in event listeners - Fix error type narrowing with `instanceof Error` - Apply sentence case to UI text labels Change-Id: I6e850d8a13b458d5cf1ad91227bf1772636b56b9
This commit is contained in:
parent
e0acce7f6d
commit
89d28d1113
7 changed files with 103 additions and 92 deletions
48
main.js
48
main.js
File diff suppressed because one or more lines are too long
75
main.ts
75
main.ts
|
|
@ -139,41 +139,41 @@ class ParallelReaderPlugin extends Plugin {
|
|||
this.registerView(VIEW_TYPE_PARALLEL, (leaf) => new ParallelReaderView(leaf, this));
|
||||
|
||||
this.addCommand({
|
||||
id: 'parallel-reader-run',
|
||||
id: 'run',
|
||||
name: this.t('cmdRun'),
|
||||
callback: () => this.runForActiveFile(false),
|
||||
});
|
||||
this.addCommand({
|
||||
id: 'parallel-reader-regen',
|
||||
id: 'regen',
|
||||
name: this.t('cmdRegen'),
|
||||
callback: () => this.runForActiveFile(true),
|
||||
});
|
||||
this.addCommand({
|
||||
id: 'parallel-reader-open-view',
|
||||
id: 'open-view',
|
||||
name: this.t('cmdOpenView'),
|
||||
callback: async () => {
|
||||
const active = this.getActiveView();
|
||||
await this.ensureView();
|
||||
if (active?.file) this.syncViewToFile(active.file);
|
||||
if (active?.file) void this.syncViewToFile(active.file);
|
||||
},
|
||||
});
|
||||
this.addCommand({
|
||||
id: 'parallel-reader-export-current',
|
||||
id: 'export-current',
|
||||
name: this.t('cmdExport'),
|
||||
callback: () => this.exportCurrentView(),
|
||||
});
|
||||
this.addCommand({
|
||||
id: 'parallel-reader-copy-current-markdown',
|
||||
id: 'copy-current-markdown',
|
||||
name: this.t('cmdCopyMarkdown'),
|
||||
callback: () => this.copyCurrentViewMarkdown(),
|
||||
});
|
||||
this.addCommand({
|
||||
id: 'parallel-reader-cancel-current',
|
||||
id: 'cancel-current',
|
||||
name: this.t('cmdCancel'),
|
||||
callback: () => this.cancelActiveGeneration(),
|
||||
});
|
||||
this.addCommand({
|
||||
id: 'parallel-reader-clear-current',
|
||||
id: 'clear-current',
|
||||
name: this.t('cmdClearCurrent'),
|
||||
callback: async () => {
|
||||
const active = this.getActiveView();
|
||||
|
|
@ -183,7 +183,7 @@ class ParallelReaderPlugin extends Plugin {
|
|||
},
|
||||
});
|
||||
this.addCommand({
|
||||
id: 'parallel-reader-clear-all',
|
||||
id: 'clear-all',
|
||||
name: this.t('cmdClearAll'),
|
||||
callback: async () => {
|
||||
const n = Object.keys(this.cacheManager.cache).length;
|
||||
|
|
@ -192,24 +192,22 @@ class ParallelReaderPlugin extends Plugin {
|
|||
},
|
||||
});
|
||||
this.addCommand({
|
||||
id: 'parallel-reader-card-prev',
|
||||
id: 'card-prev',
|
||||
name: this.t('cmdCardPrev'),
|
||||
hotkeys: [{ modifiers: ['Alt'], key: 'ArrowUp' }],
|
||||
callback: () => this.moveActiveCard(-1),
|
||||
});
|
||||
this.addCommand({
|
||||
id: 'parallel-reader-card-next',
|
||||
id: 'card-next',
|
||||
name: this.t('cmdCardNext'),
|
||||
hotkeys: [{ modifiers: ['Alt'], key: 'ArrowDown' }],
|
||||
callback: () => this.moveActiveCard(1),
|
||||
});
|
||||
this.addCommand({
|
||||
id: 'parallel-reader-card-jump',
|
||||
id: 'card-jump',
|
||||
name: this.t('cmdCardJump'),
|
||||
callback: () => this.jumpActiveCard(),
|
||||
});
|
||||
this.addCommand({
|
||||
id: 'parallel-reader-batch-generate',
|
||||
id: 'batch-generate',
|
||||
name: this.t('cmdBatchGenerate'),
|
||||
callback: () => this.runBatchForFolder(),
|
||||
});
|
||||
|
|
@ -219,19 +217,22 @@ class ParallelReaderPlugin extends Plugin {
|
|||
this.registerEvent(this.app.workspace.on('active-leaf-change', () => this.bindScrollSync()));
|
||||
this.registerEvent(
|
||||
this.app.workspace.on('file-open', (file) => {
|
||||
if (file) this.syncViewToFile(file);
|
||||
if (file) void this.syncViewToFile(file);
|
||||
}),
|
||||
);
|
||||
this.registerEvent(this.app.workspace.on('file-menu', (menu, file) => this.addFileMenuItems(menu, file)));
|
||||
this.registerEvent(this.app.vault.on('rename', (file, oldPath) => this.handleFileRename(file as TFile, oldPath)));
|
||||
this.registerEvent(this.app.vault.on('delete', (file) => this.handleFileDelete(file as TFile)));
|
||||
this.registerEvent(this.app.vault.on('rename', (file, oldPath) => {
|
||||
if (file instanceof TFile) void this.handleFileRename(file, oldPath);
|
||||
}));
|
||||
this.registerEvent(this.app.vault.on('delete', (file) => {
|
||||
if (file instanceof TFile) void this.handleFileDelete(file);
|
||||
}));
|
||||
this.bindScrollSync();
|
||||
}
|
||||
|
||||
async onunload() {
|
||||
await this.flushSettingsSave();
|
||||
await this.flushCacheSave();
|
||||
this.app.workspace.detachLeavesOfType(VIEW_TYPE_PARALLEL);
|
||||
onunload() {
|
||||
void this.flushSettingsSave();
|
||||
void this.flushCacheSave();
|
||||
}
|
||||
|
||||
/* ---------- Settings persistence ---------- */
|
||||
|
|
@ -242,7 +243,7 @@ class ParallelReaderPlugin extends Plugin {
|
|||
this.settings = normalizeSettings(Object.assign({}, DEFAULT_SETTINGS, settingsBlob));
|
||||
this.cacheManager = new CacheManager(
|
||||
this.app.vault.adapter,
|
||||
this.app.vault.configDir || '.obsidian',
|
||||
this.app.vault.configDir,
|
||||
this.manifest?.id || 'parallel-reader',
|
||||
() => this.settings,
|
||||
);
|
||||
|
|
@ -274,7 +275,7 @@ class ParallelReaderPlugin extends Plugin {
|
|||
|
||||
/* ---------- Cache delegation ---------- */
|
||||
|
||||
async cacheTouch(filePath: string) {
|
||||
cacheTouch(filePath: string) {
|
||||
return this.cacheManager.touch(filePath);
|
||||
}
|
||||
scheduleCacheSave(delayMs = 5000) {
|
||||
|
|
@ -302,7 +303,7 @@ class ParallelReaderPlugin extends Plugin {
|
|||
leaf = workspace.getRightLeaf(false)!;
|
||||
await leaf.setViewState({ type: VIEW_TYPE_PARALLEL, active: true });
|
||||
}
|
||||
workspace.revealLeaf(leaf);
|
||||
await workspace.revealLeaf(leaf);
|
||||
return leaf.view as ParallelReaderView;
|
||||
}
|
||||
|
||||
|
|
@ -363,10 +364,24 @@ class ParallelReaderPlugin extends Plugin {
|
|||
else new Notice(this.t('noCancelableJob'));
|
||||
}
|
||||
|
||||
confirmRegenerateEditedCards() {
|
||||
const message = this.t('confirmRegenerateEditedCards');
|
||||
if (typeof window !== 'undefined' && typeof window.confirm === 'function') return window.confirm(message);
|
||||
return true;
|
||||
confirmRegenerateEditedCards(): Promise<boolean> {
|
||||
return new Promise<boolean>((resolve) => {
|
||||
const message = this.t('confirmRegenerateEditedCards');
|
||||
const modal = new Modal(this.app);
|
||||
modal.titleEl.setText(this.t('displayName'));
|
||||
modal.contentEl.createEl('p', { text: message });
|
||||
const btnRow = modal.contentEl.createDiv({ cls: 'modal-button-container' });
|
||||
btnRow.createEl('button', { text: 'Cancel' }).addEventListener('click', () => {
|
||||
modal.close();
|
||||
resolve(false);
|
||||
});
|
||||
btnRow.createEl('button', { text: 'OK', cls: 'mod-cta' }).addEventListener('click', () => {
|
||||
modal.close();
|
||||
resolve(true);
|
||||
});
|
||||
modal.onClose = () => resolve(false);
|
||||
modal.open();
|
||||
});
|
||||
}
|
||||
|
||||
addFileMenuItems(menu: ObsidianMenu, file: unknown) {
|
||||
|
|
@ -477,7 +492,7 @@ class ParallelReaderPlugin extends Plugin {
|
|||
new Notice(this.t('alreadyGenerating'));
|
||||
return;
|
||||
}
|
||||
if (shouldConfirmRegenerate(this.cacheManager.get(file.path), force) && !this.confirmRegenerateEditedCards()) {
|
||||
if (shouldConfirmRegenerate(this.cacheManager.get(file.path), force) && !(await this.confirmRegenerateEditedCards())) {
|
||||
new Notice(this.t('regenerateCancelled'));
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ export class CacheManager {
|
|||
if (parsed && typeof parsed === 'object' && parsed.entries && typeof parsed.entries === 'object')
|
||||
return parsed.entries;
|
||||
} catch (e: unknown) {
|
||||
const message = String((e as Error)?.message || e || '');
|
||||
const message = e instanceof Error ? e.message : String(e);
|
||||
if (!/not found|does not exist|ENOENT/i.test(message))
|
||||
console.warn('[parallel-reader] failed to read cache.json', e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ export class GenerationJob {
|
|||
for (const handler of this._cancelHandlers.splice(0)) {
|
||||
try {
|
||||
handler();
|
||||
} catch (_) {}
|
||||
} catch { /* handler error ignored */ }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export class ParallelReaderSettingTab extends PluginSettingTab {
|
|||
const { containerEl } = this;
|
||||
const tr = (key: string, vars?: Record<string, string | number>) => this.plugin.t(key, vars);
|
||||
containerEl.empty();
|
||||
containerEl.createEl('h2', { text: tr('settingsTitle') });
|
||||
new Setting(containerEl).setName(tr('settingsTitle')).setHeading();
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(tr('settingUiLanguageName'))
|
||||
|
|
@ -64,7 +64,7 @@ export class ParallelReaderSettingTab extends PluginSettingTab {
|
|||
.setDesc(tr('settingBackendDesc'))
|
||||
.addDropdown((d) =>
|
||||
d
|
||||
.addOption('api', 'API / Provider')
|
||||
.addOption('api', 'API / provider')
|
||||
.addOption('claude-code', 'Claude Code CLI')
|
||||
.addOption('codex', 'Codex CLI')
|
||||
.setValue(this.plugin.settings.backend)
|
||||
|
|
@ -88,7 +88,7 @@ export class ParallelReaderSettingTab extends PluginSettingTab {
|
|||
t
|
||||
.setPlaceholder(tr('settingCliPathPlaceholder'))
|
||||
.setValue(this.plugin.settings.cliPath)
|
||||
.onChange(async (v) => {
|
||||
.onChange((v) => {
|
||||
this.plugin.settings.cliPath = v.trim();
|
||||
this.plugin.saveSettingsDebounced();
|
||||
}),
|
||||
|
|
@ -96,7 +96,7 @@ export class ParallelReaderSettingTab extends PluginSettingTab {
|
|||
}
|
||||
|
||||
if (!isCliBacked) {
|
||||
containerEl.createEl('h3', { text: tr('apiProviderHeader') });
|
||||
new Setting(containerEl).setName(tr('apiProviderHeader')).setHeading();
|
||||
}
|
||||
|
||||
if (!isCliBacked) {
|
||||
|
|
@ -140,7 +140,7 @@ export class ParallelReaderSettingTab extends PluginSettingTab {
|
|||
: preset.baseUrl || API_FORMATS[getApiFormat(this.plugin.settings)].defaultBaseUrl,
|
||||
)
|
||||
.setValue(this.plugin.settings.apiBaseUrl)
|
||||
.onChange(async (v) => {
|
||||
.onChange((v) => {
|
||||
this.plugin.settings.apiBaseUrl = v.trim();
|
||||
this.plugin.saveSettingsDebounced();
|
||||
}),
|
||||
|
|
@ -154,7 +154,7 @@ export class ParallelReaderSettingTab extends PluginSettingTab {
|
|||
return t
|
||||
.setPlaceholder('sk-...')
|
||||
.setValue(this.plugin.settings.apiKey)
|
||||
.onChange(async (v) => {
|
||||
.onChange((v) => {
|
||||
this.plugin.settings.apiKey = v.trim();
|
||||
this.plugin.saveSettingsDebounced();
|
||||
});
|
||||
|
|
@ -167,7 +167,7 @@ export class ParallelReaderSettingTab extends PluginSettingTab {
|
|||
t
|
||||
.setPlaceholder(preset.envVar || 'OPENAI_API_KEY')
|
||||
.setValue(this.plugin.settings.apiKeyEnvVar)
|
||||
.onChange(async (v) => {
|
||||
.onChange((v) => {
|
||||
this.plugin.settings.apiKeyEnvVar = v.trim();
|
||||
this.plugin.saveSettingsDebounced();
|
||||
}),
|
||||
|
|
@ -193,14 +193,14 @@ export class ParallelReaderSettingTab extends PluginSettingTab {
|
|||
t
|
||||
.setPlaceholder('cf-aig-authorization: Bearer ...')
|
||||
.setValue(this.plugin.settings.apiHeaders)
|
||||
.onChange(async (v) => {
|
||||
.onChange((v) => {
|
||||
this.plugin.settings.apiHeaders = v;
|
||||
this.plugin.saveSettingsDebounced();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl).setName(tr('settingMaxTokensName')).addText((t) =>
|
||||
t.setValue(String(this.plugin.settings.apiMaxTokens)).onChange(async (v) => {
|
||||
t.setValue(String(this.plugin.settings.apiMaxTokens)).onChange((v) => {
|
||||
const n = parseInt(v, 10);
|
||||
if (!Number.isNaN(n) && n > 0) {
|
||||
this.plugin.settings.apiMaxTokens = n;
|
||||
|
|
@ -227,7 +227,7 @@ export class ParallelReaderSettingTab extends PluginSettingTab {
|
|||
t
|
||||
.setPlaceholder(isCliBacked ? DEFAULT_SETTINGS.model : getApiPreset(this.plugin.settings).model || 'model-id')
|
||||
.setValue(this.plugin.settings.model)
|
||||
.onChange(async (v) => {
|
||||
.onChange((v) => {
|
||||
this.plugin.settings.model = v.trim() || (isCliBacked ? DEFAULT_SETTINGS.model : '');
|
||||
this.plugin.saveSettingsDebounced();
|
||||
}),
|
||||
|
|
@ -237,7 +237,7 @@ export class ParallelReaderSettingTab extends PluginSettingTab {
|
|||
.setName(tr('settingMaxInputName'))
|
||||
.setDesc(tr('settingMaxInputDesc'))
|
||||
.addText((t) =>
|
||||
t.setValue(String(this.plugin.settings.maxDocChars || DEFAULT_SETTINGS.maxDocChars)).onChange(async (v) => {
|
||||
t.setValue(String(this.plugin.settings.maxDocChars || DEFAULT_SETTINGS.maxDocChars)).onChange((v) => {
|
||||
const n = parseInt(v, 10);
|
||||
if (!Number.isNaN(n) && n >= 1000) {
|
||||
this.plugin.settings.maxDocChars = n;
|
||||
|
|
@ -246,7 +246,7 @@ export class ParallelReaderSettingTab extends PluginSettingTab {
|
|||
}),
|
||||
);
|
||||
|
||||
containerEl.createEl('h3', { text: tr('promptHeader') });
|
||||
new Setting(containerEl).setName(tr('promptHeader')).setHeading();
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(tr('settingPromptLanguageName'))
|
||||
|
|
@ -270,7 +270,7 @@ export class ParallelReaderSettingTab extends PluginSettingTab {
|
|||
t
|
||||
.setPlaceholder('min')
|
||||
.setValue(String(this.plugin.settings.minCards || DEFAULT_SETTINGS.minCards))
|
||||
.onChange(async (v) => {
|
||||
.onChange((v) => {
|
||||
const n = parseInt(v, 10);
|
||||
if (!Number.isNaN(n) && n > 0) {
|
||||
this.plugin.settings.minCards = n;
|
||||
|
|
@ -283,7 +283,7 @@ export class ParallelReaderSettingTab extends PluginSettingTab {
|
|||
t
|
||||
.setPlaceholder('max')
|
||||
.setValue(String(this.plugin.settings.maxCards || DEFAULT_SETTINGS.maxCards))
|
||||
.onChange(async (v) => {
|
||||
.onChange((v) => {
|
||||
const n = parseInt(v, 10);
|
||||
if (!Number.isNaN(n) && n > 0) {
|
||||
this.plugin.settings.maxCards = Math.max(n, this.plugin.settings.minCards || DEFAULT_SETTINGS.minCards);
|
||||
|
|
@ -300,7 +300,7 @@ export class ParallelReaderSettingTab extends PluginSettingTab {
|
|||
return t
|
||||
.setPlaceholder(tr('settingCustomPromptPlaceholder'))
|
||||
.setValue(this.plugin.settings.customSystemPrompt || '')
|
||||
.onChange(async (v) => {
|
||||
.onChange((v) => {
|
||||
this.plugin.settings.customSystemPrompt = v;
|
||||
this.plugin.saveSettingsDebounced();
|
||||
});
|
||||
|
|
@ -324,13 +324,13 @@ export class ParallelReaderSettingTab extends PluginSettingTab {
|
|||
.setName(tr('settingExportFolderName'))
|
||||
.setDesc(tr('settingExportFolderDesc'))
|
||||
.addText((t) =>
|
||||
t.setValue(this.plugin.settings.exportFolder).onChange(async (v) => {
|
||||
t.setValue(this.plugin.settings.exportFolder).onChange((v) => {
|
||||
this.plugin.settings.exportFolder = v.trim() || DEFAULT_SETTINGS.exportFolder;
|
||||
this.plugin.saveSettingsDebounced();
|
||||
}),
|
||||
);
|
||||
|
||||
containerEl.createEl('h3', { text: tr('cacheHeader') });
|
||||
new Setting(containerEl).setName(tr('cacheHeader')).setHeading();
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(tr('settingMaxCacheName'))
|
||||
|
|
@ -347,7 +347,7 @@ export class ParallelReaderSettingTab extends PluginSettingTab {
|
|||
this.display();
|
||||
}
|
||||
};
|
||||
t.inputEl.addEventListener('change', commit);
|
||||
t.inputEl.addEventListener('change', () => { void commit(); });
|
||||
t.inputEl.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Enter') t.inputEl.blur();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -13,15 +13,13 @@ export function addIconButton(parent: HTMLElement, icon: string, title: string,
|
|||
} else {
|
||||
button.textContent = title;
|
||||
}
|
||||
button.addEventListener('click', async (e) => {
|
||||
button.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
try {
|
||||
await onClick();
|
||||
} catch (err: unknown) {
|
||||
Promise.resolve(onClick()).catch((err: unknown) => {
|
||||
console.error(err);
|
||||
new Notice(`${title} failed: ` + ((err as Error).message || err));
|
||||
}
|
||||
new Notice(`${title} failed: ${err instanceof Error ? err.message : String(err)}`);
|
||||
});
|
||||
});
|
||||
return button;
|
||||
}
|
||||
|
|
@ -39,15 +37,13 @@ export function addTextButton(
|
|||
});
|
||||
if (icon && typeof setIcon === 'function') setIcon(button, icon);
|
||||
button.createSpan({ text: label });
|
||||
button.addEventListener('click', async (e) => {
|
||||
button.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
try {
|
||||
await onClick();
|
||||
} catch (err: unknown) {
|
||||
Promise.resolve(onClick()).catch((err: unknown) => {
|
||||
console.error(err);
|
||||
new Notice(`${label} failed: ` + ((err as Error).message || err));
|
||||
}
|
||||
new Notice(`${label} failed: ${err instanceof Error ? err.message : String(err)}`);
|
||||
});
|
||||
});
|
||||
return button;
|
||||
}
|
||||
|
|
@ -57,6 +53,6 @@ export async function copyToClipboard(text: string, successMsg: string) {
|
|||
await navigator.clipboard.writeText(text);
|
||||
new Notice(successMsg);
|
||||
} catch (e: unknown) {
|
||||
new Notice('Copy failed: ' + ((e as Error).message || e));
|
||||
new Notice(`Copy failed: ${e instanceof Error ? e.message : String(e)}`);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
10
src/view.ts
10
src/view.ts
|
|
@ -76,7 +76,7 @@ export class ParallelReaderView extends ItemView {
|
|||
return true;
|
||||
}
|
||||
|
||||
async loadFor(file: TFile, sections: ResolvedCard[], stale: boolean) {
|
||||
loadFor(file: TFile, sections: ResolvedCard[], stale: boolean) {
|
||||
this.sourceFile = file;
|
||||
this.sections = sections;
|
||||
this.stale = !!stale;
|
||||
|
|
@ -85,7 +85,7 @@ export class ParallelReaderView extends ItemView {
|
|||
this.render();
|
||||
}
|
||||
|
||||
async renderLoading(file: TFile, message: string) {
|
||||
renderLoading(file: TFile, message: string) {
|
||||
this.sourceFile = file;
|
||||
this.sections = [];
|
||||
this.stale = false;
|
||||
|
|
@ -127,7 +127,7 @@ export class ParallelReaderView extends ItemView {
|
|||
pre.textContent = text.slice(-2000);
|
||||
}
|
||||
|
||||
async renderError(file: TFile, message: string) {
|
||||
renderError(file: TFile, message: string) {
|
||||
this.sourceFile = file;
|
||||
this.sections = [];
|
||||
this.stale = false;
|
||||
|
|
@ -243,7 +243,7 @@ export class ParallelReaderView extends ItemView {
|
|||
if (sel && sel.toString().length > 0) return;
|
||||
const target = e.target as HTMLElement | null;
|
||||
if (target && target.tagName === 'A') return;
|
||||
if (s.startLine >= 0) this.plugin.scrollEditorToLine(s.startLine, this.sourceFile);
|
||||
if (s.startLine >= 0) void this.plugin.scrollEditorToLine(s.startLine, this.sourceFile);
|
||||
});
|
||||
|
||||
card.addEventListener('contextmenu', (e) => {
|
||||
|
|
@ -323,7 +323,7 @@ export class ParallelReaderView extends ItemView {
|
|||
jumpToActiveSection() {
|
||||
const line = activeSectionLine(this.sections, this.activeIdx);
|
||||
if (line < 0 || !this.sourceFile) return -1;
|
||||
this.plugin.scrollEditorToLine(line, this.sourceFile);
|
||||
void this.plugin.scrollEditorToLine(line, this.sourceFile);
|
||||
return line;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue