227 lines
8.6 KiB
Python
227 lines
8.6 KiB
Python
import os
|
|
import csv
|
|
import requests
|
|
from bs4 import BeautifulSoup
|
|
from fpdf import FPDF
|
|
|
|
# -------------------------------------------------------------------------
|
|
# CODE & CANVAS BRAND DESIGN TOKENS
|
|
# -------------------------------------------------------------------------
|
|
COLOR_LINEN = (250, 248, 245) # #FAF8F5 - Default background canvas
|
|
COLOR_NAVY = (26, 35, 50) # #1A2332 - Deep structural base color
|
|
COLOR_TERRACOTTA = (211, 107, 77) # #D36B4D - Primary visual accents
|
|
COLOR_CHARCOAL = (43, 43, 43) # #2B2B2B - High-legibility body text
|
|
COLOR_BORDER = (229, 222, 201) # #E5DEC9 - Thin muted gridlines
|
|
|
|
LOCAL_CSV_PATH = "RepoDatabase.csv"
|
|
REMOTE_CSV_URL = "https://raw.githubusercontent.com/CodeAndCanvas728/repobase/refs/heads/main/RepoDatabase.csv"
|
|
|
|
class CodeCanvasCarousel(FPDF):
|
|
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.rect(0, 0, 210, 148, 'F') # A5 Landscape boundary dimensions
|
|
|
|
# Thin editorial top rule
|
|
self.set_draw_color(*COLOR_BORDER)
|
|
self.set_line_width(0.4)
|
|
self.line(20, 15, 190, 15)
|
|
|
|
# Standalone Ampersand Shorthand as visual anchor
|
|
self.set_text_color(*COLOR_TERRACOTTA)
|
|
self.set_font("Times", "I", 16)
|
|
self.text(20, 24, "&")
|
|
|
|
# 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_font("Helvetica", "", 8)
|
|
self.text(180, 138, f"{current_slide} / {total_slides}")
|
|
|
|
def clean_typography(text):
|
|
"""Enforces absolute micro-styling purity: completely strips out em-dashes."""
|
|
return text.replace("—", " : ").replace("--", " - ")
|
|
|
|
def fetch_and_update_subject():
|
|
rows = []
|
|
selected_subject = None
|
|
file_exists_locally = os.path.exists(LOCAL_CSV_PATH)
|
|
|
|
if file_exists_locally:
|
|
with open(LOCAL_CSV_PATH, mode='r', newline='', encoding='utf-8') as f:
|
|
reader = csv.DictReader(f)
|
|
fieldnames = reader.fieldnames
|
|
for row in reader:
|
|
if not selected_subject and row.get('Used', '').strip().lower() == 'no':
|
|
row['Used'] = 'yes'
|
|
selected_subject = {
|
|
"title": row['Title'],
|
|
"desc": row['Description'],
|
|
"points": [row['Point1'], row['Point2'], row['Point3']],
|
|
"url": row.get('URL', f"https://github.com/search?q={row['Title']}")
|
|
}
|
|
rows.append(row)
|
|
|
|
if selected_subject and file_exists_locally:
|
|
with open(LOCAL_CSV_PATH, mode='w', newline='', encoding='utf-8') as f:
|
|
writer = csv.DictWriter(f, fieldnames=fieldnames)
|
|
writer.writeheader()
|
|
writer.writerows(rows)
|
|
return selected_subject
|
|
|
|
# Ultimate fallback logic if CSV down or empty
|
|
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 clean architectural boundaries", "Built for cross-tool interoperability"],
|
|
"url": "https://github.com/modelcontextprotocol"
|
|
}
|
|
|
|
def generate_assets():
|
|
data = fetch_and_update_subject()
|
|
title = clean_typography(data['title'])
|
|
desc = clean_typography(data['desc'])
|
|
points = [clean_typography(p) for p in data['points']]
|
|
|
|
os.makedirs("_drafts", exist_ok=True)
|
|
TOTAL_SLIDES = 4
|
|
|
|
pdf = CodeCanvasCarousel()
|
|
|
|
# -------------------------------------------------------------------------
|
|
# SLIDE 1: DISPLAY TITLE CARD
|
|
# -------------------------------------------------------------------------
|
|
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()
|
|
|
|
pdf.set_y(40)
|
|
pdf.set_text_color(*COLOR_NAVY)
|
|
pdf.set_font("Times", "", 18)
|
|
pdf.cell(170, 8, "Core Structural Objective", ln=True)
|
|
|
|
# Subtle geometric divider line
|
|
pdf.set_draw_color(*COLOR_BORDER)
|
|
pdf.line(20, pdf.get_y() + 2, 60, pdf.get_y() + 2)
|
|
|
|
pdf.set_y(pdf.get_y() + 12)
|
|
pdf.set_text_color(*COLOR_CHARCOAL)
|
|
pdf.set_font("Helvetica", "", 11)
|
|
pdf.multi_cell(170, 7, desc)
|
|
pdf.draw_footer(2, TOTAL_SLIDES)
|
|
|
|
# -------------------------------------------------------------------------
|
|
# 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
|
|
|
|
Looking closely at modern workflows, complexity often hides in plain sight. Today we are looking at {title}.
|
|
|
|
What it is:
|
|
{desc}
|
|
|
|
Key Architecture Considerations:
|
|
• {points[0]}
|
|
• {points[1]}
|
|
• {points[2]}
|
|
|
|
The complete visual documentation is attached below as an editorial carousel blueprint.
|
|
|
|
Repository Link: {data['url']}
|
|
|
|
#SoftwareArchitecture #DeveloperTools #TechInsights #CodeAndCanvas"""
|
|
|
|
with open("_drafts/weekly-draft.md", mode='w', encoding='utf-8') as f:
|
|
f.write(post_copy)
|
|
|
|
if __name__ == "__main__":
|
|
generate_assets()
|