feat: add build-cv-latex.mjs -- structured JSON to LaTeX renderer#905
Conversation
LaTeX twin of issue #557 (HTML builder). The agent previously wrote raw LaTeX (~8-10K tokens) and often missed escaping special chars, causing silent compile failures. Now the agent writes 2-3K tokens of JSON and the script handles template merge + LaTeX escaping. - New: build-cv-latex.mjs -- reads JSON payload, produces .tex via template - Updated: modes/latex.md -- pipeline now uses JSON + script, adds schema docs - Updated: docs/SCRIPTS.md -- reference entry for the new script - generate-latex.mjs and templates/cv-template.tex untouched Closes #47
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds build-cv-latex.mjs: a Node.js ESM CLI that converts structured JSON into a LaTeX .tex using a template, with escaping, URL sanitization, section builders, unresolved-placeholder validation, a self-test, and documentation updates describing usage and JSON schema. ChangesLaTeX CV Build Tool
Sequence DiagramsequenceDiagram
participant User as CLI invoker
participant Script as build-cv-latex.mjs
participant Template as templates/cv-template.tex
participant Builders as section builders
participant FS as FileSystem
User->>Script: run with input.json output.tex
Script->>Template: load template.tex
Script->>Builders: build sections from JSON
Builders-->>Script: LaTeX blocks
Script->>Template: substitute placeholders
Script->>FS: write output.tex
FS-->>Script: confirm write + size
Script-->>User: print JSON report
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Hello there is a good
…On Wed, 10 Jun 2026, 10:45 am Abuzar Khan, ***@***.***> wrote:
Summary
Adds build-cv-latex.mjs — the LaTeX twin of #557
<#557> (HTML builder). The
agent previously wrote ~8-10K tokens of raw LaTeX and frequently missed
escaping special chars, causing silent compile failures. Now the agent
writes ~2-3K tokens of structured JSON and the script handles template
merge + LaTeX escaping.
Changes
- *New:* build-cv-latex.mjs — reads JSON payload, produces .tex via
templates/cv-template.tex, handles all LaTeX escaping automatically
- *Updated:* modes/latex.md — pipeline now uses JSON +
build-cv-latex.mjs, adds full JSON schema documentation
- *Updated:* docs/SCRIPTS.md — reference entry for the new script
- generate-latex.mjs and templates/cv-template.tex untouched (per
maintainer request)
JSON Input Schema (agent writes this, ~2-3K tokens)
{
"name": "Jane Smith",
"contact_line": "San Francisco, CA | +1 415 555 0100",
"email": { "url": ***@***.***", "display": ***@***.***" },
"linkedin": { "url": "...", "display": "..." },
"github": { "url": "...", "display": "..." },
"education": [{ "institution": "...", "location": "...", "degree": "...", "dates": "...", "coursework": ["..."] }],
"experience": [{ "company": "...", "role": "...", "location": "...", "dates": "...", "bullets": ["..."] }],
"projects": [{ "name": "...", "context": "...", "dates": "...", "bullets": ["..."] }],
"skills": [{ "category": "...", "items": "..." }]
}
Verification
- node --check build-cv-latex.mjs — syntax OK
- node build-cv-latex.mjs --test — self-test passes
- Full pipeline test: JSON → build-cv-latex.mjs → .tex →
generate-latex.mjs → PDF (0 errors)
- node test-all.mjs --quick — 164 passed, 0 failed
Closes #47 <#47>
------------------------------
You can view, comment on, or merge this pull request online at:
#905
Commit Summary
- 41496e1
<41496e1>
feat: add build-cv-latex.mjs -- structured JSON to LaTeX renderer
File Changes
(3 files <https://github.com/santifer/career-ops/pull/905/files>)
- *A* build-cv-latex.mjs
<https://github.com/santifer/career-ops/pull/905/files#diff-4cd8635c0fdd847ce0489f832ff10999eb037394295f6fe5db15e6071a11fe51>
(306)
- *M* docs/SCRIPTS.md
<https://github.com/santifer/career-ops/pull/905/files#diff-392f26ac1abf56cad70b5b030b5c58cf271a0ac3de1269e8c8f6c8be22e3ac05>
(14)
- *M* modes/latex.md
<https://github.com/santifer/career-ops/pull/905/files#diff-fc407591e6eb88bb94320c594a0f4f8468afe408982907d265844140da48c33c>
(166)
Patch Links:
- https://github.com/santifer/career-ops/pull/905.patch
- https://github.com/santifer/career-ops/pull/905.diff
—
Reply to this email directly, view it on GitHub
<#905?email_source=notifications&email_token=B5KYPUIMEYKUSCOQSSNIDUL47EU4ZA5CNFSNUABEM5UWIORPF5TWS5BNNB2WEL2QOVWGYUTFOF2WK43UF4ZTQMZYGM2DOMZYHGTHEZLBONXW5KTTOVRHGY3SNFRGKZFFMV3GK3TUVRTG633UMVZF6Y3MNFRWW>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/B5KYPUMDYDEC4ABKNSIDHQT47EU4ZAVCNFSNUABGKJSXA33TNF2G64TZHMYTEMBRGQ3TMNJZGQ5US43TOVSTWNBWGI4TSNRUGUZDNILWAI>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
|
🎉
Ligirlburg reacted via Gmail
<https://www.google.com/gmail/about/?utm_source=gmail-in-product&utm_medium=et&utm_campaign=emojireactionemail#app>
On Wed, 10 Jun 2026, 10:46 am Ligirlburg Ligirlburg123, <
***@***.***> wrote:
… Hello there is a good
On Wed, 10 Jun 2026, 10:45 am Abuzar Khan, ***@***.***>
wrote:
> Summary
>
> Adds build-cv-latex.mjs — the LaTeX twin of #557
> <#557> (HTML builder). The
> agent previously wrote ~8-10K tokens of raw LaTeX and frequently missed
> escaping special chars, causing silent compile failures. Now the agent
> writes ~2-3K tokens of structured JSON and the script handles template
> merge + LaTeX escaping.
> Changes
>
> - *New:* build-cv-latex.mjs — reads JSON payload, produces .tex via
> templates/cv-template.tex, handles all LaTeX escaping automatically
> - *Updated:* modes/latex.md — pipeline now uses JSON +
> build-cv-latex.mjs, adds full JSON schema documentation
> - *Updated:* docs/SCRIPTS.md — reference entry for the new script
> - generate-latex.mjs and templates/cv-template.tex untouched (per
> maintainer request)
>
> JSON Input Schema (agent writes this, ~2-3K tokens)
>
> {
> "name": "Jane Smith",
> "contact_line": "San Francisco, CA | +1 415 555 0100",
> "email": { "url": ***@***.***", "display": ***@***.***" },
> "linkedin": { "url": "...", "display": "..." },
> "github": { "url": "...", "display": "..." },
> "education": [{ "institution": "...", "location": "...", "degree": "...", "dates": "...", "coursework": ["..."] }],
> "experience": [{ "company": "...", "role": "...", "location": "...", "dates": "...", "bullets": ["..."] }],
> "projects": [{ "name": "...", "context": "...", "dates": "...", "bullets": ["..."] }],
> "skills": [{ "category": "...", "items": "..." }]
> }
>
> Verification
>
> - node --check build-cv-latex.mjs — syntax OK
> - node build-cv-latex.mjs --test — self-test passes
> - Full pipeline test: JSON → build-cv-latex.mjs → .tex →
> generate-latex.mjs → PDF (0 errors)
> - node test-all.mjs --quick — 164 passed, 0 failed
>
> Closes #47 <#47>
> ------------------------------
> You can view, comment on, or merge this pull request online at:
>
> #905
> Commit Summary
>
> - 41496e1
> <41496e1>
> feat: add build-cv-latex.mjs -- structured JSON to LaTeX renderer
>
> File Changes
>
> (3 files <https://github.com/santifer/career-ops/pull/905/files>)
>
> - *A* build-cv-latex.mjs
> <https://github.com/santifer/career-ops/pull/905/files#diff-4cd8635c0fdd847ce0489f832ff10999eb037394295f6fe5db15e6071a11fe51>
> (306)
> - *M* docs/SCRIPTS.md
> <https://github.com/santifer/career-ops/pull/905/files#diff-392f26ac1abf56cad70b5b030b5c58cf271a0ac3de1269e8c8f6c8be22e3ac05>
> (14)
> - *M* modes/latex.md
> <https://github.com/santifer/career-ops/pull/905/files#diff-fc407591e6eb88bb94320c594a0f4f8468afe408982907d265844140da48c33c>
> (166)
>
> Patch Links:
>
> - https://github.com/santifer/career-ops/pull/905.patch
> - https://github.com/santifer/career-ops/pull/905.diff
>
> —
> Reply to this email directly, view it on GitHub
> <#905?email_source=notifications&email_token=B5KYPUIMEYKUSCOQSSNIDUL47EU4ZA5CNFSNUABEM5UWIORPF5TWS5BNNB2WEL2QOVWGYUTFOF2WK43UF4ZTQMZYGM2DOMZYHGTHEZLBONXW5KTTOVRHGY3SNFRGKZFFMV3GK3TUVRTG633UMVZF6Y3MNFRWW>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/B5KYPUMDYDEC4ABKNSIDHQT47EU4ZAVCNFSNUABGKJSXA33TNF2G64TZHMYTEMBRGQ3TMNJZGQ5US43TOVSTWNBWGI4TSNRUGUZDNILWAI>
> .
> You are receiving this because you are subscribed to this thread.Message
> ID: ***@***.***>
>
|
|
Hello there is it OK
|
|
How much u have to see
…On Wed, 10 Jun 2026, 10:46 am coderabbitai[bot], ***@***.***> wrote:
*coderabbitai[bot]* left a comment (santifer/career-ops#905)
<#905 (comment)>
Note
Currently processing new changes in this PR. This may take a few minutes,
please wait...
⚙️ Run configuration
*Configuration used*: Path: .coderabbit.yaml
*Review profile*: ASSERTIVE
*Plan*: Pro
*Run ID*: 53b90f5b-91b2-4f0d-a145-8d639bf1ba69
📥 Commits
Reviewing files that changed from the base of the PR and between 214f5f8
<214f5f8>
and 41496e1
<41496e1>
.
📒 Files selected for processing (3)
- build-cv-latex.mjs
- docs/SCRIPTS.md
- modes/latex.md
________________________________________________________________________
< Making the Death Star fully operational, with zero exhaust port flaws. >
------------------------------------------------------------------------
\
\ (\__/)
(•ㅅ•)
/ づ
✨ Finishing Touches 🧪 Generate unit tests (beta)
- Create PR with unit tests
------------------------------
Thanks for using CodeRabbit
<https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=santifer/career-ops&utm_content=905>!
It's free for OSS, and your support helps us grow. If you like it, consider
giving us a shout-out.
❤️ Share
- X
<https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai>
- Mastodon
<https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai>
- Reddit
<https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai>
- LinkedIn
<https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code>
Comment @coderabbitai help to get the list of available commands and
usage tips.
Tip
You can validate your CodeRabbit configuration file in your editor.
If your editor has YAML language server, you can enable auto-completion
and validation by adding # yaml-language-server: $schema=
https://coderabbit.ai/integrations/schema.v2.json at the top of your
CodeRabbit configuration file.
—
Reply to this email directly, view it on GitHub
<#905?email_source=notifications&email_token=B5KYPUKPVMUP4YEWRZIKXR347EVADA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTINRWHA3TMMRQGYY2M4TFMFZW63VKON2WE43DOJUWEZLEUVSXMZLOOSWGM33PORSXEX3DNRUWG2Y#issuecomment-4668762061>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/B5KYPUMSGNIRO72VQMUCUQL47EVADAVCNFSNUABGKJSXA33TNF2G64TZHMYTEMBRGQ3TMNJZGQ5US43TOVSTWNBWGI4TSNRUGUZDNILWAI>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
|
🎉
Ligirlburg reacted via Gmail
<https://www.google.com/gmail/about/?utm_source=gmail-in-product&utm_medium=et&utm_campaign=emojireactionemail#app>
On Wed, 10 Jun 2026, 10:47 am Ligirlburg Ligirlburg123, <
***@***.***> wrote:
… How much u have to see
On Wed, 10 Jun 2026, 10:46 am coderabbitai[bot], ***@***.***>
wrote:
> *coderabbitai[bot]* left a comment (santifer/career-ops#905)
> <#905 (comment)>
>
> Note
>
> Currently processing new changes in this PR. This may take a few minutes,
> please wait...
> ⚙️ Run configuration
>
> *Configuration used*: Path: .coderabbit.yaml
>
> *Review profile*: ASSERTIVE
>
> *Plan*: Pro
>
> *Run ID*: 53b90f5b-91b2-4f0d-a145-8d639bf1ba69
> 📥 Commits
>
> Reviewing files that changed from the base of the PR and between 214f5f8
> <214f5f8>
> and 41496e1
> <41496e1>
> .
> 📒 Files selected for processing (3)
>
> - build-cv-latex.mjs
> - docs/SCRIPTS.md
> - modes/latex.md
>
> ________________________________________________________________________
> < Making the Death Star fully operational, with zero exhaust port flaws. >
> ------------------------------------------------------------------------
> \
> \ (\__/)
> (•ㅅ•)
> / づ
>
> ✨ Finishing Touches 🧪 Generate unit tests (beta)
>
> - Create PR with unit tests
>
> ------------------------------
>
> Thanks for using CodeRabbit
> <https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=santifer/career-ops&utm_content=905>!
> It's free for OSS, and your support helps us grow. If you like it, consider
> giving us a shout-out.
> ❤️ Share
>
> - X
> <https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai>
> - Mastodon
> <https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai>
> - Reddit
> <https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai>
> - LinkedIn
> <https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code>
>
> Comment @coderabbitai help to get the list of available commands and
> usage tips.
>
> Tip
> You can validate your CodeRabbit configuration file in your editor.
>
> If your editor has YAML language server, you can enable auto-completion
> and validation by adding # yaml-language-server: $schema=
> https://coderabbit.ai/integrations/schema.v2.json at the top of your
> CodeRabbit configuration file.
>
> —
> Reply to this email directly, view it on GitHub
> <#905?email_source=notifications&email_token=B5KYPUKPVMUP4YEWRZIKXR347EVADA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTINRWHA3TMMRQGYY2M4TFMFZW63VKON2WE43DOJUWEZLEUVSXMZLOOSWGM33PORSXEX3DNRUWG2Y#issuecomment-4668762061>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/B5KYPUMSGNIRO72VQMUCUQL47EVADAVCNFSNUABGKJSXA33TNF2G64TZHMYTEMBRGQ3TMNJZGQ5US43TOVSTWNBWGI4TSNRUGUZDNILWAI>
> .
> You are receiving this because you are subscribed to this thread.Message
> ID: ***@***.***>
>
|
|
Tip For best results, initiate chat on the files or code changes.
I read through all of it to check for bugs, security issues, missing error handling, and documentation accuracy. Nothing too heavy for this one! 🐇 |
|
Tip For best results, initiate chat on the files or code changes.
(ᵔᴥᵔ) |
|
Good to hear 👂 you
|
|
Hello 👋 and thanks |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@build-cv-latex.mjs`:
- Around line 16-18: The backslash-to-\textbackslash{} substitution currently
runs before the brace-escaping call and therefore its inserted "{ }" get
escaped; reorder the chain so that brace and caret escapes run first and the
backslash replacement runs last (i.e., move the .replace(/\\/g, ...) after
.replace(/([{}])/g, ...) and .replace(/\^/g, ...)) so generated \textbackslash{}
is not mutated; update the replace sequence in build-cv-latex.mjs accordingly,
keeping the same regexes/strings but changing their order.
- Around line 29-69: The code currently calls .map on fields that are only
truthy-checked and will throw if the payload has non-array types; update
buildEducation (e.coursework), buildExperience (e.bullets), buildProjects
(e.bullets) and buildSkills (c.items) to first validate/coerce types (use
Array.isArray or cast to [] when not an array) before mapping, and when items
may be arrays join them (e.g., items.join(', ')) and pass elements through
escapeLatex; keep using escapeLatex for each element and ensure empty or missing
values produce empty strings rather than throwing.
- Around line 118-133: The URL values EMAIL_URL / LINKEDIN_URL / GITHUB_URL are
inserted raw into the LaTeX \href argument which allows template injection via
characters like "}" or "\"; validate and sanitize these fields before insertion:
implement a URL sanitizer used when assigning emailUrl/linkedinUrl/githubUrl
that (1) validates the scheme against an allowlist (mailto, http, https), (2)
percent-encodes or removes dangerous characters (e.g. backslash, braces) or
otherwise encodes them so they cannot break out of \href, and (3) falls back to
an empty string or safe placeholder on invalid input; alternatively apply the
existing escapeLatex function (or a dedicated escapeLatexForHref) to these URL
variables before placing them into the substitutions object so EMAIL_URL,
LINKEDIN_URL and GITHUB_URL are safe.
In `@modes/latex.md`:
- Line 126: Update the documented section header names so they match the actual
template: replace "Experience" with "Work Experience" and "Projects" with
"Personal Projects" in the noted documentation snippet (the line that currently
reads "Standard Jake's Resume section headers: Education, Experience, Projects,
Technical Skills") to align with the template's actual headers.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 53b90f5b-91b2-4f0d-a145-8d639bf1ba69
📒 Files selected for processing (3)
build-cv-latex.mjsdocs/SCRIPTS.mdmodes/latex.md
|
U have Google chat
…On Wed, 10 Jun 2026, 10:49 am coderabbitai[bot], ***@***.***> wrote:
*coderabbitai[bot]* left a comment (santifer/career-ops#905)
<#905 (comment)>
Tip
For best results, initiate chat on the files or code changes.
@lligirlburg-wq For this PR, I reviewed all 3 changed files:
- *build-cv-latex.mjs* — 306 lines (the main new script)
- *modes/latex.md* — 166 lines (updated pipeline docs)
- *docs/SCRIPTS.md* — 14 lines (reference entry)
I read through all of it to check for bugs, security issues, missing error
handling, and documentation accuracy. Nothing too heavy for this one! 🐇
—
Reply to this email directly, view it on GitHub
<#905?email_source=notifications&email_token=B5KYPUOQYKYWXOT57IX2NET47EVJNA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTINRWHA3TQNZSGMZKM4TFMFZW63VHMNXW23LFNZ2KKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-4668787232>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/B5KYPUMMUKA2RBDBF6M3OSD47EVJNAVCNFSNUABGKJSXA33TNF2G64TZHMYTEMBRGQ3TMNJZGQ5US43TOVSTWNBWGI4TSNRUGUZDNILWAI>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
|
🎉
Ligirlburg reacted via Gmail
<https://www.google.com/gmail/about/?utm_source=gmail-in-product&utm_medium=et&utm_campaign=emojireactionemail#app>
On Wed, 10 Jun 2026, 10:52 am Ligirlburg Ligirlburg123, <
***@***.***> wrote:
… U have Google chat
On Wed, 10 Jun 2026, 10:49 am coderabbitai[bot], ***@***.***>
wrote:
> *coderabbitai[bot]* left a comment (santifer/career-ops#905)
> <#905 (comment)>
>
> Tip
>
> For best results, initiate chat on the files or code changes.
>
> @lligirlburg-wq For this PR, I reviewed all 3 changed files:
>
> - *build-cv-latex.mjs* — 306 lines (the main new script)
> - *modes/latex.md* — 166 lines (updated pipeline docs)
> - *docs/SCRIPTS.md* — 14 lines (reference entry)
>
> I read through all of it to check for bugs, security issues, missing
> error handling, and documentation accuracy. Nothing too heavy for this one!
> 🐇
>
> —
> Reply to this email directly, view it on GitHub
> <#905?email_source=notifications&email_token=B5KYPUOQYKYWXOT57IX2NET47EVJNA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTINRWHA3TQNZSGMZKM4TFMFZW63VHMNXW23LFNZ2KKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-4668787232>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/B5KYPUMMUKA2RBDBF6M3OSD47EVJNAVCNFSNUABGKJSXA33TNF2G64TZHMYTEMBRGQ3TMNJZGQ5US43TOVSTWNBWGI4TSNRUGUZDNILWAI>
> .
> You are receiving this because you commented.Message ID:
> ***@***.***>
>
|
|
🤣
Ligirlburg reacted via Gmail
<https://www.google.com/gmail/about/?utm_source=gmail-in-product&utm_medium=et&utm_campaign=emojireactionemail#app>
On Wed, 10 Jun 2026, 10:52 am Ligirlburg Ligirlburg123, <
***@***.***> wrote:
… U have Google chat
On Wed, 10 Jun 2026, 10:49 am coderabbitai[bot], ***@***.***>
wrote:
> *coderabbitai[bot]* left a comment (santifer/career-ops#905)
> <#905 (comment)>
>
> Tip
>
> For best results, initiate chat on the files or code changes.
>
> @lligirlburg-wq For this PR, I reviewed all 3 changed files:
>
> - *build-cv-latex.mjs* — 306 lines (the main new script)
> - *modes/latex.md* — 166 lines (updated pipeline docs)
> - *docs/SCRIPTS.md* — 14 lines (reference entry)
>
> I read through all of it to check for bugs, security issues, missing
> error handling, and documentation accuracy. Nothing too heavy for this one!
> 🐇
>
> —
> Reply to this email directly, view it on GitHub
> <#905?email_source=notifications&email_token=B5KYPUOQYKYWXOT57IX2NET47EVJNA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTINRWHA3TQNZSGMZKM4TFMFZW63VHMNXW23LFNZ2KKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-4668787232>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/B5KYPUMMUKA2RBDBF6M3OSD47EVJNAVCNFSNUABGKJSXA33TNF2G64TZHMYTEMBRGQ3TMNJZGQ5US43TOVSTWNBWGI4TSNRUGUZDNILWAI>
> .
> You are receiving this because you commented.Message ID:
> ***@***.***>
>
|
…nitization, section headers - Fix escapeLatex: move backslash replacement after brace escape so \textbackslash is not mutated - Add Array.isArray guards in buildEducation, buildExperience, buildProjects, buildSkills - Add sanitizeUrl() for href URL arguments (scheme validation + dangerous char removal) - Fix modes/latex.md section headers to match template (Work Experience, Personal Projects)
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
modes/latex.md (2)
18-19: 🧹 Nitpick | 🔵 Trivial | 💤 Low valueConsider clarifying placeholder syntax in command examples.
The command examples use curly-brace syntax (
{candidate},{company},{YYYY-MM-DD}) which could be read as literal CLI syntax rather than documentation placeholders. Consider adding a brief note that these should be replaced with actual values, or use angle-bracket notation (<candidate>) which is a more common documentation convention for placeholders.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@modes/latex.md` around lines 18 - 19, Update the example commands for build-cv-latex.mjs and generate-latex.mjs to clarify that `{candidate}`, `{company}`, and `{YYYY-MM-DD}` are documentation placeholders to be replaced with real values; either replace the curly-brace placeholders with angle-bracket notation like `<candidate> <company> <YYYY-MM-DD>` or add a single short note after the two lines stating "Replace placeholders with actual values" so users of node build-cv-latex.mjs and node generate-latex.mjs won’t mistake them for literal CLI tokens.
121-121:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winClarify that URLs are validated despite not being LaTeX-escaped.
The documentation states URLs are "NOT escaped" but doesn't mention they ARE validated and sanitized. According to the commit message,
sanitizeUrl()performs scheme validation and dangerous-character removal. Add a clarification that while URLs skip LaTeX escaping (to preserve href functionality), they undergo security validation to prevent injection attacks.📝 Suggested clarification
-**Exception:** URLs inside `\href{}` are NOT escaped — the script skips the URL argument. +**Exception:** URLs inside `\href{}` are NOT LaTeX-escaped (to preserve valid hrefs), but ARE validated and sanitized (scheme check + dangerous-character removal) before insertion.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@modes/latex.md` at line 121, Update the "Exception: URLs inside `\href{}` are NOT escaped" note to clarify that although the URL argument is not LaTeX-escaped (to preserve link functionality), it is still validated and sanitized by sanitizeUrl(): state that sanitizeUrl() enforces allowed schemes and removes dangerous characters/segments to prevent injection attacks, and mention this applies specifically to URLs passed to \href{} so readers know escaping is skipped but security checks still occur.
♻️ Duplicate comments (1)
build-cv-latex.mjs (1)
16-25:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winBackslash escape pass is corrupting previously escaped LaTeX sequences.
On Line 24, replacing
\last rewrites the backslashes introduced on Lines 17–23 (for example\_,\%,\textasciicircum{}), producing invalid output and likely LaTeX compile failures.Suggested minimal fix
function escapeLatex(text, mode = 'text') { if (typeof text !== 'string') return ''; if (mode === 'url') return text; return text + .replace(/\\/g, '<<BACKSLASH>>') .replace(/([{}])/g, '\\$1') // braces first so inserted \\textbackslash etc are not mutated .replace(/\^/g, '\\textasciicircum{}') .replace(/~/g, '\\textasciitilde{}') .replace(/_/g, '\\_') .replace(/&/g, '\\&') .replace(/%/g, '\\%') .replace(/\$/g, '\\$') .replace(/#/g, '\\#') - .replace(/\\/g, '\\textbackslash{}') // backslash last — safe after braces are escaped .replace(/±/g, '$\\pm$') - .replace(/→/g, '$\\rightarrow$'); + .replace(/→/g, '$\\rightarrow$') + .replace(/<<BACKSLASH>>/g, '\\textbackslash{}'); }As per coding guidelines, "Ensure scripts handle missing data/ directories gracefully" and this escaping regression breaks core rendering behavior in the processing path.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@build-cv-latex.mjs` around lines 16 - 25, The current replace chain reverses previously inserted escapes because .replace(/\\/g, '\\textbackslash{}') runs last; move the backslash replacement earlier so it runs before inserting sequences that include backslashes (i.e., perform .replace(/\\/g, '\\textbackslash{}') immediately after the braces escape `.replace(/([{}])/g, '\\$1')`), or alternatively use a more precise regex that only replaces original/unescaped backslashes (negative lookbehind) to avoid touching the backslashes introduced by `.replace(/\^/g...)`, `.replace(/_/g...)`, `.replace(/%/g...)`, etc.; update the replace chain accordingly around the `.replace(/\\/g, '\\textbackslash{}')` call.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@build-cv-latex.mjs`:
- Around line 29-40: sanitizeUrl currently prepends "https://" when there's no
scheme which breaks mailto links (e.g., email.url used inside \href{mailto:...}
becomes mailto:https://user@domain). Change the approach in sanitizeUrl: detect
email addresses (contains '@' and no scheme) and do not prepend any scheme for
them; alternatively add a second function sanitizeEmailUrl or an options flag
(e.g., sanitizeUrl(url, { isEmail: true })) and update callers that build
\href{mailto:...} to use the email-aware sanitizer. Keep the existing trimming
and removal of unsafe chars (the replace(/[{}%$#\\~^]/g, '') logic) for both
cases, but only add "https://" for non-email, non-scheme web URLs; update usages
that construct mailto links to call the email-specific path (or pass the flag)
instead of the current sanitizeUrl behavior.
---
Outside diff comments:
In `@modes/latex.md`:
- Around line 18-19: Update the example commands for build-cv-latex.mjs and
generate-latex.mjs to clarify that `{candidate}`, `{company}`, and
`{YYYY-MM-DD}` are documentation placeholders to be replaced with real values;
either replace the curly-brace placeholders with angle-bracket notation like
`<candidate> <company> <YYYY-MM-DD>` or add a single short note after the two
lines stating "Replace placeholders with actual values" so users of node
build-cv-latex.mjs and node generate-latex.mjs won’t mistake them for literal
CLI tokens.
- Line 121: Update the "Exception: URLs inside `\href{}` are NOT escaped" note
to clarify that although the URL argument is not LaTeX-escaped (to preserve link
functionality), it is still validated and sanitized by sanitizeUrl(): state that
sanitizeUrl() enforces allowed schemes and removes dangerous characters/segments
to prevent injection attacks, and mention this applies specifically to URLs
passed to \href{} so readers know escaping is skipped but security checks still
occur.
---
Duplicate comments:
In `@build-cv-latex.mjs`:
- Around line 16-25: The current replace chain reverses previously inserted
escapes because .replace(/\\/g, '\\textbackslash{}') runs last; move the
backslash replacement earlier so it runs before inserting sequences that include
backslashes (i.e., perform .replace(/\\/g, '\\textbackslash{}') immediately
after the braces escape `.replace(/([{}])/g, '\\$1')`), or alternatively use a
more precise regex that only replaces original/unescaped backslashes (negative
lookbehind) to avoid touching the backslashes introduced by
`.replace(/\^/g...)`, `.replace(/_/g...)`, `.replace(/%/g...)`, etc.; update the
replace chain accordingly around the `.replace(/\\/g, '\\textbackslash{}')`
call.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 39feac0e-a862-40b9-860d-77367c75cfe5
📒 Files selected for processing (2)
build-cv-latex.mjsmodes/latex.md
- sanitizeUrl: detect email addresses (contains @, no scheme) and prepend mailto: instead of https:
- modes/latex.md: add note that {placeholders} should be replaced with actual values
- modes/latex.md: clarify that sanitizeUrl still validates href URLs even when LaTeX escaping is skipped
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
modes/latex.md (1)
80-80: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winClarify that
email.urlis sanitized, not "raw".The term "Raw email" is misleading. According to context snippet 4 (build-cv-latex.mjs:137-175),
email.urlis processed bysanitizeUrl()which validates the scheme and strips dangerous characters. Consider rephrasing to reflect that it's sanitized for URL safety but not LaTeX-escaped.📝 Suggested rewording
-| `email.url` | string | Raw email for `\href{mailto:...}` (NOT escaped) | +| `email.url` | string | Email for `\href{mailto:...}` (sanitized but not LaTeX-escaped) |The same clarification applies to
linkedin.urlandgithub.urlentries below if you want consistency.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@modes/latex.md` at line 80, Change the documentation entry for email.url to state that the value is sanitized for URL safety (validated/normalized by sanitizeUrl in build-cv-latex.mjs) rather than "raw" email; update the phrasing to indicate it is safe for use in href mailto links but not LaTeX-escaped, and apply the same clarification to linkedin.url and github.url so all URL fields consistently note “sanitized for URL safety (via sanitizeUrl), not LaTeX-escaped.”
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@modes/latex.md`:
- Line 80: Change the documentation entry for email.url to state that the value
is sanitized for URL safety (validated/normalized by sanitizeUrl in
build-cv-latex.mjs) rather than "raw" email; update the phrasing to indicate it
is safe for use in href mailto links but not LaTeX-escaped, and apply the same
clarification to linkedin.url and github.url so all URL fields consistently note
“sanitized for URL safety (via sanitizeUrl), not LaTeX-escaped.”
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 01e9274a-8010-488b-9796-f92b9663e1b4
📒 Files selected for processing (2)
build-cv-latex.mjsmodes/latex.md
The previous .replace() chain had an ordering bug where & -> \& inserted a backslash that was then caught by the later \ -> \textbackslash{} replacement, producing broken output like Q\textbackslash{}&A. Character-by-character processing eliminates all ordering issues.
|
Hello 👋 🫂 sorry for the late reply
|
CodeRabbit nitpick: email.url, linkedin.url, github.url docs now state they are sanitized via sanitizeUrl() rather than raw/untouched.
|
Welcome to career-ops, @abuzarai! The JSON→LaTeX renderer with auto-escaping is a clean piece of work, and it lands as exactly what the LaTeX lane needed: an optional output path that doesn't touch the default pipeline. (I registered build-cv-latex.mjs in SYSTEM_PATHS in your branch — house checklist for new top-level files.) Merged — your first contribution here. 🚀 |
Summary
Adds
build-cv-latex.mjs— the LaTeX twin of #557 (HTML builder). The agent previously wrote ~8-10K tokens of raw LaTeX and frequently missed escaping special chars, causing silent compile failures. Now the agent writes ~2-3K tokens of structured JSON and the script handles template merge + LaTeX escaping.Changes
build-cv-latex.mjs— reads JSON payload, produces.texviatemplates/cv-template.tex, handles all LaTeX escaping automaticallymodes/latex.md— pipeline now uses JSON + build-cv-latex.mjs, adds full JSON schema documentationdocs/SCRIPTS.md— reference entry for the new scriptgenerate-latex.mjsandtemplates/cv-template.texuntouched (per maintainer request)JSON Input Schema (agent writes this, ~2-3K tokens)
{ "name": "Jane Smith", "contact_line": "San Francisco, CA | +1 415 555 0100", "email": { "url": "jane@example.com", "display": "jane@example.com" }, "linkedin": { "url": "...", "display": "..." }, "github": { "url": "...", "display": "..." }, "education": [{ "institution": "...", "location": "...", "degree": "...", "dates": "...", "coursework": ["..."] }], "experience": [{ "company": "...", "role": "...", "location": "...", "dates": "...", "bullets": ["..."] }], "projects": [{ "name": "...", "context": "...", "dates": "...", "bullets": ["..."] }], "skills": [{ "category": "...", "items": "..." }] }Verification
node --check build-cv-latex.mjs— syntax OKnode build-cv-latex.mjs --test— self-test passesbuild-cv-latex.mjs→.tex→generate-latex.mjs→ PDF (0 errors)node test-all.mjs --quick— 164 passed, 0 failedCloses #871
Related to #47
Summary by CodeRabbit
New Features
Documentation