From ccb5455c30955697c2660c1886b9722f8cd0c0ad Mon Sep 17 00:00:00 2001 From: Walid Date: Wed, 24 Jun 2026 15:32:40 +0600 Subject: [PATCH] Update main.js --- main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.js b/main.js index 812e8b3..294be74 100644 --- a/main.js +++ b/main.js @@ -248,4 +248,4 @@ ${k}`:k,T=[];for(let B of r)T.push(...je(B,y,v,C));let b=Ke(T,e);this.layoutCach ${B.join(` `)} -`;try{let S=window,F=S.require("@electron/remote");if(!F?.dialog)throw new Error("no remote");let E=await F.dialog.showSaveDialog({title:"Save PDF",defaultPath:(this.currentFile?.basename??"export")+".pdf",filters:[{name:"PDF",extensions:["pdf"]}]});if(E.canceled||!E.filePath){e();return}new s.Notice("Generating PDF\u2026");let M=new Blob([$],{type:"text/html"}),R=URL.createObjectURL(M),I=new F.BrowserWindow({show:!1,webPreferences:{nodeIntegration:!1}});I.loadURL(R);let P=!1,A=()=>{URL.revokeObjectURL(R),I.close(),e()};I.webContents.once("did-fail-load",(N,w,D)=>{P||(P=!0,new s.Notice("PDF load error: "+D),A())}),I.webContents.once("did-finish-load",()=>{if(P)return;P=!0;let N=t.pageSize==="Custom";I.webContents.printToPDF({pageSize:N?"A4":t.pageSize,landscape:!N&&t.orientation==="landscape",preferCSSPageSize:N,printBackground:!0,margins:{marginType:"none"}}).then(w=>{S.require("fs").writeFile(E.filePath,w,D=>{D?new s.Notice("Error saving PDF: "+D.message):new s.Notice("\u2713 PDF saved: "+E.filePath),A()})}).catch(w=>{new s.Notice("PDF render error: "+w.message),A()})})}catch{new s.Notice("Advanced PDF export requires the Obsidian desktop app."),e()}}},Q=class extends s.PluginSettingTab{plugin;dirty=!1;constructor(t,e){super(t,e),this.plugin=e}display(){this.dirty=!1,this.buildSettings()}hide(){this.dirty&&(this.dirty=!1,this.plugin.activeModal?.render(!0))}async markDirty(){this.dirty=!0,await this.plugin.saveSettings()}buildSettings(){let{containerEl:t}=this;t.empty();let e=this.plugin.settings,a=(n,r,h,C)=>{let T=new s.Setting(t).setName(n);return C&&T.setDesc(C),T.addText(b=>b.setValue(String(e[r])).onChange(B=>{let L=parseInt(B,10)||0;e[r]=h!==void 0?Math.max(h,L):L,this.markDirty()}))},i=(n,r)=>new s.Setting(t).setName(n).addColorPicker(h=>h.setValue(e[r]).onChange(C=>{e[r]=C,this.markDirty()}));new s.Setting(t).setName("Style Preset").setHeading(),new s.Setting(t).setName("Preset").setDesc("Pick a preset to configure the overall document style. Fine-tune any setting below.").addDropdown(n=>{Object.entries(U).forEach(([r,h])=>{n.addOption(r,h.name)}),n.setValue(e.preset).onChange(r=>{this.plugin.applyPreset(r),this.markDirty().then(()=>{this.buildSettings()})})}).addButton(n=>n.setButtonText("Reset Preset").setTooltip("Reset current preset to its default values").onClick(()=>{this.plugin.applyPreset(e.preset,!0),this.markDirty().then(()=>{this.buildSettings()})})),new s.Setting(t).setName("Page").setHeading();let l;new s.Setting(t).setName("Page size").addDropdown(n=>{Object.keys(_).forEach(r=>{n.addOption(r,r)}),n.addOption("Custom","Custom\u2026"),n.setValue(e.pageSize).onChange(r=>{e.pageSize=r,l.settingEl.toggleClass("mpdf-is-hidden",r!=="Custom"),this.markDirty()})}),l=new s.Setting(t).setName("Custom page size (mm)").setDesc("Width \xD7 Height in millimetres.").addText(n=>n.setPlaceholder("Width").setValue(String(e.customPageWidth)).onChange(r=>{e.customPageWidth=Math.max(1,parseFloat(r)||210),this.markDirty()})).addText(n=>n.setPlaceholder("Height").setValue(String(e.customPageHeight)).onChange(r=>{e.customPageHeight=Math.max(1,parseFloat(r)||297),this.markDirty()})),l.settingEl.toggleClass("mpdf-is-hidden",e.pageSize!=="Custom"),new s.Setting(t).setName("Orientation").addDropdown(n=>n.addOptions({portrait:"Portrait",landscape:"Landscape"}).setValue(e.orientation).onChange(r=>{e.orientation=r,this.markDirty()})),new s.Setting(t).setName("Margin & Frame").setHeading(),new s.Setting(t).setName("Margins (mm)").setDesc("Top \xB7 Bottom \xB7 Left \xB7 Right").addText(n=>n.setPlaceholder("Top").setValue(String(e.marginTop)).onChange(r=>{e.marginTop=parseInt(r,10)||0,this.markDirty()})).addText(n=>n.setPlaceholder("Bottom").setValue(String(e.marginBottom)).onChange(r=>{e.marginBottom=parseInt(r,10)||0,this.markDirty()})).addText(n=>n.setPlaceholder("Left").setValue(String(e.marginLeft)).onChange(r=>{e.marginLeft=parseInt(r,10)||0,this.markDirty()})).addText(n=>n.setPlaceholder("Right").setValue(String(e.marginRight)).onChange(r=>{e.marginRight=parseInt(r,10)||0,this.markDirty()}));let d,p,m,c,g=n=>{[d,p,m,c].forEach(r=>r.settingEl.toggleClass("mpdf-is-hidden",!n))};new s.Setting(t).setName("Enable frame").setDesc("Draws a border around the outer edge of every page. Header, footer, and content all render inside it.").addToggle(n=>n.setValue(e.frameEnabled).onChange(r=>{e.frameEnabled=r,g(r),this.markDirty()})),d=i("Frame color","frameColor"),p=a("Frame thickness (px)","frameThickness",1),m=a("Frame margin (px)","frameMargin",0,"Gap between the page edge and the frame, applied equally on all four sides."),c=new s.Setting(t).setName("Frame style").addDropdown(n=>n.addOptions({solid:"Solid",dashed:"Dashed",dotted:"Dotted",double:"Double",groove:"Groove",ridge:"Ridge"}).setValue(e.frameStyle).onChange(r=>{e.frameStyle=r,this.markDirty()})),g(e.frameEnabled),new s.Setting(t).setName("Typography").setHeading();let u;new s.Setting(t).setName("Font family").addDropdown(n=>n.addOptions({"Georgia, serif":"Georgia (Serif)","'Times New Roman', Times, serif":"Times New Roman","'Palatino Linotype', Palatino, serif":"Palatino","Arial, sans-serif":"Arial","'Helvetica Neue', Helvetica, sans-serif":"Helvetica","'Trebuchet MS', sans-serif":"Trebuchet","'Courier New', monospace":"Courier New",__custom__:"Custom\u2026"}).setValue(e.fontFamily).onChange(r=>{e.fontFamily=r,u.settingEl.toggleClass("mpdf-is-hidden",r!=="__custom__"),this.markDirty()})),u=new s.Setting(t).setName("Custom font name").setDesc('CSS font-family value \u2014 e.g. "Inter, sans-serif". The font must be installed on your system.').addText(n=>n.setPlaceholder("e.g. Inter, sans-serif").setValue(e.customFontName).onChange(r=>{e.customFontName=r,this.markDirty()})),u.settingEl.toggleClass("mpdf-is-hidden",e.fontFamily!=="__custom__"),new s.Setting(t).setName("Font size (px)").addDropdown(n=>{["10","11","12","13","14","15","16"].forEach(r=>{n.addOption(r,r+"px")}),n.setValue(String(e.fontSize)).onChange(r=>{e.fontSize=parseInt(r),this.markDirty()})}),new s.Setting(t).setName("Code font size").addDropdown(n=>n.addOptions({"0.75":"0.75em","0.80":"0.80em","0.82":"0.82em","0.85":"0.85em","0.88":"0.88em","0.90":"0.90em","1.0":"1.00em"}).setValue(String(e.codeFontSize)).onChange(r=>{e.codeFontSize=parseFloat(r),this.markDirty()})),new s.Setting(t).setName("Line height").addDropdown(n=>n.addOptions({"1.4":"Tight (1.4)","1.6":"Compact (1.6)","1.75":"Normal (1.75)","1.85":"Relaxed (1.85)","2.0":"Double (2.0)"}).setValue(String(e.lineHeight)).onChange(r=>{e.lineHeight=parseFloat(r),this.markDirty()})),new s.Setting(t).setName("Paragraph spacing").addDropdown(n=>n.addOptions({0:"None","0.3":"Tight (0.3em)","0.5":"Normal (0.5em)","0.65":"Relaxed (0.65em)","1.0":"Wide (1em)"}).setValue(String(e.paragraphSpacing)).onChange(r=>{e.paragraphSpacing=parseFloat(r),this.markDirty()})),new s.Setting(t).setName("Heading scale").setDesc("Multiplier applied to all heading sizes.").addDropdown(n=>n.addOptions({"0.8":"Small (0.8\xD7)","0.88":"0.88\xD7","0.9":"Compact (0.9\xD7)","0.95":"0.95\xD7","1.0":"Normal (1.0\xD7)","1.05":"1.05\xD7","1.1":"Large (1.1\xD7)","1.2":"XLarge (1.2\xD7)"}).setValue(String(e.headingScale)).onChange(r=>{e.headingScale=parseFloat(r),this.markDirty()})),new s.Setting(t).setName("Background").setHeading();let f,x,y,v,H,k=n=>{f.settingEl.toggleClass("mpdf-is-hidden",n),[x,y,v,H].forEach(r=>r.settingEl.toggleClass("mpdf-is-hidden",!n))};new s.Setting(t).setName("Use image background").setDesc("When on, a background image is used instead of the solid background color.").addToggle(n=>n.setValue(e.backgroundImageEnabled).onChange(r=>{e.backgroundImageEnabled=r,k(r),this.markDirty()})),f=new s.Setting(t).setName("Page background color").addColorPicker(n=>n.setValue(e.pageBackground).onChange(r=>{e.pageBackground=r,this.markDirty()})),x=new s.Setting(t).setName("Background image").setDesc("Vault-relative path or https:// URL.").addText(n=>n.setPlaceholder("assets/background.png").setValue(e.backgroundImagePath).onChange(r=>{e.backgroundImagePath=r,this.markDirty()})),y=new s.Setting(t).setName("Fit").addDropdown(n=>n.addOptions({cover:"Cover (fill, crop edges)",contain:"Contain (fit, show gaps)",fill:"Fill (stretch to exact size)",tile:"Tile (repeat)"}).setValue(e.backgroundImageSize).onChange(r=>{e.backgroundImageSize=r,this.markDirty()})),v=new s.Setting(t).setName("Scope").setDesc("Full page includes header and footer bands. Content area only restricts the background to the text zone between them.").addDropdown(n=>n.addOptions({"full-page":"Full page","content-only":"Content area only"}).setValue(e.backgroundImageScope).onChange(r=>{e.backgroundImageScope=r,this.markDirty()})),H=new s.Setting(t).setName("Opacity").addDropdown(n=>n.addOptions({"0.05":"5%","0.1":"10%","0.15":"15%","0.2":"20%","0.3":"30%","0.4":"40%","0.5":"50%","0.6":"60%","0.7":"70%","0.8":"80%","0.9":"90%",1:"100%"}).setValue(String(e.backgroundImageOpacity)).onChange(r=>{e.backgroundImageOpacity=parseFloat(r),this.markDirty()})),k(e.backgroundImageEnabled),new s.Setting(t).setName("Colors").setHeading(),i("Accent color","accentColor"),i("Body text color","bodyColor"),i("Heading color","headingColor"),i("Blockquote background","blockquoteBg"),i("Blockquote border","blockquoteBorderColor"),i("Table header background","tableHeaderBg"),i("Code background","codeBackground"),new s.Setting(t).setName("Code syntax theme").setDesc('Independent of your Obsidian theme. "None" uses the body text color and code background above with no highlighting.').addDropdown(n=>{let r={};for(let[h,C]of Object.entries(Z))r[h]=C.name;n.addOptions(r).setValue(e.codeTheme).onChange(h=>{e.codeTheme=h,this.markDirty()})}),new s.Setting(t).setName("Header").setHeading(),new s.Setting(t).setName("Show header").addToggle(n=>n.setValue(e.showHeader).onChange(r=>{e.showHeader=r,this.markDirty()})),new s.Setting(t).setName("Show on first page").setDesc("When off, the header is hidden on page 1. Useful for title pages.").addToggle(n=>n.setValue(e.showHeaderOnFirstPage).onChange(r=>{e.showHeaderOnFirstPage=r,this.markDirty()})),new s.Setting(t).setName("Header text").setDesc("Appears on every page according to the chosen alignment.").addText(n=>n.setValue(e.headerText).onChange(r=>{e.headerText=r,this.markDirty()})),new s.Setting(t).setName("Alignment").addDropdown(n=>n.addOptions({left:"Left",center:"Center",right:"Right"}).setValue(e.headerAlignment).onChange(r=>{e.headerAlignment=r,this.markDirty()})),a("Font size (px)","headerFontSize",1),a("Height (px)","headerHeight",0,"Explicit band height. 0 = auto (follows font size)."),i("Font color","headerFontColor"),new s.Setting(t).setName("Border").setDesc("Separator line below the header.").addToggle(n=>n.setValue(e.showHeaderBorder).onChange(r=>{e.showHeaderBorder=r,this.markDirty()})),new s.Setting(t).setName("Image").setDesc("Vault-relative path or https:// URL. Fills the header band as a background banner; text renders on top. Leave blank to disable.").addText(n=>n.setPlaceholder("assets/header-banner.png").setValue(e.headerImagePath).onChange(r=>{e.headerImagePath=r,this.markDirty()})),a("Image left/right margin (px)","headerImageMargin",0,"Insets the banner from the left and right page edges. 0 = edge-to-edge."),new s.Setting(t).setName("Footer").setHeading(),new s.Setting(t).setName("Show footer").addToggle(n=>n.setValue(e.showFooter).onChange(r=>{e.showFooter=r,this.markDirty()})),new s.Setting(t).setName("Show on first page").setDesc("When off, the footer and page numbers are hidden on page 1. Page numbering starts from page 2.").addToggle(n=>n.setValue(e.showFooterOnFirstPage).onChange(r=>{e.showFooterOnFirstPage=r,this.markDirty()})),new s.Setting(t).setName("Footer text").addText(n=>n.setValue(e.footerText).onChange(r=>{e.footerText=r,this.markDirty()})),a("Font size (px)","footerFontSize",1),a("Height (px)","footerHeight",0,"Explicit band height. 0 = auto (follows font size)."),i("Font color","footerFontColor"),new s.Setting(t).setName("Border").setDesc("Separator line above the footer.").addToggle(n=>n.setValue(e.showFooterBorder).onChange(r=>{e.showFooterBorder=r,this.markDirty()})),new s.Setting(t).setName("Image").setDesc("Vault-relative path or https:// URL. Fills the footer band as a background banner.").addText(n=>n.setPlaceholder("assets/footer-banner.png").setValue(e.footerImagePath).onChange(r=>{e.footerImagePath=r,this.markDirty()})),a("Image left/right margin (px)","footerImageMargin",0,"Insets the banner from the left and right page edges."),new s.Setting(t).setName("Show page numbers").addToggle(n=>n.setValue(e.showPageNumbers).onChange(r=>{e.showPageNumbers=r,this.markDirty()})),new s.Setting(t).setName("Page number position").addDropdown(n=>n.addOptions({left:"Left",center:"Center",right:"Right"}).setValue(e.pageNumberPosition).onChange(r=>{e.pageNumberPosition=r,this.markDirty()})),new s.Setting(t).setName("Page number start").setDesc("Number assigned to the first visible page number. Accepts any integer.").addText(n=>n.setValue(String(e.pageNumberStart)).onChange(r=>{e.pageNumberStart=parseInt(r,10)||1,this.markDirty()})),new s.Setting(t).setName("Behaviour").setHeading(),new s.Setting(t).setName("Hide frontmatter").setDesc("Strip the YAML frontmatter block (--- \u2026 ---) from the preview and exported PDF.").addToggle(n=>n.setValue(e.hideFrontmatter).onChange(r=>{e.hideFrontmatter=r,this.markDirty()})),new s.Setting(t).setName("Include file name as title").setDesc("Prepend the note's file name as an H1 heading at the top of the PDF.").addToggle(n=>n.setValue(e.includeFilenameAsTitle).onChange(r=>{e.includeFilenameAsTitle=r,this.markDirty()})),new s.Setting(t).setName("Underline links").setDesc("Applies to both internal (in-document) and external links.").addToggle(n=>n.setValue(e.linkUnderline).onChange(r=>{e.linkUnderline=r,this.markDirty()})),new s.Setting(t).setName("Auto page break before H1").addToggle(n=>n.setValue(e.autoBreakH1).onChange(r=>{e.autoBreakH1=r,this.markDirty()})),new s.Setting(t).setName("Auto page break before H2").addToggle(n=>n.setValue(e.autoBreakH2).onChange(r=>{e.autoBreakH2=r,this.markDirty()})),new s.Setting(t).setName("H1 bottom border").addToggle(n=>n.setValue(e.h1BorderBottom).onChange(r=>{e.h1BorderBottom=r,this.markDirty()})),new s.Setting(t).setName("H2 bottom border").addToggle(n=>n.setValue(e.h2BorderBottom).onChange(r=>{e.h2BorderBottom=r,this.markDirty()})),new s.Setting(t).setName("Center H1").addToggle(n=>n.setValue(e.centerH1).onChange(r=>{e.centerH1=r,this.markDirty()})),new s.Setting(t).setName("Striped table rows").addToggle(n=>n.setValue(e.tableStriped).onChange(r=>{e.tableStriped=r,this.markDirty()}))}}; +`;try{let S=window,F=S.require("@electron/remote");if(!F?.dialog)throw new Error("no remote");let E=await F.dialog.showSaveDialog({title:"Save PDF",defaultPath:(this.currentFile?.basename??"export")+".pdf",filters:[{name:"PDF",extensions:["pdf"]}]});if(E.canceled||!E.filePath){e();return}new s.Notice("Generating PDF\u2026");let M=new Blob([$],{type:"text/html"}),R=URL.createObjectURL(M),I=new F.BrowserWindow({show:!1,webPreferences:{nodeIntegration:!1}});I.loadURL(R);let P=!1,A=()=>{URL.revokeObjectURL(R),I.close(),e()};I.webContents.once("did-fail-load",(N,w,D)=>{P||(P=!0,new s.Notice("PDF load error: "+D),A())}),I.webContents.once("did-finish-load",()=>{if(P)return;P=!0;let N=t.pageSize==="Custom";I.webContents.printToPDF({pageSize:N?"A4":t.pageSize,landscape:!N&&t.orientation==="landscape",preferCSSPageSize:N,printBackground:!0,margins:{marginType:"none"}}).then(w=>{S.require("fs").writeFile(E.filePath,w,D=>{D?new s.Notice("Error saving PDF: "+D.message):new s.Notice("\u2713 PDF saved: "+E.filePath),A()})}).catch(w=>{new s.Notice("PDF render error: "+w.message),A()})})}catch{new s.Notice("Advanced PDF export requires the Obsidian desktop app."),e()}}},Q=class extends s.PluginSettingTab{plugin;dirty=!1;constructor(t,e){super(t,e),this.plugin=e}display(){this.dirty=!1,this.buildSettings()}hide(){this.dirty&&(this.dirty=!1,this.plugin.activeModal?.render(!0))}async markDirty(){this.dirty=!0,await this.plugin.saveSettings()}buildSettings(){let{containerEl:t}=this;t.empty();let e=this.plugin.settings,a=(n,r,h,C)=>{let T=new s.Setting(t).setName(n);return C&&T.setDesc(C),T.addText(b=>b.setValue(String(e[r])).onChange(B=>{let L=parseInt(B,10)||0;e[r]=h!==void 0?Math.max(h,L):L,this.markDirty()}))},i=(n,r)=>new s.Setting(t).setName(n).addColorPicker(h=>h.setValue(e[r]).onChange(C=>{e[r]=C,this.markDirty()}));new s.Setting(t).setName("Style Preset").setHeading(),new s.Setting(t).setName("Preset").setDesc("Pick a preset to configure the overall document style. Fine-tune any setting below.").addDropdown(n=>{Object.entries(U).forEach(([r,h])=>{n.addOption(r,h.name)}),n.setValue(e.preset).onChange(r=>{this.plugin.applyPreset(r),this.markDirty().then(()=>{this.buildSettings()})})}).addButton(n=>n.setButtonText("Reset Preset").setTooltip("Reset current preset to its default values").onClick(()=>{this.plugin.applyPreset(e.preset,!0),this.markDirty().then(()=>{this.buildSettings()})})),new s.Setting(t).setName("Page").setHeading();let l;new s.Setting(t).setName("Page size").addDropdown(n=>{Object.keys(_).forEach(r=>{n.addOption(r,r)}),n.addOption("Custom","Custom\u2026"),n.setValue(e.pageSize).onChange(r=>{e.pageSize=r,l.settingEl.toggleClass("mpdf-is-hidden",r!=="Custom"),this.markDirty()})}),l=new s.Setting(t).setName("Custom page size (mm)").setDesc("Width \xD7 Height in millimetres.").addText(n=>n.setPlaceholder("Width").setValue(String(e.customPageWidth)).onChange(r=>{e.customPageWidth=Math.max(1,parseFloat(r)||210),this.markDirty()})).addText(n=>n.setPlaceholder("Height").setValue(String(e.customPageHeight)).onChange(r=>{e.customPageHeight=Math.max(1,parseFloat(r)||297),this.markDirty()})),l.settingEl.toggleClass("mpdf-is-hidden",e.pageSize!=="Custom"),new s.Setting(t).setName("Orientation").addDropdown(n=>n.addOptions({portrait:"Portrait",landscape:"Landscape"}).setValue(e.orientation).onChange(r=>{e.orientation=r,this.markDirty()})),new s.Setting(t).setName("Margin & Frame").setHeading(),new s.Setting(t).setName("Margins").setDesc("Top \xB7 Bottom \xB7 Left \xB7 Right").addText(n=>n.setPlaceholder("Top").setValue(String(e.marginTop)).onChange(r=>{e.marginTop=parseInt(r,10)||0,this.markDirty()})).addText(n=>n.setPlaceholder("Bottom").setValue(String(e.marginBottom)).onChange(r=>{e.marginBottom=parseInt(r,10)||0,this.markDirty()})).addText(n=>n.setPlaceholder("Left").setValue(String(e.marginLeft)).onChange(r=>{e.marginLeft=parseInt(r,10)||0,this.markDirty()})).addText(n=>n.setPlaceholder("Right").setValue(String(e.marginRight)).onChange(r=>{e.marginRight=parseInt(r,10)||0,this.markDirty()}));let d,p,m,c,g=n=>{[d,p,m,c].forEach(r=>r.settingEl.toggleClass("mpdf-is-hidden",!n))};new s.Setting(t).setName("Enable frame").setDesc("Draws a border around the outer edge of every page.").addToggle(n=>n.setValue(e.frameEnabled).onChange(r=>{e.frameEnabled=r,g(r),this.markDirty()})),d=i("Frame color","frameColor"),p=a("Frame thickness (px)","frameThickness",1),m=a("Frame margin (px)","frameMargin",0,"Gap between the page edge and the frame, applied equally on all four sides."),c=new s.Setting(t).setName("Frame style").addDropdown(n=>n.addOptions({solid:"Solid",dashed:"Dashed",dotted:"Dotted",double:"Double",groove:"Groove",ridge:"Ridge"}).setValue(e.frameStyle).onChange(r=>{e.frameStyle=r,this.markDirty()})),g(e.frameEnabled),new s.Setting(t).setName("Typography").setHeading();let u;new s.Setting(t).setName("Font family").addDropdown(n=>n.addOptions({"Georgia, serif":"Georgia (Serif)","'Times New Roman', Times, serif":"Times New Roman","'Palatino Linotype', Palatino, serif":"Palatino","Arial, sans-serif":"Arial","'Helvetica Neue', Helvetica, sans-serif":"Helvetica","'Trebuchet MS', sans-serif":"Trebuchet","'Courier New', monospace":"Courier New",__custom__:"Custom\u2026"}).setValue(e.fontFamily).onChange(r=>{e.fontFamily=r,u.settingEl.toggleClass("mpdf-is-hidden",r!=="__custom__"),this.markDirty()})),u=new s.Setting(t).setName("Custom font name").setDesc('CSS font-family value \u2014 e.g. "Inter, sans-serif". The font must be installed on your system.').addText(n=>n.setPlaceholder("e.g. Inter, sans-serif").setValue(e.customFontName).onChange(r=>{e.customFontName=r,this.markDirty()})),u.settingEl.toggleClass("mpdf-is-hidden",e.fontFamily!=="__custom__"),new s.Setting(t).setName("Font size (px)").addDropdown(n=>{["10","11","12","13","14","15","16"].forEach(r=>{n.addOption(r,r+"px")}),n.setValue(String(e.fontSize)).onChange(r=>{e.fontSize=parseInt(r),this.markDirty()})}),new s.Setting(t).setName("Code font size").addDropdown(n=>n.addOptions({"0.75":"0.75em","0.80":"0.80em","0.82":"0.82em","0.85":"0.85em","0.88":"0.88em","0.90":"0.90em","1.0":"1.00em"}).setValue(String(e.codeFontSize)).onChange(r=>{e.codeFontSize=parseFloat(r),this.markDirty()})),new s.Setting(t).setName("Line height").addDropdown(n=>n.addOptions({"1.4":"Tight (1.4)","1.6":"Compact (1.6)","1.75":"Normal (1.75)","1.85":"Relaxed (1.85)","2.0":"Double (2.0)"}).setValue(String(e.lineHeight)).onChange(r=>{e.lineHeight=parseFloat(r),this.markDirty()})),new s.Setting(t).setName("Paragraph spacing").addDropdown(n=>n.addOptions({0:"None","0.3":"Tight (0.3em)","0.5":"Normal (0.5em)","0.65":"Relaxed (0.65em)","1.0":"Wide (1em)"}).setValue(String(e.paragraphSpacing)).onChange(r=>{e.paragraphSpacing=parseFloat(r),this.markDirty()})),new s.Setting(t).setName("Heading scale").setDesc("Multiplier applied to all heading sizes.").addDropdown(n=>n.addOptions({"0.8":"Small (0.8\xD7)","0.88":"0.88\xD7","0.9":"Compact (0.9\xD7)","0.95":"0.95\xD7","1.0":"Normal (1.0\xD7)","1.05":"1.05\xD7","1.1":"Large (1.1\xD7)","1.2":"XLarge (1.2\xD7)"}).setValue(String(e.headingScale)).onChange(r=>{e.headingScale=parseFloat(r),this.markDirty()})),new s.Setting(t).setName("Background").setHeading();let f,x,y,v,H,k=n=>{f.settingEl.toggleClass("mpdf-is-hidden",n),[x,y,v,H].forEach(r=>r.settingEl.toggleClass("mpdf-is-hidden",!n))};new s.Setting(t).setName("Use image background").setDesc("When on, a background image is used instead of the solid background color.").addToggle(n=>n.setValue(e.backgroundImageEnabled).onChange(r=>{e.backgroundImageEnabled=r,k(r),this.markDirty()})),f=new s.Setting(t).setName("Page background color").addColorPicker(n=>n.setValue(e.pageBackground).onChange(r=>{e.pageBackground=r,this.markDirty()})),x=new s.Setting(t).setName("Background image").setDesc("Vault-relative path or https:// URL.").addText(n=>n.setPlaceholder("assets/background.png").setValue(e.backgroundImagePath).onChange(r=>{e.backgroundImagePath=r,this.markDirty()})),y=new s.Setting(t).setName("Fit").addDropdown(n=>n.addOptions({cover:"Cover (fill, crop edges)",contain:"Contain (fit, show gaps)",fill:"Fill (stretch to exact size)",tile:"Tile (repeat)"}).setValue(e.backgroundImageSize).onChange(r=>{e.backgroundImageSize=r,this.markDirty()})),v=new s.Setting(t).setName("Scope").setDesc("Full page includes header and footer bands. Content area only restricts the background to the text zone between them.").addDropdown(n=>n.addOptions({"full-page":"Full page","content-only":"Content area only"}).setValue(e.backgroundImageScope).onChange(r=>{e.backgroundImageScope=r,this.markDirty()})),H=new s.Setting(t).setName("Opacity").addDropdown(n=>n.addOptions({"0.05":"5%","0.1":"10%","0.15":"15%","0.2":"20%","0.3":"30%","0.4":"40%","0.5":"50%","0.6":"60%","0.7":"70%","0.8":"80%","0.9":"90%",1:"100%"}).setValue(String(e.backgroundImageOpacity)).onChange(r=>{e.backgroundImageOpacity=parseFloat(r),this.markDirty()})),k(e.backgroundImageEnabled),new s.Setting(t).setName("Colors").setHeading(),i("Accent color","accentColor"),i("Body text color","bodyColor"),i("Heading color","headingColor"),i("Blockquote background","blockquoteBg"),i("Blockquote border","blockquoteBorderColor"),i("Table header background","tableHeaderBg"),i("Code background","codeBackground"),new s.Setting(t).setName("Code syntax theme").setDesc('Independent of your Obsidian theme. "None" uses the body text color and code background above with no highlighting.').addDropdown(n=>{let r={};for(let[h,C]of Object.entries(Z))r[h]=C.name;n.addOptions(r).setValue(e.codeTheme).onChange(h=>{e.codeTheme=h,this.markDirty()})}),new s.Setting(t).setName("Header").setHeading(),new s.Setting(t).setName("Show header").addToggle(n=>n.setValue(e.showHeader).onChange(r=>{e.showHeader=r,this.markDirty()})),new s.Setting(t).setName("Show on first page").setDesc("When off, the header is hidden on page 1. Useful for title pages.").addToggle(n=>n.setValue(e.showHeaderOnFirstPage).onChange(r=>{e.showHeaderOnFirstPage=r,this.markDirty()})),new s.Setting(t).setName("Header text").addText(n=>n.setValue(e.headerText).onChange(r=>{e.headerText=r,this.markDirty()})),new s.Setting(t).setName("Alignment").addDropdown(n=>n.addOptions({left:"Left",center:"Center",right:"Right"}).setValue(e.headerAlignment).onChange(r=>{e.headerAlignment=r,this.markDirty()})),a("Font size (px)","headerFontSize",1),a("Height (px)","headerHeight",0,"Explicit band height (0 = auto)."),i("Font color","headerFontColor"),new s.Setting(t).setName("Border").setDesc("Separator line below the header.").addToggle(n=>n.setValue(e.showHeaderBorder).onChange(r=>{e.showHeaderBorder=r,this.markDirty()})),new s.Setting(t).setName("Image").setDesc("Vault-relative path or https:// URL. Fills the header band as a background banner.").addText(n=>n.setPlaceholder("assets/header-banner.png").setValue(e.headerImagePath).onChange(r=>{e.headerImagePath=r,this.markDirty()})),a("Image left/right margin (px)","headerImageMargin",0,"Insets the banner from the left and right page edges."),new s.Setting(t).setName("Footer").setHeading(),new s.Setting(t).setName("Show footer").addToggle(n=>n.setValue(e.showFooter).onChange(r=>{e.showFooter=r,this.markDirty()})),new s.Setting(t).setName("Show on first page").setDesc("When off, the footer and page numbers are hidden on page 1. Page numbering starts from page 2.").addToggle(n=>n.setValue(e.showFooterOnFirstPage).onChange(r=>{e.showFooterOnFirstPage=r,this.markDirty()})),new s.Setting(t).setName("Footer text").addText(n=>n.setValue(e.footerText).onChange(r=>{e.footerText=r,this.markDirty()})),a("Font size (px)","footerFontSize",1),a("Height (px)","footerHeight",0,"Explicit band height (0 = auto)."),i("Font color","footerFontColor"),new s.Setting(t).setName("Border").setDesc("Separator line above the footer.").addToggle(n=>n.setValue(e.showFooterBorder).onChange(r=>{e.showFooterBorder=r,this.markDirty()})),new s.Setting(t).setName("Image").setDesc("Vault-relative path or https:// URL. Fills the footer band as a background banner.").addText(n=>n.setPlaceholder("assets/footer-banner.png").setValue(e.footerImagePath).onChange(r=>{e.footerImagePath=r,this.markDirty()})),a("Image left/right margin (px)","footerImageMargin",0,"Insets the banner from the left and right page edges."),new s.Setting(t).setName("Show page numbers").addToggle(n=>n.setValue(e.showPageNumbers).onChange(r=>{e.showPageNumbers=r,this.markDirty()})),new s.Setting(t).setName("Page number position").addDropdown(n=>n.addOptions({left:"Left",center:"Center",right:"Right"}).setValue(e.pageNumberPosition).onChange(r=>{e.pageNumberPosition=r,this.markDirty()})),new s.Setting(t).setName("Page number start").setDesc("Number assigned to the first visible page number.").addText(n=>n.setValue(String(e.pageNumberStart)).onChange(r=>{e.pageNumberStart=parseInt(r,10)||1,this.markDirty()})),new s.Setting(t).setName("Behaviour").setHeading(),new s.Setting(t).setName("Hide frontmatter").setDesc("Strip the YAML frontmatter block (--- \u2026 ---) from the preview and exported PDF.").addToggle(n=>n.setValue(e.hideFrontmatter).onChange(r=>{e.hideFrontmatter=r,this.markDirty()})),new s.Setting(t).setName("Include file name as title").setDesc("Prepend the note's file name as an H1 heading at the top of the PDF.").addToggle(n=>n.setValue(e.includeFilenameAsTitle).onChange(r=>{e.includeFilenameAsTitle=r,this.markDirty()})),new s.Setting(t).setName("Underline links").setDesc("Applies to both internal and external links.").addToggle(n=>n.setValue(e.linkUnderline).onChange(r=>{e.linkUnderline=r,this.markDirty()})),new s.Setting(t).setName("Auto page break before H1").addToggle(n=>n.setValue(e.autoBreakH1).onChange(r=>{e.autoBreakH1=r,this.markDirty()})),new s.Setting(t).setName("Auto page break before H2").addToggle(n=>n.setValue(e.autoBreakH2).onChange(r=>{e.autoBreakH2=r,this.markDirty()})),new s.Setting(t).setName("H1 bottom border").addToggle(n=>n.setValue(e.h1BorderBottom).onChange(r=>{e.h1BorderBottom=r,this.markDirty()})),new s.Setting(t).setName("H2 bottom border").addToggle(n=>n.setValue(e.h2BorderBottom).onChange(r=>{e.h2BorderBottom=r,this.markDirty()})),new s.Setting(t).setName("Center H1").addToggle(n=>n.setValue(e.centerH1).onChange(r=>{e.centerH1=r,this.markDirty()})),new s.Setting(t).setName("Striped table rows").addToggle(n=>n.setValue(e.tableStriped).onChange(r=>{e.tableStriped=r,this.markDirty()}))}};