diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 6f3df54..4a26ba6 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@claude-prism/desktop", - "version": "1.1.1", + "version": "1.1.2", "private": true, "type": "module", "scripts": { diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index 61a68b1..7784ec0 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -2,7 +2,7 @@ "$schema": "https://raw.githubusercontent.com/nicegui-unofficial/nicegui-tauri-template/main/src-tauri/tauri.conf-v2-schema.json", "identifier": "com.claude-prism.desktop", "productName": "ClaudePrism", - "version": "1.1.1", + "version": "1.1.2", "build": { "beforeDevCommand": "pnpm dev", "beforeBuildCommand": "pnpm build", diff --git a/apps/desktop/src/lib/latex-compiler.ts b/apps/desktop/src/lib/latex-compiler.ts index 4333a07..dc2f230 100644 --- a/apps/desktop/src/lib/latex-compiler.ts +++ b/apps/desktop/src/lib/latex-compiler.ts @@ -5,6 +5,8 @@ import { createLogger } from "@/lib/debug/logger"; const log = createLogger("latex"); /** Resolve which file to compile and the root ID for caching. + * resolveTexRoot now handles \documentclass detection and main.tex fallback, + * so the only remaining fallback here is for projects with no .tex files. * Returns `null` when the project has no compilable .tex file. */ export function resolveCompileTarget( activeFileId: string, @@ -15,19 +17,11 @@ export function resolveCompileTarget( if (rootEntry?.type === "tex") { return { rootId, targetPath: rootEntry.relativePath }; } - // Fallback: look for any well-known root tex file - const fallback = files.find( - (f) => f.name === "main.tex" || f.name === "document.tex", - ); - if (fallback) { - return { rootId: fallback.id, targetPath: fallback.relativePath }; - } - // Final fallback: use the first available .tex file in the project + // No .tex file exists — cannot compile const anyTex = files.find((f) => f.type === "tex"); if (anyTex) { return { rootId: anyTex.id, targetPath: anyTex.relativePath }; } - // No .tex file exists — cannot compile return null; } diff --git a/apps/desktop/src/stores/document-store.ts b/apps/desktop/src/stores/document-store.ts index dfe74a6..32cecc8 100644 --- a/apps/desktop/src/stores/document-store.ts +++ b/apps/desktop/src/stores/document-store.ts @@ -148,25 +148,57 @@ function getActiveFile(state: { files: ProjectFile[]; activeFileId: string }) { /** * Resolve the root .tex file for compilation. - * Parses `% !TEX root = ` magic comment from the first 20 lines. - * Returns the root file's ID (relativePath), or the input fileId if no root is specified. + * + * Priority order: + * 1. `% !TEX root = ` magic comment in the first 20 lines of the active file + * 2. The file itself, if it contains `\documentclass` + * 3. `main.tex` or `document.tex` that contains `\documentclass` + * 4. Any other .tex file in the project that contains `\documentclass` + * 5. Fallback: the active file itself */ export function resolveTexRoot(fileId: string, files: ProjectFile[]): string { const file = files.find((f) => f.id === fileId); if (!file || file.type !== "tex" || !file.content) return fileId; + // 1. Check for % !TEX root magic comment const lines = file.content.split("\n").slice(0, 20); for (const line of lines) { const match = line.match(/^%\s*!TEX\s+root\s*=\s*(.+)/i); if (match) { const rootPath = match[1].trim(); - // Try matching by relative path first, then by filename const target = files.find((f) => f.relativePath === rootPath) ?? files.find((f) => f.name === rootPath); if (target) return target.id; } } + + // 2. If the current file contains \documentclass, it is a root file + if (/\\documentclass[\s{[]/.test(file.content)) { + return fileId; + } + + // 3. Look for main.tex or document.tex with \documentclass + const wellKnown = files.find( + (f) => + (f.name === "main.tex" || f.name === "document.tex") && + f.type === "tex" && + f.content && + /\\documentclass[\s{[]/.test(f.content), + ); + if (wellKnown) return wellKnown.id; + + // 4. Any .tex file with \documentclass + const anyRoot = files.find( + (f) => + f.type === "tex" && + f.id !== fileId && + f.content && + /\\documentclass[\s{[]/.test(f.content), + ); + if (anyRoot) return anyRoot.id; + + // 5. Fallback: the active file itself return fileId; }