Refactor PDF generation and update class structure

This commit is contained in:
CodeAndCanvas728 2026-06-17 17:14:21 +02:00 committed by GitHub
parent 1d54412d34
commit d8350ef83e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,6 +1,5 @@
import os import os
import csv import csv
import re
import requests import requests
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from fpdf import FPDF from fpdf import FPDF
@ -17,48 +16,55 @@ COLOR_BORDER = (229, 222, 201) # #E5DEC9 - Thin muted gridlines
LOCAL_CSV_PATH = "RepoDatabase.csv" LOCAL_CSV_PATH = "RepoDatabase.csv"
REMOTE_CSV_URL = "https://raw.githubusercontent.com/CodeAndCanvas728/repobase/refs/heads/main/RepoDatabase.csv" REMOTE_CSV_URL = "https://raw.githubusercontent.com/CodeAndCanvas728/repobase/refs/heads/main/RepoDatabase.csv"
class CodeCanvasPDF(FPDF): class CodeCanvasCarousel(FPDF):
def header(self): def __init__(self):
# Initialize in Landscape mode ('L') using millimeters, explicitly custom sizing (A5 Landscape)
super().__init__(orientation='L', unit='mm', format='A5')
self.set_margins(20, 25, 20)
self.set_auto_page_break(False)
def draw_brand_canvas(self):
"""Fills background with Linen Canvas and draws the minimal header framework."""
self.set_fill_color(*COLOR_LINEN) self.set_fill_color(*COLOR_LINEN)
self.rect(0, 0, 210, 297, 'F') self.rect(0, 0, 210, 148, 'F') # A5 Landscape boundary dimensions
# Thin editorial top rule
self.set_draw_color(*COLOR_BORDER) self.set_draw_color(*COLOR_BORDER)
self.set_line_width(0.5) self.set_line_width(0.4)
self.line(15, 15, 195, 15) self.line(20, 15, 190, 15)
# Standalone Ampersand Shorthand # Standalone Ampersand Shorthand as visual anchor
self.set_text_color(*COLOR_TERRACOTTA) self.set_text_color(*COLOR_TERRACOTTA)
self.set_font("Times", "I", 16) # Classic serif self.set_font("Times", "I", 16)
self.text(15, 25, "&") self.text(20, 24, "&")
self.set_text_color(*COLOR_NAVY)
self.set_font("Helvetica", "B", 8) # Sans-serif technical data
self.text(23, 23, "CODE & CANVAS | INSIGHTS")
def footer(self): # Sans-serif technical meta-tag
self.set_text_color(*COLOR_NAVY)
self.set_font("Helvetica", "B", 7)
self.text(28, 22, "CODE & CANVAS | INSIGHTS")
def draw_footer(self, current_slide, total_slides):
"""Draws page numbering following clean, minimal layout scales."""
self.set_text_color(*COLOR_CHARCOAL) self.set_text_color(*COLOR_CHARCOAL)
self.set_font("Helvetica", "", 8) self.set_font("Helvetica", "", 8)
self.text(185, 285, f"Page {self.page_no()}") self.text(180, 138, f"{current_slide} / {total_slides}")
def clean_typography(text): def clean_typography(text):
"""Enforces absolute purity of text: No unicode or markdown em-dashes.""" """Enforces absolute micro-styling purity: completely strips out em-dashes."""
return text.replace("", " : ").replace("--", " - ") return text.replace("", " : ").replace("--", " - ")
def fetch_and_update_subject(): def fetch_and_update_subject():
"""Reads local repository CSV to find an unused row, updates it to 'yes',
and writes it back immediately to prevent duplicate scheduling entries."""
rows = [] rows = []
selected_subject = None selected_subject = None
file_exists_locally = os.path.exists(LOCAL_CSV_PATH) file_exists_locally = os.path.exists(LOCAL_CSV_PATH)
# 1. Read Database Data
if file_exists_locally: if file_exists_locally:
with open(LOCAL_CSV_PATH, mode='r', newline='', encoding='utf-8') as f: with open(LOCAL_CSV_PATH, mode='r', newline='', encoding='utf-8') as f:
reader = csv.DictReader(f) reader = csv.DictReader(f)
fieldnames = reader.fieldnames fieldnames = reader.fieldnames
for row in reader: for row in reader:
# Find the first unused item matching criteria
if not selected_subject and row.get('Used', '').strip().lower() == 'no': if not selected_subject and row.get('Used', '').strip().lower() == 'no':
row['Used'] = 'yes' # State Update Mutation row['Used'] = 'yes'
selected_subject = { selected_subject = {
"title": row['Title'], "title": row['Title'],
"desc": row['Description'], "desc": row['Description'],
@ -66,27 +72,7 @@ def fetch_and_update_subject():
"url": row.get('URL', f"https://github.com/search?q={row['Title']}") "url": row.get('URL', f"https://github.com/search?q={row['Title']}")
} }
rows.append(row) rows.append(row)
else:
# Fallback tracking if working outside local repository layout
print("Warning: Local RepoDatabase.csv not found. Reverting to remote live endpoint.")
try:
res = requests.get(REMOTE_CSV_URL, timeout=10)
if res.status_code == 200:
lines = res.text.splitlines()
reader = csv.DictReader(lines)
fieldnames = reader.fieldnames
for row in reader:
if not selected_subject and row.get('Used', '').strip().lower() == 'no':
selected_subject = {
"title": row['Title'],
"desc": row['Description'],
"points": [row['Point1'], row['Point2'], row['Point3']],
"url": row.get('URL', '')
}
except Exception:
pass
# 2. Save Updated Database State if modified locally
if selected_subject and file_exists_locally: if selected_subject and file_exists_locally:
with open(LOCAL_CSV_PATH, mode='w', newline='', encoding='utf-8') as f: with open(LOCAL_CSV_PATH, mode='w', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f, fieldnames=fieldnames) writer = csv.DictWriter(f, fieldnames=fieldnames)
@ -94,29 +80,13 @@ def fetch_and_update_subject():
writer.writerows(rows) writer.writerows(rows)
return selected_subject return selected_subject
# 3. Dynamic GitHub Scraping Fallback Routine # Ultimate fallback logic if CSV down or empty
if not selected_subject: return {
print("Database exhausted or unreachable. Querying trending open-source indexes...") "title": "Model Context Protocol",
try: "desc": "An open standard enabling secure, structured data communication layers between local environments and generative applications.",
fb_res = requests.get("https://github.com/trending", timeout=10) "points": ["Eliminates custom integration glue code", "Maintains clean architectural boundaries", "Built for cross-tool interoperability"],
soup = BeautifulSoup(fb_res.text, 'html.parser') "url": "https://github.com/modelcontextprotocol"
repo = soup.find('article', class_='Box-row') }
raw_title = repo.find('h2', class_='h3').text.strip().replace('\n', '').replace(' ', '')
desc = repo.find('p', class_='col-9').text.strip()
return {
"title": raw_title.split('/')[-1],
"desc": desc,
"points": ["Open-source workflow standard", "Highly modular architectural design", "Streamlined environment footprint"],
"url": f"https://github.com/{raw_title}"
}
except Exception:
# Absolute hard-fail recovery state
return {
"title": "Model Context Protocol",
"desc": "An open standard enabling secure, structured data communication layers between local environments and generative applications.",
"points": ["Eliminates custom integration glue code", "Maintains clear architectural boundaries", "Built for cross-tool interoperability"],
"url": "https://github.com/modelcontextprotocol"
}
def generate_assets(): def generate_assets():
data = fetch_and_update_subject() data = fetch_and_update_subject()
@ -124,55 +94,113 @@ def generate_assets():
desc = clean_typography(data['desc']) desc = clean_typography(data['desc'])
points = [clean_typography(p) for p in data['points']] points = [clean_typography(p) for p in data['points']]
# Target path configuration
os.makedirs("_drafts", exist_ok=True) os.makedirs("_drafts", exist_ok=True)
safe_date = "weekly-draft" TOTAL_SLIDES = 4
pdf = CodeCanvasCarousel()
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
# PDF COMPILATION BLOCK # SLIDE 1: DISPLAY TITLE CARD
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
pdf = CodeCanvasPDF()
pdf.set_margins(15, 30, 15)
pdf.add_page() pdf.add_page()
pdf.draw_brand_canvas()
pdf.set_y(45)
pdf.set_text_color(*COLOR_NAVY)
pdf.set_font("Times", "", 32) # Editorial high-contrast serif display
pdf.multi_cell(170, 14, title)
pdf.set_y(pdf.get_y() + 6)
pdf.set_text_color(*COLOR_CHARCOAL)
pdf.set_font("Helvetica", "", 12) # Sans-serif structural subtitle
pdf.multi_cell(170, 6, "An architectural breakdown of engineering utility and integration footprints.")
pdf.draw_footer(1, TOTAL_SLIDES)
# -------------------------------------------------------------------------
# SLIDE 2: THE CORE PROBLEMATIQUE / OVERVIEW
# -------------------------------------------------------------------------
pdf.add_page()
pdf.draw_brand_canvas()
# Header display layout
pdf.set_y(40) pdf.set_y(40)
pdf.set_text_color(*COLOR_NAVY) pdf.set_text_color(*COLOR_NAVY)
pdf.set_font("Times", "", 26) pdf.set_font("Times", "", 18)
pdf.multi_cell(180, 12, title) pdf.cell(170, 8, "Core Structural Objective", ln=True)
# Layout dividing grid rules # Subtle geometric divider line
pdf.set_draw_color(*COLOR_BORDER) pdf.set_draw_color(*COLOR_BORDER)
pdf.line(15, pdf.get_y() + 5, 80, pdf.get_y() + 5) pdf.line(20, pdf.get_y() + 2, 60, pdf.get_y() + 2)
# Copy layout execution pdf.set_y(pdf.get_y() + 12)
pdf.set_y(pdf.get_y() + 15)
pdf.set_text_color(*COLOR_CHARCOAL) pdf.set_text_color(*COLOR_CHARCOAL)
pdf.set_font("Helvetica", "", 11) pdf.set_font("Helvetica", "", 11)
pdf.multi_cell(180, 7, desc) pdf.multi_cell(170, 7, desc)
pdf.draw_footer(2, TOTAL_SLIDES)
# Balanced spacing grids for parameters
pdf.set_y(pdf.get_y() + 15)
for idx, pt in enumerate(points, 1):
pdf.set_draw_color(*COLOR_BORDER)
pdf.set_fill_color(*COLOR_LINEN)
pdf.rect(15, pdf.get_y(), 180, 18, 'DF')
pdf.set_x(20)
pdf.set_text_color(*COLOR_TERRACOTTA)
pdf.set_font("Times", "I", 12)
pdf.cell(10, 18, f"0{idx}")
pdf.set_text_color(*COLOR_CHARCOAL)
pdf.set_font("Helvetica", "", 10)
pdf.cell(160, 18, pt)
pdf.set_y(pdf.get_y() + 22)
pdf_path = f"_drafts/{safe_date}.pdf"
pdf.output(pdf_path)
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
# MARKDOWN CONVERSION BLOCK # SLIDE 3: TECHNICAL CONSIDERATIONS (GRID BLOCK)
# -------------------------------------------------------------------------
pdf.add_page()
pdf.draw_brand_canvas()
pdf.set_y(38)
pdf.set_text_color(*COLOR_NAVY)
pdf.set_font("Times", "", 18)
pdf.cell(170, 8, "Key Architecture Vectors", ln=True)
start_y = pdf.get_y() + 8
for idx, pt in enumerate(points):
current_item_y = start_y + (idx * 22)
# Structural card containers using thin borders
pdf.set_draw_color(*COLOR_BORDER)
pdf.set_fill_color(*COLOR_LINEN)
pdf.rect(20, current_item_y, 170, 16, 'DF')
# Terracotta index anchor points
pdf.set_y(current_item_y + 4)
pdf.set_x(24)
pdf.set_text_color(*COLOR_TERRACOTTA)
pdf.set_font("Times", "I", 11)
pdf.cell(10, 8, f"0{idx+1}")
# Clean structural sans body text
pdf.set_x(36)
pdf.set_text_color(*COLOR_CHARCOAL)
pdf.set_font("Helvetica", "", 10)
pdf.cell(150, 8, pt)
pdf.draw_footer(3, TOTAL_SLIDES)
# -------------------------------------------------------------------------
# SLIDE 4: THE CALL TO ACTION / ARCHITECTURE ROOT
# -------------------------------------------------------------------------
pdf.add_page()
pdf.draw_brand_canvas()
pdf.set_y(45)
pdf.set_text_color(*COLOR_NAVY)
pdf.set_font("Times", "", 24)
pdf.multi_cell(170, 10, f"Explore the Open-Source Blueprint")
pdf.set_y(pdf.get_y() + 10)
pdf.set_text_color(*COLOR_CHARCOAL)
pdf.set_font("Helvetica", "", 11)
pdf.multi_cell(170, 6, "Review the configuration patterns, track the baseline execution logs, and implement the layout block directly into your development container environments.")
# High-contrast action footer block
pdf.set_y(pdf.get_y() + 12)
pdf.set_text_color(*COLOR_TERRACOTTA)
pdf.set_font("Helvetica", "B", 10)
pdf.cell(170, 6, f"Source Index: {data['url']}", ln=True)
pdf.draw_footer(4, TOTAL_SLIDES)
# Output file generation paths
pdf.output("_drafts/weekly-draft.pdf")
# -------------------------------------------------------------------------
# GENERATE MARKDOWN TEXT FILE
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
post_copy = f"""💡 Weekly AI Architecture Breakdown post_copy = f"""💡 Weekly AI Architecture Breakdown
@ -192,11 +220,8 @@ Repository Link: {data['url']}
#SoftwareArchitecture #DeveloperTools #TechInsights #CodeAndCanvas""" #SoftwareArchitecture #DeveloperTools #TechInsights #CodeAndCanvas"""
md_path = f"_drafts/{safe_date}.md" with open("_drafts/weekly-draft.md", mode='w', encoding='utf-8') as f:
with open(md_path, mode='w', encoding='utf-8') as f:
f.write(post_copy) f.write(post_copy)
print(f"Workflow Complete: Created tracking drafts inside configuration paths.")
if __name__ == "__main__": if __name__ == "__main__":
generate_assets() generate_assets()