import { useState } from 'react'; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Checkbox } from '@/components/ui/checkbox'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { Input } from '@/components/ui/input'; import { Switch } from '@/components/ui/switch'; import { useAppStore } from '@/stores/app-store'; import { useSettingsStore } from '@/stores/settings-store'; import { useExportSource } from '@/hooks/use-export-source'; import { generateHtml } from '@/lib/html-export'; import { ipc } from '@/lib/ipc'; import { toast } from '@/lib/toast'; import { ExportDialogFooter } from './ExportDialogFooter'; export function ExportHtmlDialog({ sourcePath }: { sourcePath: string }) { const closeModal = useAppStore((s) => s.closeModal); const { htmlHighlightStyle, renderTablesAsAscii } = useSettingsStore(); const source = useExportSource(); const [standalone, setStandalone] = useState(true); const [highlight, setHighlight] = useState(htmlHighlightStyle); const [ascii, setAscii] = useState(renderTablesAsAscii); const [selfContained, setSelfContained] = useState(false); const [toc, setToc] = useState(false); const [tocDepth, setTocDepth] = useState(3); const [numberSections, setNumberSections] = useState(false); const [cssPath, setCssPath] = useState(''); const [submitting, setSubmitting] = useState(false); const [error, setError] = useState(null); const handleSubmit = async () => { if (!source) { setError('No file open.'); return; } setSubmitting(true); setError(null); try { const html = generateHtml({ source: source.source, title: source.title, standalone, highlightStyle: highlight, renderTablesAsAscii: ascii, }); const options = { standalone, highlightStyle: highlight, selfContained, toc, tocDepth, numberSections, css: cssPath || undefined, }; await window.electronAPI?.export?.withOptions?.('html', options); const saveResult = await ipc.app.showSaveDialog?.({ title: 'Save as HTML', defaultPath: source.path.replace(/\.md$/, '.html'), }); if (!saveResult?.ok || !saveResult.data) { setSubmitting(false); return; } const buffer = new TextEncoder().encode(html); const writeResult = await ipc.file.writeBuffer({ path: saveResult.data, buffer }); if (!writeResult.ok) { setError(writeResult.error.message); setSubmitting(false); return; } toast.success(`Exported ${source.title} to ${saveResult.data}`); closeModal(); } catch (err) { const msg = err instanceof Error ? err.message : String(err); toast.error(`Export failed: ${msg}`); setError(msg); setSubmitting(false); } }; return ( !o && closeModal()}> Export to HTML {sourcePath}
{toc && (
setTocDepth(Math.min(6, Math.max(1, Number(e.target.value))))} className="w-20" aria-label="TOC depth" />
)}
setCssPath(e.target.value)} placeholder="/path/to/custom.css" aria-label="Custom CSS file path" />
{error && (
{error}
)}
); }