"""
# Combine all content
final_content = '\n'.join(html_all_pages_content)
html_all_content = f"{html_header}{toc_html}{final_content}"
return html_all_content
except Exception as e:
raise DocumentationProcessingError(f"Error processing documentation: {e}")
def generate_pdf(html_content, output_pdf, format_options=None):
"""Generate PDF using Playwright with enhanced error handling"""
default_format = {
'format': 'A4',
'margin': {
'top': '50px',
'right': '50px',
'bottom': '50px',
'left': '50px'
},
'print_background': True,
'display_header_footer': True,
'header_template': '
of
',
'footer_template': '
'
}
format_options = format_options or default_format
try:
playwright = sync_playwright().start()
browser = playwright.chromium.launch()
context = browser.new_context()
page = context.new_page()
# Set viewport size for consistent rendering
page.set_viewport_size({"width": 1280, "height": 1024})
# Increase timeouts for better reliability
page.set_default_timeout(120000) # 2 minutes
# Set content and wait for loading
page.set_content(html_content, wait_until='networkidle')
# Additional waits for content
page.wait_for_load_state('networkidle')
page.wait_for_load_state('domcontentloaded')
# Generate PDF
page.pdf(path=output_pdf, **format_options)
except Exception as e:
raise DocumentationProcessingError(f"Error generating PDF: {str(e)}")
finally:
if 'page' in locals():
page.close()
if 'context' in locals():
context.close()
if 'browser' in locals():
browser.close()
if 'playwright' in locals():
playwright.stop()
def main():
"""Main execution function with error handling"""
repo_dir = "astro-docs"
repo_url = "https://github.com/withastro/docs.git"
branch = "main"
docs_dir = "src/content/docs/en"
output_pdf = f"Astro_Documentation_{datetime.now().strftime('%Y-%m-%d')}.pdf"
temp_dir = None
try:
# Add version and license information to console
print(f"""
Astro Documentation PDF Generator v1.0.0
Copyright (C) 2024 PacNPal
This program comes with ABSOLUTELY NO WARRANTY; for details see the LICENSE file.
This is free software, and you are welcome to redistribute it
under certain conditions; see the LICENSE file for details.
""")
# Create CSS if it doesn't exist
if not os.path.exists('styles.css'):
print("Creating default styles.css...")
create_default_css()
print("Default CSS file created.")
# Create temporary directory for processing
temp_dir = tempfile.mkdtemp()
# Clone repository
print("Cloning Astro documentation repository...")
clone_repo(repo_url, branch, docs_dir, repo_dir)
# Get and sort files
print("Finding and sorting documentation files...")
docs_dir_full_path = os.path.join(repo_dir, docs_dir)
files_to_process = get_files_sorted(docs_dir_full_path)
print(f"Found {len(files_to_process)} files to process")
# Create cover page
with open('styles.css', 'r', encoding='utf8') as f:
css_content = f.read()
cover_html = f"""
Astro Documentation
Generated on {datetime.now().strftime('%Y-%m-%d')}
"""
# Process files and generate HTML
print("Processing documentation files...")
html_content = process_files(files_to_process, repo_dir, docs_dir)
# Combine cover and content
final_html = f"{cover_html}
{html_content}"
final_html = add_license_page(final_html)
# Generate PDF
print(f"Generating PDF: {output_pdf}")
generate_pdf(final_html, output_pdf)
print(f"Documentation successfully generated: {output_pdf}")
except DocumentationProcessingError as e:
print(f"Error: {e}")
return 1
except Exception as e:
print(f"Unexpected error: {e}")
print("This program is licensed under AGPL-3.0. Source code is available at: [Your Repository URL]")
return 1
finally:
# Cleanup
if temp_dir and os.path.exists(temp_dir):
shutil.rmtree(temp_dir, ignore_errors=True)
if __name__ == "__main__":
exit(main())