@dytsou/resume-converter 2.1.1 → 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/latex/resume.tex CHANGED
@@ -187,8 +187,8 @@
187
187
 
188
188
  \section{Education}
189
189
  \resumeHeadingListStart{}
190
- \resumeQuadHeading{National Yang Ming Chiao Tung University}{Hsinchu, Taiwan}
191
- {Bachelor of Science in Computer Science}{Sept. 2022 -- Jun. 2026}
190
+ \resumeQuadHeading{National Yang Ming Chiao Tung University}{Hsinchu, Taiwan}%
191
+ {Bachelor of Science in Computer Science}{Sept. 2022 -- Present}
192
192
  \resumeHeadingListEnd{}
193
193
  %---------------------------------------------
194
194
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dytsou/resume-converter",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "type": "module",
5
5
  "dependencies": {
6
6
  "@unified-latex/unified-latex-to-hast": "^1.8.3",
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "devDependencies": {
16
16
  "@eslint/js": "^9.39.2",
17
- "@types/react": "^19.2.7",
17
+ "@types/react": "^19.2.8",
18
18
  "@types/react-dom": "^19.2.3",
19
19
  "@vitejs/plugin-react": "^5.1.2",
20
20
  "eslint": "^9.39.2",
@@ -23,9 +23,9 @@
23
23
  "eslint-plugin-react-refresh": "^0.4.26",
24
24
  "globals": "^17.0.0",
25
25
  "husky": "^9.1.7",
26
- "prettier": "^3.7.4",
26
+ "prettier": "^3.8.0",
27
27
  "typescript": "^5.5.3",
28
- "typescript-eslint": "^8.52.0",
28
+ "typescript-eslint": "^8.53.0",
29
29
  "vite": "^7.3.1"
30
30
  },
31
31
  "license": "MIT",
@@ -223,40 +223,19 @@ export function processQuadHeadings(html, quadHeadingMatches) {
223
223
  let idx = 0;
224
224
 
225
225
  return html.replace(
226
- /<span class="macro macro-resumeQuadHeading"><\/span>([^<]*?)\s*(Bachelor of[^<]*?)\s*([A-Z][a-z]{2,9}\.\s\d{4}\s[–-]\s[A-Z][a-z]{2,9}\.\s\d{4})/g,
227
- (m, pre, degreeLine, dates) => {
226
+ /<span class="macro macro-resumeQuadHeading"><\/span>([\s\S]*?)(?=(<ul|<span|<\/div|<\/p|$))/g,
227
+ (m, content) => {
228
228
  const parsed = quadHeadingMatches[idx++];
229
229
 
230
- if (parsed) {
231
- const uni = parsed[1].trim();
232
- const loc = parsed[2].trim();
233
- const degree = parsed[3].trim();
234
- const dateRange = (parsed[4] || dates)
235
- .replace(/\s*--\s*/g, ' – ')
236
- .replace(/\s+/g, ' ')
237
- .trim();
238
-
239
- return `
240
- <div class="quad">
241
- <div class="row"><div class="left"><strong>${uni}</strong></div><div class="right">${loc}</div></div>
242
- <div class="row"><div class="left"><em>${degree}</em></div><div class="right"><em>${dateRange}</em></div></div>
243
- </div>`;
230
+ if (!parsed || parsed.length < 5) {
231
+ // If we don't have parsed arguments, return original
232
+ return m;
244
233
  }
245
234
 
246
- // Fallback parsing
247
- const preTrim = (pre || '').replace(/\s+/g, ' ').trim();
248
- let uni = preTrim;
249
- let loc = '';
250
-
251
- const cityCountryMatch = preTrim.match(
252
- /^(.*?),\s*([A-Za-z''\- ]+,\s*[A-Za-z''\- ]+)$/
253
- );
254
- if (cityCountryMatch) {
255
- uni = cityCountryMatch[1].trim();
256
- loc = cityCountryMatch[2].trim();
257
- }
258
-
259
- const cleanDates = dates
235
+ const uni = parsed[1].trim();
236
+ const loc = parsed[2].trim();
237
+ const degree = parsed[3].trim();
238
+ const dateRange = parsed[4]
260
239
  .replace(/\s*--\s*/g, ' – ')
261
240
  .replace(/\s+/g, ' ')
262
241
  .trim();
@@ -264,7 +243,7 @@ export function processQuadHeadings(html, quadHeadingMatches) {
264
243
  return `
265
244
  <div class="quad">
266
245
  <div class="row"><div class="left"><strong>${uni}</strong></div><div class="right">${loc}</div></div>
267
- <div class="row"><div class="left"><em>${degreeLine}</em></div><div class="right"><em>${cleanDates}</em></div></div>
246
+ <div class="row"><div class="left"><em>${degree}</em></div><div class="right"><em>${dateRange}</em></div></div>
268
247
  </div>`;
269
248
  }
270
249
  );
@@ -33,12 +33,30 @@ export function parseLatexMacro(content, macroName, argCount) {
33
33
  args.push(currentArg.trim());
34
34
  parsedArgs++;
35
35
  currentArg = '';
36
- // Look for next argument
37
- while (pos < content.length && content[pos] !== '{') {
36
+ // Look for next argument, skipping whitespace, newlines, and comments
37
+ while (pos < content.length) {
38
38
  pos++;
39
- }
40
- if (pos < content.length) {
41
- braceCount = 1;
39
+ const nextChar = content[pos];
40
+ // Skip whitespace and newlines
41
+ if (nextChar === ' ' || nextChar === '\t' || nextChar === '\n' || nextChar === '\r') {
42
+ continue;
43
+ }
44
+ // Skip LaTeX comments (lines starting with %)
45
+ if (nextChar === '%') {
46
+ while (pos < content.length && content[pos] !== '\n' && content[pos] !== '\r') {
47
+ pos++;
48
+ }
49
+ continue;
50
+ }
51
+ // Found the opening brace for next argument
52
+ if (nextChar === '{') {
53
+ braceCount = 1;
54
+ break;
55
+ }
56
+ // If we hit something else before finding {, we might be done
57
+ if (nextChar && nextChar.match(/[a-zA-Z\\]/)) {
58
+ break;
59
+ }
42
60
  }
43
61
  } else {
44
62
  currentArg += char;