Spaces:
Running
Running
Fix LaTeX API errors: use texlive.net and disable auto-compile on save
Browse files- app/api/data/route.ts +2 -66
- app/api/latex/compile/route.ts +45 -41
- app/components/TextEditor.tsx +2 -9
app/api/data/route.ts
CHANGED
|
@@ -120,72 +120,8 @@ export async function POST(request: NextRequest) {
|
|
| 120 |
|
| 121 |
await writeFile(filePath, content, 'utf-8')
|
| 122 |
|
| 123 |
-
// Auto-
|
| 124 |
-
|
| 125 |
-
console.log('β¨ Detected .tex file, auto-converting to PDF using external API...')
|
| 126 |
-
try {
|
| 127 |
-
console.log(`π LaTeX content length: ${content.length} characters`)
|
| 128 |
-
|
| 129 |
-
// Compile LaTeX to PDF using external API
|
| 130 |
-
const compileResponse = await fetch('https://latexbase.com/api/v1/compile', {
|
| 131 |
-
method: 'POST',
|
| 132 |
-
headers: {
|
| 133 |
-
'Content-Type': 'application/json',
|
| 134 |
-
},
|
| 135 |
-
body: JSON.stringify({
|
| 136 |
-
compiler: 'pdflatex',
|
| 137 |
-
content: content
|
| 138 |
-
}),
|
| 139 |
-
signal: AbortSignal.timeout(60000)
|
| 140 |
-
})
|
| 141 |
-
|
| 142 |
-
if (compileResponse.ok) {
|
| 143 |
-
const result = await compileResponse.json()
|
| 144 |
-
|
| 145 |
-
if (result.status === 'success' && result.pdf) {
|
| 146 |
-
const pdfBuffer = Buffer.from(result.pdf, 'base64')
|
| 147 |
-
const pdfFileName = fileName.replace('.tex', '.pdf')
|
| 148 |
-
const pdfFilePath = path.join(targetDir, pdfFileName)
|
| 149 |
-
|
| 150 |
-
console.log(`πΎ PDF size: ${pdfBuffer.byteLength} bytes`)
|
| 151 |
-
console.log(`π Saving PDF to: ${pdfFilePath}`)
|
| 152 |
-
|
| 153 |
-
await writeFile(pdfFilePath, pdfBuffer)
|
| 154 |
-
console.log(`β
PDF generated successfully: ${pdfFileName}`)
|
| 155 |
-
|
| 156 |
-
return NextResponse.json({
|
| 157 |
-
success: true,
|
| 158 |
-
pdfGenerated: true,
|
| 159 |
-
pdfFileName: pdfFileName,
|
| 160 |
-
message: `LaTeX file saved and converted to ${pdfFileName}`
|
| 161 |
-
})
|
| 162 |
-
} else {
|
| 163 |
-
console.error('PDF compilation returned error:', result)
|
| 164 |
-
return NextResponse.json({
|
| 165 |
-
success: true,
|
| 166 |
-
pdfGenerated: false,
|
| 167 |
-
error: 'LaTeX file saved but PDF generation failed'
|
| 168 |
-
})
|
| 169 |
-
}
|
| 170 |
-
} else {
|
| 171 |
-
console.error('PDF compilation failed:', await compileResponse.text())
|
| 172 |
-
return NextResponse.json({
|
| 173 |
-
success: true,
|
| 174 |
-
pdfGenerated: false,
|
| 175 |
-
error: 'LaTeX file saved but PDF generation failed'
|
| 176 |
-
})
|
| 177 |
-
}
|
| 178 |
-
} catch (pdfError) {
|
| 179 |
-
console.error('β Error generating PDF:', pdfError)
|
| 180 |
-
console.error(' Error details:', pdfError instanceof Error ? pdfError.message : String(pdfError))
|
| 181 |
-
return NextResponse.json({
|
| 182 |
-
success: true,
|
| 183 |
-
pdfGenerated: false,
|
| 184 |
-
error: 'LaTeX file saved but PDF generation failed',
|
| 185 |
-
details: pdfError instanceof Error ? pdfError.message : String(pdfError)
|
| 186 |
-
})
|
| 187 |
-
}
|
| 188 |
-
}
|
| 189 |
|
| 190 |
return NextResponse.json({ success: true })
|
| 191 |
}
|
|
|
|
| 120 |
|
| 121 |
await writeFile(filePath, content, 'utf-8')
|
| 122 |
|
| 123 |
+
// Note: Auto-PDF generation is disabled to avoid external API dependencies
|
| 124 |
+
// Users can manually compile LaTeX files using the TextEditor's "Compile" button
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
|
| 126 |
return NextResponse.json({ success: true })
|
| 127 |
}
|
app/api/latex/compile/route.ts
CHANGED
|
@@ -11,56 +11,60 @@ export async function POST(request: NextRequest) {
|
|
| 11 |
)
|
| 12 |
}
|
| 13 |
|
| 14 |
-
console.log('π Compiling LaTeX to PDF
|
| 15 |
console.log(` Content length: ${latex.length} characters`)
|
| 16 |
|
| 17 |
-
// Try
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
body: JSON.stringify({
|
| 24 |
-
compiler: 'pdflatex',
|
| 25 |
-
content: latex
|
| 26 |
-
}),
|
| 27 |
-
signal: AbortSignal.timeout(60000) // 60 second timeout for large documents
|
| 28 |
-
})
|
| 29 |
-
|
| 30 |
-
if (!compileResponse.ok) {
|
| 31 |
-
const errorText = await compileResponse.text()
|
| 32 |
-
console.error('β LaTeX compilation failed:', errorText)
|
| 33 |
-
return NextResponse.json(
|
| 34 |
-
{
|
| 35 |
-
error: 'LaTeX compilation failed',
|
| 36 |
-
details: errorText.substring(0, 500),
|
| 37 |
-
message: 'The LaTeX compiler returned an error. Check your syntax.'
|
| 38 |
},
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
return NextResponse.json(
|
| 58 |
{
|
| 59 |
-
error: '
|
| 60 |
-
details:
|
| 61 |
-
message: '
|
| 62 |
},
|
| 63 |
-
{ status:
|
| 64 |
)
|
| 65 |
}
|
| 66 |
|
|
|
|
| 11 |
)
|
| 12 |
}
|
| 13 |
|
| 14 |
+
console.log('π Compiling LaTeX to PDF...')
|
| 15 |
console.log(` Content length: ${latex.length} characters`)
|
| 16 |
|
| 17 |
+
// Try LaTeX compilation API with better error handling
|
| 18 |
+
try {
|
| 19 |
+
const compileResponse = await fetch('https://texlive.net/cgi-bin/latexcgi', {
|
| 20 |
+
method: 'POST',
|
| 21 |
+
headers: {
|
| 22 |
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
},
|
| 24 |
+
body: new URLSearchParams({
|
| 25 |
+
filecontents: latex,
|
| 26 |
+
filename: 'document.tex',
|
| 27 |
+
engine: 'pdflatex',
|
| 28 |
+
return: 'pdf'
|
| 29 |
+
}),
|
| 30 |
+
signal: AbortSignal.timeout(60000)
|
| 31 |
+
})
|
| 32 |
|
| 33 |
+
// Check if response is actually a PDF
|
| 34 |
+
const contentType = compileResponse.headers.get('content-type')
|
| 35 |
+
|
| 36 |
+
if (compileResponse.ok && contentType?.includes('pdf')) {
|
| 37 |
+
const pdfBuffer = Buffer.from(await compileResponse.arrayBuffer())
|
| 38 |
+
console.log(`β
LaTeX compiled successfully! PDF size: ${pdfBuffer.byteLength} bytes`)
|
| 39 |
|
| 40 |
+
const response = new NextResponse(pdfBuffer)
|
| 41 |
+
response.headers.set('Content-Type', 'application/pdf')
|
| 42 |
+
response.headers.set('Content-Disposition', `attachment; filename="${filename || 'document.pdf'}"`)
|
| 43 |
|
| 44 |
+
return response
|
| 45 |
+
} else {
|
| 46 |
+
// API returned error or HTML
|
| 47 |
+
const errorText = await compileResponse.text()
|
| 48 |
+
console.error('β LaTeX compilation failed:', errorText.substring(0, 200))
|
| 49 |
+
|
| 50 |
+
return NextResponse.json(
|
| 51 |
+
{
|
| 52 |
+
error: 'LaTeX compilation service unavailable',
|
| 53 |
+
details: 'The external LaTeX compiler is currently unavailable.',
|
| 54 |
+
message: 'LaTeX compilation services are temporarily unavailable. Your .tex file has been saved - you can download and compile it locally.'
|
| 55 |
+
},
|
| 56 |
+
{ status: 503 }
|
| 57 |
+
)
|
| 58 |
+
}
|
| 59 |
+
} catch (fetchError) {
|
| 60 |
+
console.error('β API fetch error:', fetchError)
|
| 61 |
return NextResponse.json(
|
| 62 |
{
|
| 63 |
+
error: 'LaTeX compilation service unavailable',
|
| 64 |
+
details: 'Could not reach LaTeX compilation service',
|
| 65 |
+
message: 'LaTeX compilation services are temporarily unavailable. Your .tex file has been saved - you can download and compile it locally.'
|
| 66 |
},
|
| 67 |
+
{ status: 503 }
|
| 68 |
)
|
| 69 |
}
|
| 70 |
|
app/components/TextEditor.tsx
CHANGED
|
@@ -148,15 +148,8 @@ export function TextEditor({
|
|
| 148 |
}
|
| 149 |
}
|
| 150 |
|
| 151 |
-
// Auto-compile on save
|
| 152 |
-
|
| 153 |
-
if (isLatexFile && saveStatus === 'saved') {
|
| 154 |
-
// Small delay to ensure file is saved
|
| 155 |
-
setTimeout(() => {
|
| 156 |
-
compileToPDF()
|
| 157 |
-
}, 500)
|
| 158 |
-
}
|
| 159 |
-
}, [saveStatus])
|
| 160 |
|
| 161 |
// Cleanup PDF URL on unmount
|
| 162 |
useEffect(() => {
|
|
|
|
| 148 |
}
|
| 149 |
}
|
| 150 |
|
| 151 |
+
// Note: Auto-compile on save is disabled to avoid unreliable API calls
|
| 152 |
+
// Users should manually click "Compile" button to generate PDF
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 153 |
|
| 154 |
// Cleanup PDF URL on unmount
|
| 155 |
useEffect(() => {
|