File size: 5,975 Bytes
a96dec4
ddd44f7
 
 
 
 
a96dec4
ddd44f7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import streamlit as st
from pathlib import Path
import base64
import datetime
import markdown2
from weasyprint import HTML, CSS

# --- Configuration & Setup ---

# Define the layouts based on the specification.
# The 'size' key uses CSS-compatible dimensions.
LAYOUTS = {
    "A4 Portrait": {"size": "210mm 297mm", "icon": "πŸ“„"},
    "A4 Landscape": {"size": "297mm 210mm", "icon": "πŸ“„"},
    "Letter Portrait": {"size": "8.5in 11in", "icon": "πŸ“„"},
    "Letter Landscape": {"size": "11in 8.5in", "icon": "πŸ“„"},
    "Wide 16:9": {"aspect_ratio": "16/9", "icon": "πŸ“Ί"},
    "Vertical 9:16": {"aspect_ratio": "9/16", "icon": "πŸ“±"},
    "Square 1:1": {"aspect_ratio": "1/1", "icon": "πŸ–ΌοΈ"},
}

# Directory to save the generated PDFs
OUTPUT_DIR = Path("generated_pdfs")
OUTPUT_DIR.mkdir(exist_ok=True)

# --- Helper Functions ---

def get_file_download_link(file_path: Path) -> str:
    """Generates a base64-encoded download link for a file."""
    with open(file_path, "rb") as f:
        data = base64.b64encode(f.read()).decode()
    return f'<a href="data:application/octet-stream;base64,{data}" download="{file_path.name}">Download</a>'

def display_file_explorer():
    """Renders a simple file explorer in the Streamlit app."""
    st.header("πŸ“‚ File Explorer")

    # Display Source Markdown files
    st.subheader("Source Markdown Files (.md)")
    md_files = list(Path(".").glob("*.md"))
    if not md_files:
        st.info("No Markdown files found in the current directory. Create a `.md` file to begin.")
    else:
        for md_file in md_files:
            col1, col2 = st.columns([0.8, 0.2])
            with col1:
                st.write(f"πŸ“ `{md_file.name}`")
            with col2:
                st.markdown(get_file_download_link(md_file), unsafe_allow_html=True)

    # Display Generated PDF files
    st.subheader("Generated PDF Files")
    pdf_files = sorted(list(OUTPUT_DIR.glob("*.pdf")), reverse=True)
    if not pdf_files:
        st.info("No PDFs generated yet. Click the button above.")
    else:
        for pdf_file in pdf_files:
            col1, col2 = st.columns([0.8, 0.2])
            with col1:
                st.write(f"πŸ“„ `{pdf_file.name}`")
            with col2:
                st.markdown(get_file_download_link(pdf_file), unsafe_allow_html=True)

def generate_pdf_from_markdown(md_path: Path):
    """
    Reads a markdown file and generates PDFs for all defined layouts.
    """
    try:
        md_content = md_path.read_text(encoding="utf-8")
        html_content = markdown2.markdown(md_content, extras=["tables", "fenced-code-blocks", "cuddled-lists"])
        
        # Basic styling for the PDF
        base_css = """
        @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap');
        body { font-family: 'Inter', sans-serif; line-height: 1.6; }
        h1, h2, h3 { font-weight: 700; }
        code {
            background-color: #f0f0f0;
            padding: 2px 4px;
            border-radius: 3px;
            font-family: monospace;
        }
        pre { background-color: #f0f0f0; padding: 1em; border-radius: 5px; overflow: auto; }
        table { border-collapse: collapse; width: 100%; }
        th, td { border: 1px solid #ddd; padding: 8px; }
        th { background-color: #f2f2f2; }
        """

        date_str = datetime.datetime.now().strftime("%Y-%m-%d")
        
        for name, properties in LAYOUTS.items():
            st.write(f"   - Generating `{name}` format...")
            
            page_css = f"@page {{ size: {properties.get('size', 'A4')}; margin: 2cm; }}"
            if 'aspect_ratio' in properties:
                # For aspect ratio, we fix width and calculate height. This is an approximation.
                # A more robust solution might require more complex CSS.
                page_css = f"@page {{ size: 210mm calc(210mm * {properties['aspect_ratio']}); margin: 1cm; }}"

            final_css = CSS(string=base_css + page_css)
            
            output_filename = f"{md_path.stem}_{name.replace(' ', '-')}_{date_str}.pdf"
            output_path = OUTPUT_DIR / output_filename
            
            HTML(string=html_content).write_pdf(output_path, stylesheets=[final_css])
            
    except Exception as e:
        st.error(f"Failed to process {md_path.name}: {e}")


# --- Streamlit App UI ---

st.set_page_config(layout="wide", page_title="PDF Generator")

st.title("πŸ“„ Markdown to PDF Generator")
st.markdown("This tool finds all `.md` files in this directory, converts them to PDF in various layouts, and provides download links.")

# Create a sample markdown file if none exists
if not list(Path(".").glob("*.md")):
    with open("sample.md", "w", encoding="utf-8") as f:
        f.write("# Sample Document\n\n")
        f.write("This is a sample markdown file created for you. You can edit this file or add your own `.md` files to this directory.\n\n")
        f.write("- Item 1\n- Item 2\n\n")
        f.write("`code snippet`\n\n")
        f.write("Click the button below to start the PDF generation process.")
    st.rerun()


if st.button("πŸš€ Generate PDFs from all Markdown Files", type="primary"):
    markdown_files = list(Path(".").glob("*.md"))
    
    if not markdown_files:
        st.warning("No `.md` files found. Please add a markdown file to the directory.")
    else:
        with st.spinner("Generating PDFs... This may take a moment."):
            progress_bar = st.progress(0)
            total_steps = len(markdown_files)
            
            for i, md_file in enumerate(markdown_files):
                st.info(f"Processing: **{md_file.name}**")
                generate_pdf_from_markdown(md_file)
                progress_bar.progress((i + 1) / total_steps)

        st.success("βœ… PDF generation complete!")
        # Use st.rerun() to immediately refresh the file explorer
        st.rerun()

# Display the file explorer section
display_file_explorer()