mirror of
https://github.com/jacobinwwey/obsidian-NotEMD.git
synced 2026-07-22 05:48:27 +00:00
1.6.0 mermaid error update
This commit is contained in:
parent
74ba2a8580
commit
9e185e2370
9 changed files with 1325 additions and 68 deletions
|
|
@ -251,6 +251,9 @@ Access plugin settings via:
|
|||
* **On**: Allows you to specify a custom output folder and filename suffix.
|
||||
|
||||
#### Batch Mermaid Fix
|
||||
- **Enable Mermaid Error Detection**:
|
||||
* **Off (Default)**: Error detection is skipped after processing.
|
||||
* **On**: Scans processed files for remaining Mermaid syntax errors and generates a `mermaid_error_{foldername}.md` report.
|
||||
- **Move files with Mermaid errors to specified folder**:
|
||||
* **Off**: Files with errors remain in place.
|
||||
* **On**: Moves any files that still contain Mermaid syntax errors after the fix attempt to a dedicated folder for manual review.
|
||||
|
|
|
|||
|
|
@ -296,6 +296,9 @@ Notemd 通过与各种大型语言模型 (LLM) 集成来增强您的 Obsidian
|
|||
* **开启**: 允许您指定自定义输出文件夹和文件名后缀。
|
||||
|
||||
#### 批量Mermaid修复
|
||||
- **启用Mermaid错误检测**:
|
||||
* **关闭 (默认)**: 处理后跳过错误检测。
|
||||
* **开启**: 扫描处理后的文件以查找剩余的Mermaid语法错误,并生成 `mermaid_error_{foldername}.md` 报告。
|
||||
- **将存在Mermaid错误的文件移动到指定文件夹**:
|
||||
* **关闭**: 有错误的文件保留在原位。
|
||||
* **开启**: 将修复尝试后仍包含Mermaid语法错误的文件移动到专用文件夹以供手动审查。
|
||||
|
|
|
|||
1264
package-lock.json
generated
1264
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -34,6 +34,9 @@
|
|||
"obsidian": "latest",
|
||||
"ts-jest": "^29.3.2",
|
||||
"tslib": "2.4.0",
|
||||
"typescript": "4.7.4"
|
||||
"typescript": "^5.9.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"mermaid": "^11.12.2"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -225,6 +225,7 @@ export const DEFAULT_SETTINGS: NotemdSettings = {
|
|||
extractOriginalTextCustomSuffix: '_Extracted',
|
||||
useCustomPromptForExtractOriginalText: false,
|
||||
customPromptExtractOriginalText: '',
|
||||
enableMermaidErrorDetection: false,
|
||||
moveMermaidErrorFiles: false,
|
||||
mermaidErrorFolderPath: 'MermaidErrors',
|
||||
};
|
||||
|
|
|
|||
104
src/fileUtils.ts
104
src/fileUtils.ts
|
|
@ -8,6 +8,7 @@ import { callDeepSeekAPI, callOpenAIApi, callAnthropicApi, callGoogleApi, callMi
|
|||
import { refineMermaidBlocks, cleanupLatexDelimiters } from './mermaidProcessor'; // Assuming this will be moved or imported correctly later
|
||||
import { _performResearch } from './searchUtils'; // Assuming this will be moved or imported correctly later
|
||||
import { showDeletionConfirmationModal } from './ui/modals'; // Assuming this will be moved or imported correctly later
|
||||
import mermaid from 'mermaid';
|
||||
|
||||
// --- Backlink and Note Management ---
|
||||
|
||||
|
|
@ -969,57 +970,50 @@ export async function batchFixMermaidSyntaxInFolder(app: App, settings: NotemdSe
|
|||
progressReporter.log(`➖ No changes needed for: ${file.name}`);
|
||||
}
|
||||
|
||||
// Post-fix check for remaining errors
|
||||
// Read content again (fixMermaidSyntaxInFile might have modified it)
|
||||
const content = await app.vault.read(file);
|
||||
let fileErrorCount = 0;
|
||||
// Simple heuristic regex to find potentially broken nodes: Node[...] where content has space/CJK and NOT quoted
|
||||
// We reuse the logic from refinedMermaidBlocks but just for detection
|
||||
const lines = content.split('\n');
|
||||
let inMermaid = false;
|
||||
for (const line of lines) {
|
||||
if (/^```\s*\(?\s*mermaid\s*\)?/.test(line)) { inMermaid = true; continue; }
|
||||
if (line.trim() === '```') { inMermaid = false; continue; }
|
||||
if (inMermaid) {
|
||||
// Check for Node[...] that isn't quoted but should be
|
||||
// We search for matches that refinedMermaidBlocks WOULD catch but maybe missed or are new?
|
||||
// Actually, if refineMermaidBlocks worked, these should be fixed.
|
||||
// The user says "which files still contain Mermaid errors".
|
||||
// Let's assume if we find any `Node[...]` where `...` contains spaces/CJK and isn't `"... "`, it's an error.
|
||||
// Regex: (\S+)\[([^"\]]+)\] where group 2 has spaces or CJK
|
||||
// Exclude matches that look like `Node["..."]` (already handled by [^"])
|
||||
// But `Node[Label]` is valid if Label is simple.
|
||||
// Only error if Label has spaces or CJK.
|
||||
// Also excluding lines with 'subgraph' as they might be handled differently or valid.
|
||||
if (!line.includes('subgraph')) {
|
||||
const brokenNodeRegex = /(\S+)\[([^"\]]+)\]/g;
|
||||
let match;
|
||||
while ((match = brokenNodeRegex.exec(line)) !== null) {
|
||||
const content = match[2];
|
||||
if (/[ \u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]/.test(content)) {
|
||||
fileErrorCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Post-fix check for remaining errors (if enabled)
|
||||
if (settings.enableMermaidErrorDetection) {
|
||||
// Read content again (fixMermaidSyntaxInFile might have modified it)
|
||||
const content = await app.vault.read(file);
|
||||
let fileErrorCount = 0;
|
||||
|
||||
// Robust Regex to find mermaid blocks:
|
||||
// 1. Matches indentation (Start of line + spaces/tabs)
|
||||
// 2. Matches ``` or ~~~ fences
|
||||
// 3. Matches 'mermaid' (case insensitive via flags)
|
||||
// 4. Captures content inside
|
||||
const mermaidBlockRegex = /^(?:[ \t]*)(?:```|~~~)\s*mermaid\b[^\n]*\n([\s\S]*?)\n(?:[ \t]*)(?:```|~~~)/gim;
|
||||
let match;
|
||||
|
||||
while ((match = mermaidBlockRegex.exec(content)) !== null) {
|
||||
const blockContent = match[1];
|
||||
try {
|
||||
// Use the imported mermaid library to validate syntax
|
||||
// mermaid.parse throws an error if the code is invalid
|
||||
await mermaid.parse(blockContent);
|
||||
} catch (parseErr) {
|
||||
fileErrorCount++;
|
||||
// Optional: detailed logging if needed
|
||||
// console.log(`Mermaid parse error in ${file.name}:`, parseErr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fileErrorCount > 0) {
|
||||
mermaidErrors.push({ filename: file.name, count: fileErrorCount });
|
||||
// Move file if enabled
|
||||
if (errorMoveFolder) {
|
||||
const destPath = `${errorMoveFolder}/${file.name}`;
|
||||
if (file.parent?.path !== errorMoveFolder) {
|
||||
try {
|
||||
// Check if dest exists
|
||||
if (app.vault.getAbstractFileByPath(destPath)) {
|
||||
progressReporter.log(`⚠️ Destination ${destPath} exists. Skipping move for ${file.name}.`);
|
||||
} else {
|
||||
await app.vault.rename(file, destPath);
|
||||
progressReporter.log(`Moved error file to: ${destPath}`);
|
||||
if (fileErrorCount > 0) {
|
||||
mermaidErrors.push({ filename: file.name, count: fileErrorCount });
|
||||
// Move file if enabled
|
||||
if (errorMoveFolder) {
|
||||
const destPath = `${errorMoveFolder}/${file.name}`;
|
||||
if (file.parent?.path !== errorMoveFolder) {
|
||||
try {
|
||||
// Check if dest exists
|
||||
if (app.vault.getAbstractFileByPath(destPath)) {
|
||||
progressReporter.log(`⚠️ Destination ${destPath} exists. Skipping move for ${file.name}.`);
|
||||
} else {
|
||||
await app.vault.rename(file, destPath);
|
||||
progressReporter.log(`Moved error file to: ${destPath}`);
|
||||
}
|
||||
} catch (moveErr: any) {
|
||||
progressReporter.log(`Error moving file ${file.name}: ${moveErr.message}`);
|
||||
}
|
||||
} catch (moveErr: any) {
|
||||
progressReporter.log(`Error moving file ${file.name}: ${moveErr.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1047,18 +1041,12 @@ export async function batchFixMermaidSyntaxInFolder(app: App, settings: NotemdSe
|
|||
}
|
||||
|
||||
// Generate Error Report
|
||||
if (mermaidErrors.length > 0) {
|
||||
if (settings.enableMermaidErrorDetection && mermaidErrors.length > 0) {
|
||||
const folderName = folder.name === '/' ? 'Root' : folder.name;
|
||||
const reportFileName = `mermaid_error_${folderName}.md`;
|
||||
// Determine save path: current directory implies root or same level? User said "within the current directory".
|
||||
// Usually, putting it in the root is safest/easiest to find.
|
||||
const reportContent = mermaidErrors.map(e => `[[${e.filename}]]-[${e.count}]`).join(''); // User requested single line per entry?
|
||||
// "structured and output as a single line per entry" -> usually means one line in the file per error entry?
|
||||
// OR "output as a single line per entry" -> [[File]]-[Count]\n[[File]]-[Count]
|
||||
// Example: `[[First error filename]]-[Number of faulty Mermaid diagrams][[Second error filename]]-[Number of faulty Mermaid diagrams]...`
|
||||
// Wait, the example shows them ALL on one line concatenated?
|
||||
// `[[First error filename]]-[Number of faulty Mermaid diagrams][[Second error filename]]-[Number of faulty Mermaid diagrams]...`
|
||||
// This is unusual but I will follow the example literally: Concatenated string.
|
||||
|
||||
// Use triple newline to match the requested format's spacing
|
||||
const reportContent = mermaidErrors.map(e => `[[${e.filename}]]-[${e.count}]`).join('\n\n\n');
|
||||
|
||||
try {
|
||||
const reportFile = app.vault.getAbstractFileByPath(reportFileName);
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ export const mockSettings: NotemdSettings = {
|
|||
extractOriginalTextUseCustomOutput: false,
|
||||
extractOriginalTextCustomPath: '',
|
||||
extractOriginalTextCustomSuffix: '',
|
||||
enableMermaidErrorDetection: false,
|
||||
moveMermaidErrorFiles: false,
|
||||
mermaidErrorFolderPath: '',
|
||||
};
|
||||
|
|
|
|||
|
|
@ -134,6 +134,7 @@ export interface NotemdSettings {
|
|||
extractOriginalTextCustomSuffix: string; // New
|
||||
useCustomPromptForExtractOriginalText: boolean;
|
||||
customPromptExtractOriginalText: string;
|
||||
enableMermaidErrorDetection: boolean; // New
|
||||
moveMermaidErrorFiles: boolean; // New
|
||||
mermaidErrorFolderPath: string; // New
|
||||
}
|
||||
|
|
|
|||
|
|
@ -712,6 +712,17 @@ export class NotemdSettingTab extends PluginSettingTab {
|
|||
// --- Batch Mermaid Fix Settings ---
|
||||
new Setting(containerEl).setName('Batch Mermaid fix').setHeading();
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('Enable Mermaid Error Detection')
|
||||
.setDesc('On: Scan files for Mermaid syntax errors after fixing and generate a report. Off: Skip error detection.')
|
||||
.addToggle(toggle => toggle
|
||||
.setValue(this.plugin.settings.enableMermaidErrorDetection)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.enableMermaidErrorDetection = value;
|
||||
await this.plugin.saveSettings();
|
||||
this.display(); // Refresh to show/hide related settings if needed
|
||||
}));
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('Move files with Mermaid errors to specified folder')
|
||||
.setDesc('On: Move any files that still contain Mermaid errors after fixing to a designated folder.')
|
||||
|
|
|
|||
Loading…
Reference in a new issue