refactor: restore strict lint hygiene

Change-Id: I26917328ec55e529242dfd8e4c42af0b3fcd58b7
This commit is contained in:
wujunchen 2026-04-26 17:41:28 +08:00
parent 89e1ab9d5c
commit 9ed36570b5
8 changed files with 89 additions and 52 deletions

46
main.js

File diff suppressed because one or more lines are too long

54
main.ts
View file

@ -73,12 +73,10 @@ async function summarizeDocument(
break;
default: {
const useStreaming = supportsStreaming(settings);
const abortController = useStreaming ? new AbortController() : null;
if (abortController) {
job.onCancel(() => abortController.abort());
}
if (useStreaming) {
cards = await summarizeViaApiStreaming(system, user, settings, onStreamProgress, abortController!.signal);
const abortController = new AbortController();
job.onCancel(() => abortController.abort());
cards = await summarizeViaApiStreaming(system, user, settings, onStreamProgress, abortController.signal);
} else {
cards = await summarizeViaApi(requestUrl, system, user, settings);
}
@ -132,7 +130,8 @@ class ParallelReaderPlugin extends Plugin {
this.addRibbonIcon('book-open', this.t('ribbonOpen'), async () => {
const active = this.getActiveView();
await this.ensureView();
const view = await this.ensureView();
if (!view) return;
if (active?.file) await this.syncViewToFile(active.file);
});
@ -153,7 +152,8 @@ class ParallelReaderPlugin extends Plugin {
name: this.t('cmdOpenView'),
callback: async () => {
const active = this.getActiveView();
await this.ensureView();
const view = await this.ensureView();
if (!view) return;
if (active?.file) void this.syncViewToFile(active.file);
},
});
@ -221,12 +221,16 @@ class ParallelReaderPlugin extends Plugin {
}),
);
this.registerEvent(this.app.workspace.on('file-menu', (menu, file) => this.addFileMenuItems(menu, file)));
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.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();
}
@ -296,11 +300,16 @@ class ParallelReaderPlugin extends Plugin {
/* ---------- View management ---------- */
async ensureView() {
async ensureView(): Promise<ParallelReaderView | null> {
const { workspace } = this.app;
let leaf = workspace.getLeavesOfType(VIEW_TYPE_PARALLEL)[0];
if (!leaf) {
leaf = workspace.getRightLeaf(false)!;
const newLeaf = workspace.getRightLeaf(false);
if (!newLeaf) {
new Notice(this.t('viewOpenFailed'));
return null;
}
leaf = newLeaf;
await leaf.setViewState({ type: VIEW_TYPE_PARALLEL, active: true });
}
await workspace.revealLeaf(leaf);
@ -446,6 +455,7 @@ class ParallelReaderPlugin extends Plugin {
async exportCurrentView() {
const active = this.getActiveView();
const view = await this.ensureView();
if (!view) return;
if (!view.sourceFile || !view.sections.length) {
if (active?.file) await this.syncViewToFile(active.file);
}
@ -459,6 +469,7 @@ class ParallelReaderPlugin extends Plugin {
async copyCurrentViewMarkdown() {
const active = this.getActiveView();
const view = await this.ensureView();
if (!view) return;
if (!view.sourceFile || !view.sections.length) {
if (active?.file) await this.syncViewToFile(active.file);
}
@ -492,7 +503,10 @@ class ParallelReaderPlugin extends Plugin {
new Notice(this.t('alreadyGenerating'));
return;
}
if (shouldConfirmRegenerate(this.cacheManager.get(file.path), force) && !(await this.confirmRegenerateEditedCards())) {
if (
shouldConfirmRegenerate(this.cacheManager.get(file.path), force) &&
!(await this.confirmRegenerateEditedCards())
) {
new Notice(this.t('regenerateCancelled'));
return;
}
@ -509,6 +523,7 @@ class ParallelReaderPlugin extends Plugin {
}
view = await this.ensureView();
if (!view) return;
job.throwIfCancelled();
job.setPhase('cache-check');
@ -528,10 +543,11 @@ class ParallelReaderPlugin extends Plugin {
new Notice(this.t('generatingNotice'));
job.setPhase('generating');
const streamProgress = view
const streamingView = view;
const streamProgress = streamingView
? (progress: StreamProgress) => {
if (!progress.done && this.viewIsShowingFile(view, file)) {
view!.renderStreamingPreview(file, progress.accumulated);
if (!progress.done && this.viewIsShowingFile(streamingView, file)) {
streamingView.renderStreamingPreview(file, progress.accumulated);
}
}
: undefined;

View file

@ -115,10 +115,19 @@ export function runCli(
});
}
child.stdout!.on('data', (d) => {
if (!child.stdout || !child.stderr || !child.stdin) {
fail(new Error('CLI process streams are unavailable'));
return;
}
const childStdout = child.stdout;
const childStderr = child.stderr;
const childStdin = child.stdin;
childStdout.on('data', (d) => {
stdout += d.toString('utf8');
});
child.stderr!.on('data', (d) => {
childStderr.on('data', (d) => {
stderr += d.toString('utf8');
});
child.on('error', (e) => {
@ -134,14 +143,14 @@ export function runCli(
if (stdinText) {
try {
child.stdin!.write(stdinText);
child.stdin!.end();
childStdin.write(stdinText);
childStdin.end();
} catch (_e) {
// Child may have exited before stdin was written.
}
} else {
try {
child.stdin!.end();
childStdin.end();
} catch (_) {
/* ignore */
}

View file

@ -64,7 +64,9 @@ export class GenerationJob {
for (const handler of this._cancelHandlers.splice(0)) {
try {
handler();
} catch { /* handler error ignored */ }
} catch {
/* handler error ignored */
}
}
return true;
}

View file

@ -58,6 +58,7 @@ export const STRINGS: Record<string, Record<string, string>> = {
noExportContent: '当前没有可导出的对照笔记',
noCopyContent: '当前没有可复制的对照笔记',
noActiveCard: '当前没有可跳转的摘要卡片',
viewOpenFailed: '无法打开对照笔记面板',
confirmRegenerateEditedCards: '这篇笔记的对照卡片已被手动编辑。重新生成会覆盖这些修改,是否继续?',
regenerateCancelled: '已取消重新生成',
cardDeleted: '已删除此卡片',
@ -208,6 +209,7 @@ export const STRINGS: Record<string, Record<string, string>> = {
noExportContent: 'No parallel notes to export',
noCopyContent: 'No parallel notes to copy',
noActiveCard: 'No active summary card to jump',
viewOpenFailed: 'Could not open the Parallel Reader pane',
confirmRegenerateEditedCards:
'These parallel-reader cards were edited manually. Regenerating will overwrite those edits. Continue?',
regenerateCancelled: 'Regeneration cancelled',

View file

@ -32,6 +32,12 @@ type RequestUrlFunction = (params: {
throw?: boolean;
}) => Promise<{ status: number; json: unknown; text: string }>;
function requiredDeltaExtractor(format: string) {
const extractor = deltaExtractorForFormat(format);
if (!extractor) throw new Error(`Streaming not supported for format: ${format}`);
return extractor;
}
interface AnthropicMessagesBody {
model: string;
max_tokens: number;
@ -506,7 +512,7 @@ async function streamSummarizeViaOpenAiChat(
const headers = buildApiHeaders(settings);
const body = buildOpenAiChatBody(system, user, settings, { structured: false });
body.stream = true;
const extractor = deltaExtractorForFormat('openai-chat')!;
const extractor = requiredDeltaExtractor('openai-chat');
const text = await streamingFetch(url, headers, body, extractor, onProgress, signal, settings);
return parseCardsJson(text.trim(), settings);
}
@ -522,7 +528,7 @@ async function streamSummarizeViaAnthropicMessages(
const headers = buildApiHeaders(settings, { 'anthropic-version': '2023-06-01' });
const body = buildAnthropicMessagesBody(system, user, settings, { structured: false });
body.stream = true;
const extractor = deltaExtractorForFormat('anthropic-messages')!;
const extractor = requiredDeltaExtractor('anthropic-messages');
const text = await streamingFetch(url, headers, body, extractor, onProgress, signal, settings);
return parseCardsJson(text.trim(), settings);
}

View file

@ -347,7 +347,9 @@ export class ParallelReaderSettingTab extends PluginSettingTab {
this.display();
}
};
t.inputEl.addEventListener('change', () => { void commit(); });
t.inputEl.addEventListener('change', () => {
void commit();
});
t.inputEl.addEventListener('keydown', (e) => {
if (e.key === 'Enter') t.inputEl.blur();
});

View file

@ -45,7 +45,7 @@ export function deltaExtractorForFormat(format: string): DeltaExtractor | null {
export function parseSseBuffer(buffer: string, extractDelta: DeltaExtractor): { deltas: string[]; rest: string } {
const deltas: string[] = [];
const lines = buffer.split('\n');
const rest = lines.pop()!; // keep incomplete line
const rest = lines.pop() ?? ''; // keep incomplete line
for (const line of lines) {
const trimmed = line.trim();