resume-parser-ats 1.1.0
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/LICENSE +21 -0
- package/README.md +294 -0
- package/bin/cli.js +368 -0
- package/dist/mcp-server/server.d.ts +18 -0
- package/dist/mcp-server/server.d.ts.map +1 -0
- package/dist/mcp-server/server.js +276 -0
- package/dist/mcp-server/server.js.map +1 -0
- package/dist/src/index.d.ts +96 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +39 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/prompts/insights-prompt.d.ts +24 -0
- package/dist/src/prompts/insights-prompt.d.ts.map +1 -0
- package/dist/src/prompts/insights-prompt.js +129 -0
- package/dist/src/prompts/insights-prompt.js.map +1 -0
- package/dist/src/prompts/parser-prompt.d.ts +11 -0
- package/dist/src/prompts/parser-prompt.d.ts.map +1 -0
- package/dist/src/prompts/parser-prompt.js +150 -0
- package/dist/src/prompts/parser-prompt.js.map +1 -0
- package/dist/src/tools/analyze-resume.d.ts +52 -0
- package/dist/src/tools/analyze-resume.d.ts.map +1 -0
- package/dist/src/tools/analyze-resume.js +286 -0
- package/dist/src/tools/analyze-resume.js.map +1 -0
- package/dist/src/tools/parse-resume.d.ts +57 -0
- package/dist/src/tools/parse-resume.d.ts.map +1 -0
- package/dist/src/tools/parse-resume.js +608 -0
- package/dist/src/tools/parse-resume.js.map +1 -0
- package/dist/src/tools/suggest-improvements.d.ts +51 -0
- package/dist/src/tools/suggest-improvements.d.ts.map +1 -0
- package/dist/src/tools/suggest-improvements.js +472 -0
- package/dist/src/tools/suggest-improvements.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,608 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Step 1–4: Resume Parsing Engine
|
|
4
|
+
*
|
|
5
|
+
* Implements the full OpenResume algorithm:
|
|
6
|
+
* Step 1: Read text items from PDF
|
|
7
|
+
* Step 2: Group text items into lines
|
|
8
|
+
* Step 3: Group lines into sections
|
|
9
|
+
* Step 4: Extract resume attributes from sections via feature scoring
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
45
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
|
+
};
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
exports.extractTextItemsFromPDF = extractTextItemsFromPDF;
|
|
49
|
+
exports.extractTextItemsFromRawText = extractTextItemsFromRawText;
|
|
50
|
+
exports.groupTextItemsIntoLines = groupTextItemsIntoLines;
|
|
51
|
+
exports.groupLinesIntoSections = groupLinesIntoSections;
|
|
52
|
+
exports.parseResume = parseResume;
|
|
53
|
+
const fs_1 = __importDefault(require("fs"));
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// Step 1: Read text items from PDF
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
/**
|
|
58
|
+
* Extract text items from raw resume text (simplified version).
|
|
59
|
+
*
|
|
60
|
+
* In a full implementation this would use pdfjs-dist to extract
|
|
61
|
+
* text items with position, bold, and newline metadata from a PDF.
|
|
62
|
+
* Here we simulate the extraction from raw text input.
|
|
63
|
+
*/
|
|
64
|
+
async function extractTextItemsFromPDF(filePath) {
|
|
65
|
+
const warnings = [];
|
|
66
|
+
try {
|
|
67
|
+
// In production: use pdfjs-dist to read the PDF and extract text items
|
|
68
|
+
// with (x1, x2, y, bold, newLine) metadata.
|
|
69
|
+
//
|
|
70
|
+
// const pdfjsLib = require("pdfjs-dist/legacy/build/pdf.js");
|
|
71
|
+
// const doc = await pdfjsLib.getDocument(filePath).promise;
|
|
72
|
+
// ... iterate pages, get textContent, map to TextItem[]
|
|
73
|
+
//
|
|
74
|
+
// For now we fall back to a simplified extraction:
|
|
75
|
+
const fs = await Promise.resolve().then(() => __importStar(require("fs")));
|
|
76
|
+
const pdfBuffer = fs.readFileSync(filePath);
|
|
77
|
+
// Attempt to extract text from the PDF buffer using a simple approach.
|
|
78
|
+
// The full implementation should use pdfjs-dist for accurate positioning.
|
|
79
|
+
const text = pdfBuffer.toString("latin1");
|
|
80
|
+
// Extract readable text portions (simplified heuristic)
|
|
81
|
+
const textItems = [];
|
|
82
|
+
const lines = text
|
|
83
|
+
.split(/[\r\n]+/)
|
|
84
|
+
.filter((l) => l.trim().length > 0);
|
|
85
|
+
let y = 800;
|
|
86
|
+
for (const line of lines) {
|
|
87
|
+
const cleanLine = line.replace(/[^\x20-\x7E]/g, "").trim();
|
|
88
|
+
if (cleanLine.length === 0)
|
|
89
|
+
continue;
|
|
90
|
+
// Determine if line is likely a section header
|
|
91
|
+
const isBold = /^[A-Z\s/&]+$/.test(cleanLine) && cleanLine.length < 40;
|
|
92
|
+
const isSectionTitle = isBold && cleanLine.length > 2;
|
|
93
|
+
textItems.push({
|
|
94
|
+
text: cleanLine,
|
|
95
|
+
x1: 36,
|
|
96
|
+
x2: 36 + cleanLine.length * 5,
|
|
97
|
+
y: y,
|
|
98
|
+
bold: isSectionTitle,
|
|
99
|
+
newLine: true,
|
|
100
|
+
});
|
|
101
|
+
y -= 14;
|
|
102
|
+
}
|
|
103
|
+
if (textItems.length === 0) {
|
|
104
|
+
warnings.push("Could not extract any text items from the PDF. The file may be image-based or corrupted.");
|
|
105
|
+
}
|
|
106
|
+
return { items: textItems, warnings };
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
110
|
+
warnings.push(`Error reading PDF: ${message}`);
|
|
111
|
+
return { items: [], warnings };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Fallback: parse text items from raw text input
|
|
116
|
+
*
|
|
117
|
+
* Heuristics for determining bold/section-title:
|
|
118
|
+
* 1. Known section headers (EDUCATION, EXPERIENCE, etc.) → bold + section title
|
|
119
|
+
* 2. Short ALL-CAPS lines (≤ 40 chars) → bold (but NOT a section title if
|
|
120
|
+
* they look like a name — i.e., only letters, spaces, periods, and → )
|
|
121
|
+
* 3. First non-empty line is treated as the candidate name → bold, NOT section title
|
|
122
|
+
*/
|
|
123
|
+
function extractTextItemsFromRawText(rawText) {
|
|
124
|
+
const lines = rawText.split(/\n/);
|
|
125
|
+
const items = [];
|
|
126
|
+
let y = 800;
|
|
127
|
+
// Detect which line is likely the name (first non-empty line that is NOT a section title)
|
|
128
|
+
let firstNameLine = null;
|
|
129
|
+
for (const line of lines) {
|
|
130
|
+
const trimmed = line.trim();
|
|
131
|
+
if (trimmed.length === 0)
|
|
132
|
+
continue;
|
|
133
|
+
if (!SECTION_TITLE_KEYWORDS.includes(trimmed.toUpperCase())) {
|
|
134
|
+
firstNameLine = trimmed;
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
for (const line of lines) {
|
|
139
|
+
const trimmed = line.trim();
|
|
140
|
+
if (trimmed.length === 0)
|
|
141
|
+
continue;
|
|
142
|
+
const upperTrimmed = trimmed.toUpperCase();
|
|
143
|
+
const isKnownSection = SECTION_TITLE_KEYWORDS.includes(upperTrimmed);
|
|
144
|
+
const isAllCapsShort = /^[A-Z\s/&]+$/.test(trimmed) && trimmed.length <= 40 && trimmed.length > 2;
|
|
145
|
+
const looksLikeName = /^[A-Z][a-zA-Z\s\.]+$/.test(trimmed) && trimmed.length > 2 && trimmed.length < 50;
|
|
146
|
+
const isFirstName = firstNameLine !== null && trimmed === firstNameLine;
|
|
147
|
+
// Determine bold and section-title flags
|
|
148
|
+
let bold = false;
|
|
149
|
+
if (isKnownSection) {
|
|
150
|
+
// Known section headers are always section titles
|
|
151
|
+
bold = true;
|
|
152
|
+
}
|
|
153
|
+
else if (isAllCapsShort && !looksLikeName && !isFirstName) {
|
|
154
|
+
// Short ALL-CAPS that don't look like names → bold, section title
|
|
155
|
+
bold = true;
|
|
156
|
+
}
|
|
157
|
+
else if (isFirstName && looksLikeName) {
|
|
158
|
+
// First line that looks like a name → bold, NOT a section title
|
|
159
|
+
bold = true;
|
|
160
|
+
}
|
|
161
|
+
else if (isAllCapsShort) {
|
|
162
|
+
// Could be a name in all caps — bold but not a section title
|
|
163
|
+
bold = true;
|
|
164
|
+
}
|
|
165
|
+
items.push({
|
|
166
|
+
text: trimmed,
|
|
167
|
+
x1: 36,
|
|
168
|
+
x2: 36 + trimmed.length * 5,
|
|
169
|
+
y,
|
|
170
|
+
bold,
|
|
171
|
+
newLine: true,
|
|
172
|
+
});
|
|
173
|
+
y -= 14;
|
|
174
|
+
}
|
|
175
|
+
return items;
|
|
176
|
+
}
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
// Step 2: Group text items into lines
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
/**
|
|
181
|
+
* Merge adjacent text items on the same Y-coordinate if their horizontal
|
|
182
|
+
* distance is smaller than the average character width.
|
|
183
|
+
*/
|
|
184
|
+
function groupTextItemsIntoLines(items) {
|
|
185
|
+
if (items.length === 0)
|
|
186
|
+
return [];
|
|
187
|
+
// Calculate average character width
|
|
188
|
+
const charWidthItems = items.filter((i) => !i.bold && i.text.trim().length > 0);
|
|
189
|
+
let totalWidth = 0;
|
|
190
|
+
let totalChars = 0;
|
|
191
|
+
for (const item of charWidthItems) {
|
|
192
|
+
totalWidth += item.x2 - item.x1;
|
|
193
|
+
totalChars += item.text.length;
|
|
194
|
+
}
|
|
195
|
+
const avgCharWidth = totalChars > 0 ? totalWidth / totalChars : 5;
|
|
196
|
+
// Group items by Y-coordinate (same line)
|
|
197
|
+
const yGroups = new Map();
|
|
198
|
+
const yTolerance = 3; // Pixels tolerance for same line
|
|
199
|
+
const sortedItems = [...items].sort((a, b) => b.y - a.y); // Top to bottom
|
|
200
|
+
const yKeys = [];
|
|
201
|
+
for (const item of sortedItems) {
|
|
202
|
+
let matched = false;
|
|
203
|
+
for (const key of yKeys) {
|
|
204
|
+
if (Math.abs(item.y - key) <= yTolerance) {
|
|
205
|
+
yGroups.get(key).push(item);
|
|
206
|
+
matched = true;
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
if (!matched) {
|
|
211
|
+
yKeys.push(item.y);
|
|
212
|
+
yGroups.set(item.y, [item]);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
// Sort groups by Y (top to bottom)
|
|
216
|
+
yKeys.sort((a, b) => b - a);
|
|
217
|
+
const lines = [];
|
|
218
|
+
for (const yKey of yKeys) {
|
|
219
|
+
const groupItems = yGroups.get(yKey);
|
|
220
|
+
// Sort items left to right
|
|
221
|
+
groupItems.sort((a, b) => a.x1 - b.x1);
|
|
222
|
+
// Merge adjacent items
|
|
223
|
+
const merged = [];
|
|
224
|
+
for (const item of groupItems) {
|
|
225
|
+
if (merged.length === 0) {
|
|
226
|
+
merged.push({ ...item });
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
const prev = merged[merged.length - 1];
|
|
230
|
+
const distance = item.x1 - prev.x2;
|
|
231
|
+
if (distance < avgCharWidth && !item.newLine) {
|
|
232
|
+
// Merge with previous item
|
|
233
|
+
prev.text += item.text;
|
|
234
|
+
prev.x2 = item.x2;
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
// Add separator and new item
|
|
238
|
+
merged.push({ ...item });
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
const lineText = merged.map((i) => i.text).join(" ").trim();
|
|
242
|
+
lines.push({
|
|
243
|
+
lineNumber: lines.length + 1,
|
|
244
|
+
text: lineText,
|
|
245
|
+
items: merged,
|
|
246
|
+
y: yKey,
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
return lines;
|
|
250
|
+
}
|
|
251
|
+
// ---------------------------------------------------------------------------
|
|
252
|
+
// Step 3: Group lines into sections
|
|
253
|
+
// ---------------------------------------------------------------------------
|
|
254
|
+
/** Known section title keywords for fallback heuristic */
|
|
255
|
+
const SECTION_TITLE_KEYWORDS = [
|
|
256
|
+
"PROFILE", "SUMMARY", "OBJECTIVE", "ABOUT", "ABOUT ME",
|
|
257
|
+
"EDUCATION", "ACADEMIC", "DEGREES", "ACADEMICS",
|
|
258
|
+
"EXPERIENCE", "WORK EXPERIENCE", "EMPLOYMENT", "PROFESSIONAL EXPERIENCE",
|
|
259
|
+
"WORK HISTORY", "CAREER HISTORY",
|
|
260
|
+
"SKILLS", "TECHNICAL SKILLS", "COMPETENCIES", "AREAS OF EXPERTISE",
|
|
261
|
+
"PROJECTS", "PORTFOLIO", "PERSONAL PROJECTS",
|
|
262
|
+
"CERTIFICATIONS", "LICENSES", "HONORS", "AWARDS", "HONORS & AWARDS",
|
|
263
|
+
"VOLUNTEER", "VOLUNTEER EXPERIENCE", "COMMUNITY", "COMMUNITY SERVICE",
|
|
264
|
+
"LEADERSHIP", "LEADERSHIP EXPERIENCE",
|
|
265
|
+
"PUBLICATIONS", "RESEARCH", "RESEARCH EXPERIENCE",
|
|
266
|
+
"INTERESTS", "ACTIVITIES", "HOBBIES", "EXTRACURRICULAR",
|
|
267
|
+
"LANGUAGES", "REFERENCES",
|
|
268
|
+
];
|
|
269
|
+
/**
|
|
270
|
+
* Determine if a line is a section title.
|
|
271
|
+
* Primary heuristic: only text item, bold, all UPPERCASE.
|
|
272
|
+
* Fallback heuristic: keyword match.
|
|
273
|
+
*/
|
|
274
|
+
function isSectionTitle(line) {
|
|
275
|
+
const text = line.text.trim();
|
|
276
|
+
const upperText = text.toUpperCase();
|
|
277
|
+
// Fallback heuristic first: exact keyword match (handles raw-text case cleanly)
|
|
278
|
+
const cleanUpper = upperText.replace(/[^A-Z\s/&]/g, "").trim();
|
|
279
|
+
if (SECTION_TITLE_KEYWORDS.includes(cleanUpper)) {
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
// Primary heuristic: only text item, bold, all UPPERCASE
|
|
283
|
+
// But exclude names — "Leo Leopard" etc. should NOT be detected as section titles
|
|
284
|
+
if (line.items.length === 1 && line.items[0].bold && /^[A-Z\s/&]+$/.test(text)) {
|
|
285
|
+
// If it looks like a name (mixed case or typical name pattern), it's not a section title
|
|
286
|
+
if (/^[A-Z][a-zA-Z\s\.]+$/.test(text) && text.length < 50) {
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Group lines into sections based on section titles.
|
|
295
|
+
*/
|
|
296
|
+
function groupLinesIntoSections(lines) {
|
|
297
|
+
if (lines.length === 0)
|
|
298
|
+
return [];
|
|
299
|
+
const sections = [];
|
|
300
|
+
let currentSection = { title: "PROFILE", lines: [] };
|
|
301
|
+
for (const line of lines) {
|
|
302
|
+
if (isSectionTitle(line)) {
|
|
303
|
+
// Save the current section if it has lines
|
|
304
|
+
if (currentSection.lines.length > 0) {
|
|
305
|
+
sections.push(currentSection);
|
|
306
|
+
}
|
|
307
|
+
currentSection = { title: line.text.trim().toUpperCase(), lines: [] };
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
currentSection.lines.push(line);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
// Push the last section
|
|
314
|
+
if (currentSection.lines.length > 0) {
|
|
315
|
+
sections.push(currentSection);
|
|
316
|
+
}
|
|
317
|
+
return sections;
|
|
318
|
+
}
|
|
319
|
+
// --- Profile feature sets ---
|
|
320
|
+
const NAME_FEATURE_SETS = [
|
|
321
|
+
{ match: (text) => /^[a-zA-Z\s\.]+$/.test(text), score: 3 },
|
|
322
|
+
{ match: (_text, item) => item.bold, score: 2 },
|
|
323
|
+
{ match: (text) => text === text.toUpperCase() && /[A-Z]/.test(text), score: 2 },
|
|
324
|
+
{ match: (text) => text.includes("@"), score: -4 },
|
|
325
|
+
{ match: (text) => /\d/.test(text), score: -4 },
|
|
326
|
+
{ match: (text) => text.includes(","), score: -4 },
|
|
327
|
+
{ match: (text) => text.includes("/"), score: -4 },
|
|
328
|
+
];
|
|
329
|
+
const EMAIL_FEATURE_SETS = [
|
|
330
|
+
{ match: (text) => /\S+@\S+\.\S+/.test(text), score: 4 },
|
|
331
|
+
{ match: (text) => /^[a-zA-Z\s\.]+$/.test(text) && !text.includes("@"), score: -1 },
|
|
332
|
+
{ match: (text) => /\d/.test(text) && !text.includes("@"), score: -2 },
|
|
333
|
+
{ match: (text) => text.includes("@"), score: 4 },
|
|
334
|
+
];
|
|
335
|
+
const PHONE_FEATURE_SETS = [
|
|
336
|
+
{ match: (text) => /\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{4}/.test(text), score: 4 },
|
|
337
|
+
{ match: (text) => /^[a-zA-Z\s\.]+$/.test(text), score: -4 },
|
|
338
|
+
{ match: (text) => text.includes("@"), score: -4 },
|
|
339
|
+
{ match: (text) => /\d/.test(text) && !/\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{4}/.test(text), score: -1 },
|
|
340
|
+
];
|
|
341
|
+
const LOCATION_FEATURE_SETS = [
|
|
342
|
+
{ match: (text) => /[A-Z][a-zA-Z\s]+,\s*[A-Z]{2}/.test(text), score: 4 },
|
|
343
|
+
{ match: (text) => text.includes("@"), score: -4 },
|
|
344
|
+
{ match: (text) => !text.includes(","), score: -2 },
|
|
345
|
+
];
|
|
346
|
+
const URL_FEATURE_SETS = [
|
|
347
|
+
{ match: (text) => /\S+\.[a-z]+\/\S+/.test(text), score: 4 },
|
|
348
|
+
{ match: (text) => /https?:\/\//i.test(text), score: 4 },
|
|
349
|
+
{ match: (text) => /linkedin\.com/i.test(text), score: 4 },
|
|
350
|
+
{ match: (text) => /github\.com/i.test(text), score: 4 },
|
|
351
|
+
{ match: (text) => /^[a-zA-Z\s\.]+$/.test(text), score: -4 },
|
|
352
|
+
];
|
|
353
|
+
// --- Education / Experience feature sets ---
|
|
354
|
+
const SCHOOL_KEYWORDS = /college|university|school|institute|academy|faculty/i;
|
|
355
|
+
const DEGREE_KEYWORDS = /associate|bachelor|master|doctorate|b\.s\.|b\.a\.|m\.s\.|m\.a\.|ph\.d|bsc|msc|ba|ma|mba|bs|ms/i;
|
|
356
|
+
const GPA_REGEX = /[0-4]\.\d{1,2}/;
|
|
357
|
+
const DATE_REGEX = /(?:19|20)\d{2}/;
|
|
358
|
+
const JOB_TITLE_KEYWORDS = /analyst|engineer|intern|manager|developer|coordinator|director|associate|consultant|specialist|lead|architect|designer|administrator|assistant|officer|executive|president|vice|chief|head|supervisor|technician|clerk|trainee|volunteer/i;
|
|
359
|
+
// --- Feature scoring function ---
|
|
360
|
+
function computeFeatureScore(text, item, featureSets) {
|
|
361
|
+
let totalScore = 0;
|
|
362
|
+
for (const fs of featureSets) {
|
|
363
|
+
if (fs.match(text, item)) {
|
|
364
|
+
totalScore += fs.score;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return totalScore;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* From a list of text items, find the one with the highest feature score
|
|
371
|
+
* for a given set of feature sets.
|
|
372
|
+
*/
|
|
373
|
+
function extractBestMatch(items, featureSets) {
|
|
374
|
+
let bestScore = -Infinity;
|
|
375
|
+
let bestText = null;
|
|
376
|
+
for (const item of items) {
|
|
377
|
+
const text = item.text.trim();
|
|
378
|
+
if (text.length === 0)
|
|
379
|
+
continue;
|
|
380
|
+
const score = computeFeatureScore(text, item, featureSets);
|
|
381
|
+
if (score > bestScore) {
|
|
382
|
+
bestScore = score;
|
|
383
|
+
bestText = text;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
return bestScore > 0 ? bestText : null;
|
|
387
|
+
}
|
|
388
|
+
// --- Subsection detection ---
|
|
389
|
+
/**
|
|
390
|
+
* Detect subsection boundaries within a section.
|
|
391
|
+
* Primary: vertical line gap > typical line gap × 1.4
|
|
392
|
+
* Fallback: text item is bolded
|
|
393
|
+
*/
|
|
394
|
+
function detectSubsections(section) {
|
|
395
|
+
const { lines } = section;
|
|
396
|
+
if (lines.length === 0)
|
|
397
|
+
return [];
|
|
398
|
+
// Calculate typical line gap
|
|
399
|
+
const gaps = [];
|
|
400
|
+
for (let i = 1; i < lines.length; i++) {
|
|
401
|
+
gaps.push(Math.abs(lines[i].y - lines[i - 1].y));
|
|
402
|
+
}
|
|
403
|
+
const typicalGap = gaps.length > 0
|
|
404
|
+
? gaps.sort((a, b) => a - b)[Math.floor(gaps.length / 2)]
|
|
405
|
+
: 14;
|
|
406
|
+
const subsectionGapThreshold = typicalGap * 1.4;
|
|
407
|
+
// Split lines into subsections
|
|
408
|
+
const subsections = [];
|
|
409
|
+
let currentSubsection = [lines[0]];
|
|
410
|
+
for (let i = 1; i < lines.length; i++) {
|
|
411
|
+
const gap = Math.abs(lines[i].y - lines[i - 1].y);
|
|
412
|
+
const isBoldStart = lines[i].items.some((item) => item.bold);
|
|
413
|
+
if (gap > subsectionGapThreshold || (isBoldStart && currentSubsection.length > 1)) {
|
|
414
|
+
subsections.push(currentSubsection);
|
|
415
|
+
currentSubsection = [lines[i]];
|
|
416
|
+
}
|
|
417
|
+
else {
|
|
418
|
+
currentSubsection.push(lines[i]);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
subsections.push(currentSubsection);
|
|
422
|
+
return subsections;
|
|
423
|
+
}
|
|
424
|
+
// --- Section-specific extractors ---
|
|
425
|
+
function extractProfile(sections) {
|
|
426
|
+
const profileSection = sections.find((s) => s.title === "PROFILE");
|
|
427
|
+
if (!profileSection) {
|
|
428
|
+
// Try SUMMARY or OBJECTIVE
|
|
429
|
+
const fallback = sections.find((s) => ["SUMMARY", "OBJECTIVE", "ABOUT"].includes(s.title));
|
|
430
|
+
if (fallback) {
|
|
431
|
+
return extractProfileFromSection(fallback);
|
|
432
|
+
}
|
|
433
|
+
return { name: null, email: null, phone: null, location: null, url: null, summary: null };
|
|
434
|
+
}
|
|
435
|
+
return extractProfileFromSection(profileSection);
|
|
436
|
+
}
|
|
437
|
+
function extractProfileFromSection(section) {
|
|
438
|
+
const allItems = section.lines.flatMap((l) => l.items);
|
|
439
|
+
const allTexts = allItems.map((i) => i.text.trim()).filter((t) => t.length > 0);
|
|
440
|
+
const name = extractBestMatch(allItems, NAME_FEATURE_SETS);
|
|
441
|
+
const email = extractBestMatch(allItems, EMAIL_FEATURE_SETS);
|
|
442
|
+
const phone = extractBestMatch(allItems, PHONE_FEATURE_SETS);
|
|
443
|
+
const location = extractBestMatch(allItems, LOCATION_FEATURE_SETS);
|
|
444
|
+
const url = extractBestMatch(allItems, URL_FEATURE_SETS);
|
|
445
|
+
// Summary: everything that isn't name/email/phone/location/url
|
|
446
|
+
const summaryTexts = allTexts.filter((t) => t !== name &&
|
|
447
|
+
t !== email &&
|
|
448
|
+
t !== phone &&
|
|
449
|
+
t !== location &&
|
|
450
|
+
t !== url &&
|
|
451
|
+
!SECTION_TITLE_KEYWORDS.includes(t.toUpperCase().replace(/[^A-Z\s/&]/g, "").trim()));
|
|
452
|
+
const summary = summaryTexts.length > 0 ? summaryTexts.join(" ") : null;
|
|
453
|
+
return { name, email, phone, location, url, summary };
|
|
454
|
+
}
|
|
455
|
+
function extractEducation(sections) {
|
|
456
|
+
const eduSection = sections.find((s) => ["EDUCATION", "ACADEMIC", "DEGREES", "ACADEMICS"].includes(s.title));
|
|
457
|
+
if (!eduSection)
|
|
458
|
+
return [];
|
|
459
|
+
const subsections = detectSubsections(eduSection);
|
|
460
|
+
const educations = [];
|
|
461
|
+
for (const sub of subsections) {
|
|
462
|
+
const allItems = sub.flatMap((l) => l.items);
|
|
463
|
+
const allTexts = allItems.map((i) => i.text.trim()).filter((t) => t.length > 0);
|
|
464
|
+
// Find school
|
|
465
|
+
const school = allTexts.find((t) => SCHOOL_KEYWORDS.test(t)) || null;
|
|
466
|
+
// Find degree
|
|
467
|
+
const degree = allTexts.find((t) => DEGREE_KEYWORDS.test(t)) || null;
|
|
468
|
+
// Find GPA
|
|
469
|
+
const gpa = allTexts.find((t) => GPA_REGEX.test(t)) || null;
|
|
470
|
+
// Find date
|
|
471
|
+
const date = allTexts.find((t) => DATE_REGEX.test(t)) || null;
|
|
472
|
+
// Find descriptions (bullet points)
|
|
473
|
+
const descriptions = allTexts.filter((t) => t !== school &&
|
|
474
|
+
t !== degree &&
|
|
475
|
+
t !== gpa &&
|
|
476
|
+
t !== date &&
|
|
477
|
+
!SECTION_TITLE_KEYWORDS.includes(t.toUpperCase()));
|
|
478
|
+
educations.push({ school, degree, gpa, date, descriptions });
|
|
479
|
+
}
|
|
480
|
+
return educations;
|
|
481
|
+
}
|
|
482
|
+
function extractExperience(sections) {
|
|
483
|
+
const expSection = sections.find((s) => [
|
|
484
|
+
"EXPERIENCE", "WORK EXPERIENCE", "EMPLOYMENT",
|
|
485
|
+
"PROFESSIONAL EXPERIENCE", "WORK HISTORY", "CAREER HISTORY",
|
|
486
|
+
"VOLUNTEER", "VOLUNTEER EXPERIENCE", "COMMUNITY",
|
|
487
|
+
"COMMUNITY SERVICE",
|
|
488
|
+
].includes(s.title));
|
|
489
|
+
if (!expSection)
|
|
490
|
+
return [];
|
|
491
|
+
const subsections = detectSubsections(expSection);
|
|
492
|
+
const experiences = [];
|
|
493
|
+
for (const sub of subsections) {
|
|
494
|
+
const allItems = sub.flatMap((l) => l.items);
|
|
495
|
+
const allTexts = allItems.map((i) => i.text.trim()).filter((t) => t.length > 0);
|
|
496
|
+
// Find company (bolded or no job title match)
|
|
497
|
+
const company = allTexts.find((t) => {
|
|
498
|
+
const item = allItems.find((i) => i.text.trim() === t);
|
|
499
|
+
return item?.bold && !JOB_TITLE_KEYWORDS.test(t);
|
|
500
|
+
}) || null;
|
|
501
|
+
// Find job title
|
|
502
|
+
const jobTitle = allTexts.find((t) => JOB_TITLE_KEYWORDS.test(t)) || null;
|
|
503
|
+
// Find date
|
|
504
|
+
const date = allTexts.find((t) => DATE_REGEX.test(t)) || null;
|
|
505
|
+
// Descriptions (bullet points)
|
|
506
|
+
const descriptions = allTexts.filter((t) => t !== company &&
|
|
507
|
+
t !== jobTitle &&
|
|
508
|
+
t !== date &&
|
|
509
|
+
!SECTION_TITLE_KEYWORDS.includes(t.toUpperCase()));
|
|
510
|
+
experiences.push({ company, jobTitle, date, descriptions });
|
|
511
|
+
}
|
|
512
|
+
return experiences;
|
|
513
|
+
}
|
|
514
|
+
function extractSkills(sections) {
|
|
515
|
+
const skillSection = sections.find((s) => ["SKILLS", "TECHNICAL SKILLS", "COMPETENCIES", "AREAS OF EXPERTISE"].includes(s.title));
|
|
516
|
+
if (!skillSection)
|
|
517
|
+
return [];
|
|
518
|
+
const allTexts = skillSection.lines.flatMap((l) => l.items.map((i) => i.text.trim()).filter((t) => t.length > 0));
|
|
519
|
+
const descriptions = allTexts.filter((t) => !SECTION_TITLE_KEYWORDS.includes(t.toUpperCase()));
|
|
520
|
+
return [{ descriptions }];
|
|
521
|
+
}
|
|
522
|
+
function extractProjects(sections) {
|
|
523
|
+
const projSection = sections.find((s) => ["PROJECTS", "PORTFOLIO", "PERSONAL PROJECTS"].includes(s.title));
|
|
524
|
+
if (!projSection)
|
|
525
|
+
return [];
|
|
526
|
+
const subsections = detectSubsections(projSection);
|
|
527
|
+
const projects = [];
|
|
528
|
+
for (const sub of subsections) {
|
|
529
|
+
const allTexts = sub.flatMap((l) => l.items.map((i) => i.text.trim()).filter((t) => t.length > 0));
|
|
530
|
+
const name = allTexts[0] || null;
|
|
531
|
+
const date = allTexts.find((t) => DATE_REGEX.test(t)) || null;
|
|
532
|
+
const descriptions = allTexts.filter((t) => t !== name && t !== date && !SECTION_TITLE_KEYWORDS.includes(t.toUpperCase()));
|
|
533
|
+
projects.push({ name, date, descriptions });
|
|
534
|
+
}
|
|
535
|
+
return projects;
|
|
536
|
+
}
|
|
537
|
+
// ---------------------------------------------------------------------------
|
|
538
|
+
// Main parse function
|
|
539
|
+
// ---------------------------------------------------------------------------
|
|
540
|
+
function parseResume(input) {
|
|
541
|
+
const warnings = [];
|
|
542
|
+
const stepsCompleted = [];
|
|
543
|
+
let textItems;
|
|
544
|
+
// Step 1: Extract text items
|
|
545
|
+
if (input.rawText) {
|
|
546
|
+
textItems = extractTextItemsFromRawText(input.rawText);
|
|
547
|
+
stepsCompleted.push(1);
|
|
548
|
+
}
|
|
549
|
+
else if (input.filePath) {
|
|
550
|
+
// For synchronous version we use the raw text approach;
|
|
551
|
+
// in production this would be async with pdfjs-dist
|
|
552
|
+
try {
|
|
553
|
+
const content = fs_1.default.readFileSync(input.filePath, "utf-8");
|
|
554
|
+
textItems = extractTextItemsFromRawText(content);
|
|
555
|
+
stepsCompleted.push(1);
|
|
556
|
+
}
|
|
557
|
+
catch {
|
|
558
|
+
warnings.push(`Could not read file: ${input.filePath}`);
|
|
559
|
+
textItems = [];
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
else {
|
|
563
|
+
warnings.push("No input provided. Please provide either filePath or rawText.");
|
|
564
|
+
return {
|
|
565
|
+
success: false,
|
|
566
|
+
data: {
|
|
567
|
+
profile: { name: null, email: null, phone: null, location: null, url: null, summary: null },
|
|
568
|
+
education: [],
|
|
569
|
+
experience: [],
|
|
570
|
+
skills: [],
|
|
571
|
+
projects: [],
|
|
572
|
+
sections: [],
|
|
573
|
+
rawTextItems: [],
|
|
574
|
+
lines: [],
|
|
575
|
+
},
|
|
576
|
+
metadata: { parserVersion: "1.0.0", stepsCompleted: [], warnings },
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
// Step 2: Group text items into lines
|
|
580
|
+
const lines = groupTextItemsIntoLines(textItems);
|
|
581
|
+
stepsCompleted.push(2);
|
|
582
|
+
// Step 3: Group lines into sections
|
|
583
|
+
const sections = groupLinesIntoSections(lines);
|
|
584
|
+
stepsCompleted.push(3);
|
|
585
|
+
// Step 4: Extract resume attributes from sections
|
|
586
|
+
const profile = extractProfile(sections);
|
|
587
|
+
const education = extractEducation(sections);
|
|
588
|
+
const experience = extractExperience(sections);
|
|
589
|
+
const skills = extractSkills(sections);
|
|
590
|
+
const projects = extractProjects(sections);
|
|
591
|
+
stepsCompleted.push(4);
|
|
592
|
+
const parsedResume = {
|
|
593
|
+
profile,
|
|
594
|
+
education,
|
|
595
|
+
experience,
|
|
596
|
+
skills,
|
|
597
|
+
projects,
|
|
598
|
+
sections,
|
|
599
|
+
rawTextItems: textItems,
|
|
600
|
+
lines,
|
|
601
|
+
};
|
|
602
|
+
return {
|
|
603
|
+
success: true,
|
|
604
|
+
data: parsedResume,
|
|
605
|
+
metadata: { parserVersion: "1.0.0", stepsCompleted, warnings },
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
//# sourceMappingURL=parse-resume.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-resume.js","sourceRoot":"","sources":["../../../src/tools/parse-resume.ts"],"names":[],"mappings":"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"}
|