NREHub

MedCORE PDF → HTML Conversion Guide

The complete pipeline for converting a plain MedCORE PDF into a styled, print-ready HTML document — as established with Cardiology. Reuse this for every future organ…

956 words ~4 min

MedCORE PDF → HTML Conversion Guide

The complete pipeline for converting a plain MedCORE PDF into a styled, print-ready HTML document — as established with Cardiology. Reuse this for every future organ system.


0. Location & Naming

  • Source PDF lives in MedCORE Systems/<System>/
  • Output HTML goes in the same folder, named <System> MedCORE.html (Title Case)
  • This template lives in MedCORE Systems/MedCORE Template/template.html — always start from a copy of it, never from scratch

1. Extract the PDF

pdftotext "X. System - MedCORE [Updated].pdf" /tmp/system.txt

Read the text in 500-line chunks. Known extraction artifacts:

  • Tables scramble — text arrives out of order; reconstruct by reading the page images of the PDF (open the PDF and read pages visually when a table looks wrong)
  • Ligatures break — profile → profile, bene t → benefit
  • Bold is lost — infer emphasis from the block patterns
  • Every MedCORE PDF follows the same block pattern: CORE CONCEPT / RECOGNITION PATTERN(S) / diagnostics / TREATMENT / EXAM TRAPS / POWER NUMBERS + tables + numbered algorithms. Map content into those blocks.

2. Content Rules (hard rules, never break)

  1. Preserve ALL content from the PDF — nothing dropped, nothing invented
  2. No emojis anywhere — SF Symbols only (§4). Emojis are fine in chat, banned in documents
  3. NEVER write “PMDC”, “NRE-I”, “PM&DC” or any official exam name — use “the exam”, “exam prep”, “the resident exam”
  4. Keep the house vocabulary: MedCORE, discriminator, trap, future alert, reverse-engineered pattern

3. Document Skeleton (from template.html)

Copy template.html and fill it in. The mechanics are already proven — do not redesign:

  • A4 pages: .page divs (210mm × 297mm min-height, 18mm side margins, 4mm navy top bar, page-break-after: always, padding 22mm top / 28mm bottom for the running header/footer)
  • Running header: section label left, system name right, 7pt uppercase
  • Running footer: doc title left, mono page-num chip right
  • Cover (navy gradient) → TOC (linked, numbered 1.1…) → content pages → back cover (IP notice)
  • Section headings: .section-num kicker + h2 with bottom border; h3/h4 carry SF icons
  • Hybrid boxy boxes (header band + bottom stripe, NO border-radius anywhere in the file):
    • .box.core = navy — Core Concept
    • .box.recog = teal — Recognition Pattern
    • .box.trap = red — Exam Traps / Red Flags
    • .box.power = amber — Power Numbers
    • .box.never = deep red — Never-Do / Contraindicated
    • .alert-strip = solid color band, no body — standalone urgent rules
    • .algorithm = mono protocol box
  • Tables: navy thead, zebra rows, square corners
  • Page fill: ~6 MCQ cards per page, or moderate content per page — do not let a page div overflow A4

4. Icons — SF Symbols Pipeline

Full details in memory entry mem_20260903024959_2541bc. Summary:

  1. Verify every symbol name against /Applications/SF Symbols Beta.app/Contents/Resources/Metadata/name_availability.plist (9,476 names). Never invent. Known nonexistent: microscope, siren, bacteria (use microbe)
  2. Render with Swift: NSImage(systemSymbolName:) + .SymbolConfiguration(pointSize: 96, weight: .regular), draw into an NSImage, tint with color.setFill() + rect.fill(using: .sourceAtop). Three tints: white (bands/strips), navy #1a2744 (h3/h4 headings), red #c0392b (inline warnings)
  3. Optimize: PIL — crop to alpha bbox, quantize(colors=24, method=FASTOCTREE) → ~1-2KB each
  4. Embed: CSS .sfi-{slug}-{tint} { background-image: url("data:image/png;base64,...") } injected before </style>; spans <span class="sficon sfi sfi-{slug}-{tint}" aria-hidden="true"></span>
  5. Standard icon map: lightbulb=core, scope=recognition, waveform.path.ecg=ECG/biomarkers, cross.case=diagnostics, rectangle.split.2x1=classification/comparison, checklist=criteria, stethoscope=exam/risk factors, pills=treatment, exclamationmark.triangle(.fill)=traps/warnings, xmark.octagon=never, list.number=power numbers, timer=time-critical, bolt.heart=cardiac emergency, alarm=timing, arrow.triangle.2.circlepath=differential/reference, waveform=sound, music.note=maneuvers, circle.lefthalf.filled=cyanotic, circle=acyanotic, figure.walk=PAD, drop=blood/HTN, chart.bar=data, chart.line.downtrend.xyaxis=downtrends, microbe=organisms
  6. GOTCHA: CSS class slugs use dashes, never underscores (filenames use underscores — convert). Multi-word symbols: dots → dashes too

5. MCQ Practice Session (standing format)

Full details in memory entry mem_20260903031227_00aa75. Summary:

  • One unified section 1.15 “MCQ Practice Session” — 50 questions, all unsolved, all proper full-length clinical vignette stems (never telegrams): age/sex, presentation with duration, risk factors, complete vitals line, exam findings, investigations, formal lead-in
  • Each stem carries a mono jump chip <a class="jump" href="#ans-qN">AN</a>
  • Section 1.16 “Answer Key & Full Breakdown” — one teal .ansbox per question: correct-line, Concept + .lvl chip (Recall/Interpretation/Analysis), Why-correct, Discriminator, .kill table (letter-by-letter eliminations), Trap type, Future alert
  • Questions derived from the document’s own content, proportional coverage, continuous numbering Q1..Q50

6. Build Mechanics & Gotchas

  • Write tool fails past ~90KB — write head+CSS first, then append body via bash heredocs (cat >> file << 'EOF'), splice/patch via python
  • Auto-renumber page-num spans after every splice: first is ii (TOC), rest sequential 1..N. Never hand-number
  • Verify after EVERY build (python check):
    • div balance (<div count == </div> count)
    • anchored page ids all present
    • question count == breakdown count (count breakdowns via ansbox substring — class="ansbox" never appears alone, it’s class="box recog ansbox")
    • all jump anchors resolve to ids
    • zero emoji characters, zero NRE/PMDC wording
    • icon classes: used ⊆ defined (regex sfi-([a-z0-9-]+)" vs \.sfi-([a-z0-9-]+)\s*\{)
    • no leftover placeholders ([System], SFI_CLASSES, CORRECT markers in question sections)
  • Regex danger: non-greedy .*? with DOTALL must be bounded — unanchored patterns crawl across the document and delete sections (this lost 7 pages once — recovered by rebuild)
  • &amp; in HTML text — when classifying icons by following text, match the escaped form

7. Final Checklist

  • All PDF content present and faithful
  • Zero emojis
  • Zero PMDC/NRE-I wording
  • Zero border-radius (fully boxy)
  • All icon classes resolve
  • Page numbers sequential (ii + 1..N)
  • Div balance
  • Cover, TOC, back cover present
  • @page A4 + print-color-adjust: exact for PDF export