Skip to content

feat: add build-cv-latex.mjs -- structured JSON to LaTeX renderer#905

Merged
santifer merged 7 commits into
santifer:mainfrom
abuzarai:feat/build-cv-latex
Jun 11, 2026
Merged

feat: add build-cv-latex.mjs -- structured JSON to LaTeX renderer#905
santifer merged 7 commits into
santifer:mainfrom
abuzarai:feat/build-cv-latex

Conversation

@abuzarai

@abuzarai abuzarai commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

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

  • 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": "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 OK
  • node build-cv-latex.mjs --test — self-test passes
  • Full pipeline test: JSON → build-cv-latex.mjs.texgenerate-latex.mjs → PDF (0 errors)
  • node test-all.mjs --quick — 164 passed, 0 failed

Closes #871
Related to #47

Summary by CodeRabbit

  • New Features

    • CLI tool to generate a LaTeX CV from a structured JSON payload, with automatic LaTeX escaping, URL sanitization/validation, a self-test mode, JSON output report, explicit exit codes, and support for help/test flags.
  • Documentation

    • Updated export workflow with a detailed JSON schema, usage examples, CLI usage guidance, and error-handling/validation notes.

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
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds 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.

Changes

LaTeX CV Build Tool

Layer / File(s) Summary
Escaping and URL sanitization
build-cv-latex.mjs
Implements escapeLatex(text, mode) and sanitizeUrl(url) for safe LaTeX insertion and normalized contact links.
Section builders
build-cv-latex.mjs
buildEducation(), buildExperience(), buildProjects(), buildSkills() format JSON arrays into escaped LaTeX headings, lists, and lines.
Main CLI control flow and template substitution
build-cv-latex.mjs
main() handles --help/--test/args, validates input/template, builds substitution map, replaces {{PLACEHOLDER}} tokens, errors on unresolved placeholders, writes .tex, and emits a JSON report.
Self-test execution
build-cv-latex.mjs
runSelfTest() writes a temp sample JSON, exercises the substitution/validation path against the real template, writes temp .tex to /tmp, prints self-test JSON status, and cleans up.
Script reference and usage documentation
docs/SCRIPTS.md
Adds npm run build:latex to Quick Reference and a ## build:latex section describing usage, CLI examples, and exit codes.
LaTeX mode pipeline and JSON schema documentation
modes/latex.md
Updates the LaTeX export pipeline to emit a JSON payload, run build-cv-latex.mjs then generate-latex.mjs; adds JSON input schema, field reference, and notes about automatic escaping and URL handling.

Sequence Diagram

sequenceDiagram
  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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

🔴 core-architecture

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding build-cv-latex.mjs, a new script that converts structured JSON to LaTeX.
Linked Issues check ✅ Passed The pull request fulfills all coding objectives from issue #871: implements build-cv-latex.mjs for JSON-to-LaTeX conversion, performs LaTeX escaping, leaves generate-latex.mjs unchanged, and documents the schema.
Out of Scope Changes check ✅ Passed All changes directly support the PR objectives: build-cv-latex.mjs implements the core feature, modes/latex.md documents the new pipeline, and docs/SCRIPTS.md adds the script reference.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@lligirlburg-wq

lligirlburg-wq commented Jun 10, 2026 via email

Copy link
Copy Markdown

@lligirlburg-wq

lligirlburg-wq commented Jun 10, 2026 via email

Copy link
Copy Markdown

@lligirlburg-wq

lligirlburg-wq commented Jun 10, 2026 via email

Copy link
Copy Markdown

@lligirlburg-wq

lligirlburg-wq commented Jun 10, 2026 via email

Copy link
Copy Markdown

@lligirlburg-wq

lligirlburg-wq commented Jun 10, 2026 via email

Copy link
Copy Markdown

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

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! 🐇

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@lligirlburg-wq Glad the excitement is contagious! 🎉 If you have any questions about the PR or need anything reviewed, feel free to ask anytime.

(ᵔᴥᵔ)

@lligirlburg-wq

lligirlburg-wq commented Jun 10, 2026 via email

Copy link
Copy Markdown

@lligirlburg-wq

Copy link
Copy Markdown

Hello 👋 and thanks

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 214f5f8 and 41496e1.

📒 Files selected for processing (3)
  • build-cv-latex.mjs
  • docs/SCRIPTS.md
  • modes/latex.md

Comment thread build-cv-latex.mjs Outdated
Comment thread build-cv-latex.mjs
Comment thread build-cv-latex.mjs Outdated
Comment thread modes/latex.md Outdated
@lligirlburg-wq

lligirlburg-wq commented Jun 10, 2026 via email

Copy link
Copy Markdown

@lligirlburg-wq

lligirlburg-wq commented Jun 10, 2026 via email

Copy link
Copy Markdown

@lligirlburg-wq

lligirlburg-wq commented Jun 10, 2026 via email

Copy link
Copy Markdown

…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)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 value

Consider 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 win

Clarify 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 win

Backslash 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

📥 Commits

Reviewing files that changed from the base of the PR and between 41496e1 and 8e33907.

📒 Files selected for processing (2)
  • build-cv-latex.mjs
  • modes/latex.md

Comment thread build-cv-latex.mjs
- 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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 win

Clarify that email.url is sanitized, not "raw".

The term "Raw email" is misleading. According to context snippet 4 (build-cv-latex.mjs:137-175), email.url is processed by sanitizeUrl() 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.url and github.url entries 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

📥 Commits

Reviewing files that changed from the base of the PR and between 8e33907 and e802192.

📒 Files selected for processing (2)
  • build-cv-latex.mjs
  • modes/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.
@lligirlburg-wq

lligirlburg-wq commented Jun 10, 2026 via email

Copy link
Copy Markdown

abuzarai and others added 3 commits June 10, 2026 15:32
CodeRabbit nitpick: email.url, linkedin.url, github.url docs now state they are sanitized via sanitizeUrl() rather than raw/untouched.
@santifer santifer merged commit b4af01f into santifer:main Jun 11, 2026
7 checks passed
@santifer

Copy link
Copy Markdown
Owner

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. 🚀

@abuzarai abuzarai deleted the feat/build-cv-latex branch June 11, 2026 17:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build-cv-latex.mjs — structured JSON to LaTeX renderer

3 participants