""" pdf.py — Zouq-ul-ilm | Professional Notes PDF Generator Handles markdown headings (#, ##, ###) AND === TOPIC === dividers. """ from reportlab.lib.pagesizes import A4 from reportlab.lib.styles import ParagraphStyle from reportlab.lib.units import mm from reportlab.lib import colors from reportlab.lib.enums import TA_LEFT, TA_JUSTIFY from reportlab.platypus import ( BaseDocTemplate, Frame, PageTemplate, Paragraph, Spacer, HRFlowable, ListFlowable, ListItem, KeepTogether, PageBreak, ) from reportlab.platypus.flowables import Flowable import re, io # ─── PALETTE ────────────────────────────────────────────────────────────────── INK = colors.HexColor("#0F1117") NAVY = colors.HexColor("#1B2A4A") GOLD = colors.HexColor("#C8973F") GOLD_LIGHT = colors.HexColor("#FBF3E4") SLATE = colors.HexColor("#3D4A5C") MUTED = colors.HexColor("#7B8499") DIVIDER = colors.HexColor("#DDE1EA") WHITE = colors.white W_PAGE, H_PAGE = A4 MARGIN_LR = 18*mm MARGIN_TOP = 30*mm MARGIN_BOT = 22*mm TEXT_W = W_PAGE - 2*MARGIN_LR # ─── CUSTOM FLOWABLES ───────────────────────────────────────────────────────── class TopicBanner(Flowable): """Full-width dark banner for === TOPIC === headings.""" BH = 15*mm def __init__(self, title, width=TEXT_W): super().__init__() self.title = title self.width = width self.height = self.BH + 6*mm def draw(self): c = self.canv c.saveState() c.setFillColor(NAVY) c.roundRect(0, 4*mm, self.width, self.BH, radius=5, fill=1, stroke=0) c.setFillColor(GOLD) c.roundRect(0, 4*mm, 4, self.BH, radius=2, fill=1, stroke=0) c.setFillColor(WHITE) c.setFont("Helvetica-Bold", 12.5) c.drawString(9*mm, 4*mm + self.BH/2 - 4.5, self.title) c.restoreState() class SectionHeading(Flowable): """Gold-accented card for ## H2 headings.""" BH = 9*mm def __init__(self, title, width=TEXT_W): super().__init__() self.title = title self.width = width self.height = self.BH + 5*mm def draw(self): c = self.canv c.saveState() c.setFillColor(GOLD_LIGHT) c.setStrokeColor(GOLD) c.setLineWidth(0.8) c.roundRect(0, 3*mm, self.width, self.BH, radius=4, fill=1, stroke=1) c.setFillColor(GOLD) c.roundRect(0, 3*mm, 3.5, self.BH, radius=2, fill=1, stroke=0) c.setFillColor(NAVY) c.setFont("Helvetica-Bold", 11) c.drawString(7*mm, 3*mm + self.BH/2 - 4, self.title) c.restoreState() # ─── PAGE TEMPLATE ──────────────────────────────────────────────────────────── class ZouqDoc(BaseDocTemplate): def __init__(self, target, doc_title="Notes", **kw): self.doc_title = doc_title super().__init__(target, **kw) frame = Frame( MARGIN_LR, MARGIN_BOT, TEXT_W, H_PAGE - MARGIN_TOP - MARGIN_BOT, leftPadding=0, rightPadding=0, topPadding=0, bottomPadding=0, ) self.addPageTemplates([ PageTemplate(id="main", frames=[frame], onPage=self._decorate) ]) def _decorate(self, canvas, doc): canvas.saveState() W, H = A4 # Header canvas.setFillColor(NAVY) canvas.rect(0, H - MARGIN_TOP, W, MARGIN_TOP, fill=1, stroke=0) canvas.setFillColor(GOLD) canvas.rect(0, H - MARGIN_TOP, W, 2, fill=1, stroke=0) canvas.setFillColor(WHITE) canvas.setFont("Helvetica-Bold", 9.5) canvas.drawString(MARGIN_LR, H - 16*mm, "Zouq-ul-ilm") canvas.setFont("Helvetica", 8.5) canvas.setFillColor(colors.HexColor("#A8B4C8")) canvas.drawRightString(W - MARGIN_LR, H - 16*mm, self.doc_title[:65]) # Footer canvas.setFillColor(colors.HexColor("#F2F4F7")) canvas.rect(0, 0, W, MARGIN_BOT - 4*mm, fill=1, stroke=0) canvas.setFillColor(GOLD) canvas.rect(0, MARGIN_BOT - 4*mm, W, 1.5, fill=1, stroke=0) canvas.setFont("Helvetica", 7.5) canvas.setFillColor(MUTED) canvas.drawString(MARGIN_LR, 7*mm, "Generated by Zouq-ul-ilm · AI-Powered Study Notes") canvas.drawRightString(W - MARGIN_LR, 7*mm, f"Page {doc.page}") canvas.restoreState() # ─── STYLES ─────────────────────────────────────────────────────────────────── def _S(): return { "h1": ParagraphStyle("h1", fontName="Helvetica-Bold", fontSize=19, leading=25, textColor=NAVY, spaceBefore=4, spaceAfter=4), "h3": ParagraphStyle("h3", fontName="Helvetica-Bold", fontSize=11, leading=15, textColor=SLATE, spaceBefore=7, spaceAfter=3), "body": ParagraphStyle("body", fontName="Helvetica", fontSize=10.5, leading=16.5, textColor=SLATE, spaceAfter=5, alignment=TA_JUSTIFY), "bullet": ParagraphStyle("bullet", fontName="Helvetica", fontSize=10.5, leading=15.5, textColor=SLATE, spaceBefore=1, spaceAfter=1), "sub_bullet": ParagraphStyle("sub_bullet", fontName="Helvetica", fontSize=9.8, leading=14, textColor=MUTED, spaceBefore=1, spaceAfter=1), } # ─── INLINE MARKDOWN ────────────────────────────────────────────────────────── def _md(t): t = t.replace("&", "&").replace("<", "<").replace(">", ">") t = re.sub(r"\*\*(.+?)\*\*", r'\1', t) t = re.sub(r"__(.+?)__", r'\1', t) t = re.sub(r"\*(.+?)\*", r'\1', t) t = re.sub(r"_(.+?)_", r'\1', t) t = re.sub(r"~~(.+?)~~", r'\1', t) t = re.sub(r"`(.+?)`", r' \1 ', t) return t # ─── PATTERNS ───────────────────────────────────────────────────────────────── H1_RE = re.compile(r'^#\s+(.+)') H2_RE = re.compile(r'^##\s+(.+)') H3_RE = re.compile(r'^###\s+(.+)') BULLET_RE = re.compile(r'^\s*[-*•]\s+(.+)') SUB_RE = re.compile(r'^\s*\+\s+(.+)') OL_RE = re.compile(r'^\s*\d+\.\s+(.+)') TOPIC_RE = re.compile(r'^={3,}\s*(.+?)\s*={3,}$') SEP_RE = re.compile(r'^[=\-]{3,}\s*$') def _bullet_list(items, S, ordered=False): li = [] for text, is_sub in items: style = S["sub_bullet"] if is_sub else S["bullet"] li.append(ListItem( Paragraph(_md(text), style), bulletColor=MUTED if is_sub else GOLD, leftIndent=28 if is_sub else 16, bulletFontSize=9 if is_sub else 12, )) return ListFlowable(li, bulletType="1" if ordered else "bullet", bulletFontName="Helvetica-Bold", bulletFontSize=10.5, bulletColor=GOLD, leftIndent=8, spaceBefore=3, spaceAfter=6) # ─── MAIN ───────────────────────────────────────────────────────────────────── def pdf1(text: str, output_path: str = None): S = _S() # Derive doc title m = re.search(r'^#\s+(.+)', text, re.M) or re.search(r'^={3,}\s*(.+?)\s*={3,}$', text, re.M) doc_title = m.group(1).strip() if m else "Study Notes" target = output_path or io.BytesIO() doc = ZouqDoc(target, doc_title=doc_title, pagesize=A4, topMargin=MARGIN_TOP, bottomMargin=MARGIN_BOT, leftMargin=MARGIN_LR, rightMargin=MARGIN_LR) story = [] lines = text.split('\n') i = 0 topic_count = 0 while i < len(lines): line = lines[i].strip() # skip pure separator lines if SEP_RE.match(line): i += 1; continue # blank line if not line: story.append(Spacer(1, 2.5*mm)) i += 1; continue # === TOPIC === — chapter break m = TOPIC_RE.match(line) if m: topic_count += 1 if topic_count > 1: story.append(PageBreak()) story.append(Spacer(1, 2*mm)) story.append(TopicBanner(m.group(1).strip().title())) story.append(Spacer(1, 4*mm)) i += 1; continue # # H1 if H1_RE.match(line): clean = re.sub(r'^#\s+', '', line) story.append(Spacer(1, 3*mm)) story.append(HRFlowable(width="100%", thickness=2, color=GOLD, spaceAfter=2)) story.append(Paragraph(_md(clean), S["h1"])) story.append(HRFlowable(width="100%", thickness=0.4, color=DIVIDER, spaceAfter=4)) i += 1; continue # ## H2 if H2_RE.match(line): clean = re.sub(r'^##\s+', '', line) story.append(KeepTogether([ Spacer(1, 4*mm), SectionHeading(clean), Spacer(1, 2.5*mm), ])) i += 1; continue # ### H3 if H3_RE.match(line): clean = re.sub(r'^###\s+', '', line) story.append(Spacer(1, 3*mm)) story.append(Paragraph(_md(clean), S["h3"])) story.append(HRFlowable(width="40%", thickness=1, color=GOLD, spaceAfter=2)) i += 1; continue # Numbered list if OL_RE.match(line): items = [] while i < len(lines): m2 = OL_RE.match(lines[i].strip()) if not m2: break items.append((m2.group(1), False)) i += 1 story.append(_bullet_list(items, S, ordered=True)) continue # Bullet list (with optional + sub-items) if BULLET_RE.match(line) or SUB_RE.match(line): items = [] while i < len(lines): l2 = lines[i].strip() mb = BULLET_RE.match(l2) ms = SUB_RE.match(l2) if mb: items.append((mb.group(1), False)); i += 1 elif ms: items.append((ms.group(1), True)); i += 1 else: break if items: story.append(_bullet_list(items, S)) continue # Plain paragraph story.append(Paragraph(_md(line), S["body"])) i += 1 doc.build(story) if not output_path and isinstance(target, io.BytesIO): return target.getvalue() # ─── DEMO ───────────────────────────────────────────────────────────────────── if __name__ == "__main__": sample = """ === INFORMATION SECURITY FOUNDATIONS === Information Security Foundations ===================================== Definition Information security refers to the practice of protecting information from unauthorized access, use, disclosure, disruption, modification, or destruction. It involves a set of strategies, policies, and procedures to ensure the confidentiality, integrity, and availability of information. Key Concepts * **Confidentiality:** Protecting information from unauthorized access or disclosure. * **Integrity:** Ensuring that information is accurate, complete, and not modified without authorization. * **Availability:** Ensuring that information is accessible and usable when needed. * **Authentication:** Verifying the identity of users, systems, or entities. * **Non-repudiation:** Ensuring that a sender of a message cannot deny having sent the message. Types/Categories of Information Security * **Network Security:** Protecting networks from unauthorized access, use, or malicious activities. + Firewalls and IDS + VPN and encrypted tunnels * **Application Security:** Protecting software applications from vulnerabilities. * **Data Security:** Protecting data from unauthorized access, use, or disclosure. * **Cloud Security:** Protecting cloud-based infrastructure, data, and applications from threats. Important Points * **Risk Management:** Identifying, assessing, and mitigating risks to information security. * **Threats:** Potential occurrences that could compromise security such as hacking or malware. * **Vulnerabilities:** Weaknesses in systems that can be exploited by threats. * **Incident Response:** Responding to and managing security incidents. * **Compliance:** Adhering to laws like GDPR or HIPAA. Brief Summary Information security foundations involve protecting information from unauthorized access. Key concepts include confidentiality, integrity, availability, authentication, and non-repudiation. By understanding these principles, individuals and organizations can establish a strong security foundation. === SYMMETRIC AND ASYMMETRIC CRYPTOGRAPHY === Introduction to Cryptography Cryptography is the practice of secure communication by transforming **plaintext** into unreadable **ciphertext** to protect it from unauthorized access. Key Concepts * **Encryption:** The process of converting plaintext into ciphertext. * **Decryption:** The process of converting ciphertext back into plaintext. * **Key:** A secret code used for encryption and decryption. ## Symmetric Cryptography Definition: Symmetric cryptography uses the **same secret key** for both encryption and decryption. Types/Categories * Block Ciphers: Divide data into fixed-length blocks (e.g., **AES**). * Stream Ciphers: Encrypt data one bit or byte at a time (e.g., **RC4**). Important Points * Advantages: + Fast and efficient + Easy to implement + Low computational overhead * Disadvantages: + Key management is a major challenge + Not suitable for large-scale networks ## Asymmetric Cryptography Definition: Asymmetric cryptography uses a **pair of keys**: a public key for encryption and a private key for decryption. Types/Categories * **RSA** (Rivest-Shamir-Adleman): A widely used asymmetric encryption algorithm. * **Elliptic Curve Cryptography (ECC):** Uses elliptic curves for stronger security with smaller keys. Brief Summary Symmetric cryptography is fast and efficient but has key management challenges. Asymmetric cryptography provides secure key exchange and authentication but is computationally intensive. """ pdf1(sample, "/mnt/user-data/outputs/notes.pdf")