[{"data":1,"prerenderedAt":252},["ShallowReactive",2],{"blog-slugs":3,"project-rezuma-en":8},{"en":4,"ar":7},[5,6],"dynamic-generic-slots","from-renderless-component-to-composable-function",[5,6],{"id":9,"title":10,"body":11,"description":244,"extension":245,"meta":246,"navigation":247,"path":248,"seo":249,"stem":250,"__hash__":251},"projects/projects/en/rezuma.md","Rezuma",{"type":12,"value":13,"toc":236},"minimark",[14,19,23,27,30,33,37,44,175,178,182,189,192,215,218,222,225,229,232],[15,16,18],"h2",{"id":17},"why","Why",[20,21,22],"p",{},"A resume can look right in a preview and still lose text during PDF export. Rezuma checks text extraction from its sample PDFs with pdf.js.",[15,24,26],{"id":25},"a-pdf-with-real-text","A PDF with real text",[20,28,29],{},"The exporter uses jsPDF to draw text rather than turn the preview into an image. It embeds Source Serif 4 or Source Sans 3, or Noto Naskh Arabic and Noto Sans Arabic for Arabic. The fonts are subsetted and fetched at export time to keep them out of the initial bundle.",[20,31,32],{},"Layout uses two passes: content is measured into groups, then paginated. Grouping keeps job titles with their dates and section headings with their first entry, and limits widows and orphans. The preview uses the same font families as webfonts.",[15,34,36],{"id":35},"verifying-the-export","Verifying the export",[20,38,39,43],{},[40,41,42],"code",{},"pnpm verify:pdf"," generates sample PDFs, extracts their text with pdf.js, and checks that the names, employers, dates, bullets and skills in the sample resumes survive extraction, accents included.",[45,46,51],"pre",{"className":47,"code":48,"language":49,"meta":50,"style":50},"language-bash shiki shiki-themes site-light site-light site-dark","AR / classic / sidebar\n  file        ar-classic-sidebar.pdf (65 KB, 1 page)\n  extracted   2563 chars\n  checks      51/51 found\n  order       summary → experience → skills → education\n  arabic      1554 letters (61% of the text)\n","bash","",[40,52,53,74,100,112,124,149],{"__ignoreMap":50},[54,55,58,62,66,69,71],"span",{"class":56,"line":57},"line",1,[54,59,61],{"class":60},"sUqqj","AR",[54,63,65],{"class":64},"sgVH1"," /",[54,67,68],{"class":64}," classic",[54,70,65],{"class":64},[54,72,73],{"class":64}," sidebar\n",[54,75,77,80,83,87,90,94,97],{"class":56,"line":76},2,[54,78,79],{"class":60},"  file",[54,81,82],{"class":64},"        ar-classic-sidebar.pdf",[54,84,86],{"class":85},"sBiod"," (65 ",[54,88,89],{"class":64},"KB,",[54,91,93],{"class":92},"sJ-0L"," 1",[54,95,96],{"class":64}," page",[54,98,99],{"class":85},")\n",[54,101,103,106,109],{"class":56,"line":102},3,[54,104,105],{"class":60},"  extracted",[54,107,108],{"class":92},"   2563",[54,110,111],{"class":64}," chars\n",[54,113,115,118,121],{"class":56,"line":114},4,[54,116,117],{"class":60},"  checks",[54,119,120],{"class":64},"      51/51",[54,122,123],{"class":64}," found\n",[54,125,127,130,133,136,139,141,144,146],{"class":56,"line":126},5,[54,128,129],{"class":60},"  order",[54,131,132],{"class":64},"       summary",[54,134,135],{"class":64}," →",[54,137,138],{"class":64}," experience",[54,140,135],{"class":64},[54,142,143],{"class":64}," skills",[54,145,135],{"class":64},[54,147,148],{"class":64}," education\n",[54,150,152,155,158,161,164,167,170,173],{"class":56,"line":151},6,[54,153,154],{"class":60},"  arabic",[54,156,157],{"class":92},"      1554",[54,159,160],{"class":64}," letters",[54,162,163],{"class":85}," (61% ",[54,165,166],{"class":64},"of",[54,168,169],{"class":64}," the",[54,171,172],{"class":64}," text",[54,174,99],{"class":85},[20,176,177],{},"The nine test cases cover three languages, two styles and four layouts. Expected section order comes from the layout configuration. These checks show what pdf.js extracts from the tested files; they do not establish how a particular applicant tracking system will interpret them.",[15,179,181],{"id":180},"arabic-and-right-to-left","Arabic and right-to-left",[20,183,184,185,188],{},"Switching the interface to Arabic sets ",[40,186,187],{},"dir=\"rtl\""," on the document. The stylesheets use logical properties to mirror the editor, toolbar and resume layout.",[20,190,191],{},"The PDF takes more work:",[193,194,195,203,209],"ul",{},[196,197,198,202],"li",{},[199,200,201],"strong",{},"Shaping."," Letters are substituted with Arabic Presentation Forms before drawing, so they join, and measurement runs the same pass.",[196,204,205,208],{},[199,206,207],{},"Line breaking."," Arabic uses a custom greedy wrap that measures the shaped text, rather than relying on jsPDF's wrapping of unshaped text.",[196,210,211,214],{},[199,212,213],{},"Extraction."," Text comes back as presentation forms. The verification script uses NFKC normalisation to fold it back to base letters before checking it.",[20,216,217],{},"Dates use Latin digits in Arabic exports as a compatibility choice for date parsers.",[15,219,221],{"id":220},"privacy","Privacy",[20,223,224],{},"Rezuma works without an account and stores resume content in your browser's local storage. It generates PDFs locally. You can download a PDF, save your resume as JSON, or open a saved JSON file to continue editing.",[15,226,228],{"id":227},"landing-page-effects","Landing page effects",[20,230,231],{},"The landing page's effects (an aurora written as one fragment shader in raw WebGL2, a canvas dot grid, split and scrambled headings) add no dependency. With reduced motion enabled the page shows its final state, and animated text keeps an intact copy in the accessibility tree.",[233,234,235],"style",{},"html pre.shiki code .sUqqj, html code.shiki .sUqqj{--shiki-light:#4A3170;--shiki-default:#4A3170;--shiki-dark:#D9BDF0}html pre.shiki code .sgVH1, html code.shiki .sgVH1{--shiki-light:#3A6830;--shiki-default:#3A6830;--shiki-dark:#A5CF93}html pre.shiki code .sBiod, html code.shiki .sBiod{--shiki-light:#322C28;--shiki-default:#322C28;--shiki-dark:#DBD7D0}html pre.shiki code .sJ-0L, html code.shiki .sJ-0L{--shiki-light:#2D54A0;--shiki-default:#2D54A0;--shiki-dark:#93BDF5}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":50,"searchDepth":76,"depth":76,"links":237},[238,239,240,241,242,243],{"id":17,"depth":76,"text":18},{"id":25,"depth":76,"text":26},{"id":35,"depth":76,"text":36},{"id":180,"depth":76,"text":181},{"id":220,"depth":76,"text":221},{"id":227,"depth":76,"text":228},"Build a resume in your browser and export a PDF with selectable text.","md",{},true,"/projects/en/rezuma",{"title":10,"description":244},"projects/en/rezuma","jn4mm9OShfQXVKlGqhIzF1F8QudDvpVh6kWLByaBDdQ",1791794146535]