@pranavraut033/ats-checker 1.1.1 → 1.2.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/README.md +36 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +15 -0
- package/dist/index.mjs.map +1 -1
- package/dist/pdf/index.d.mts +12 -0
- package/dist/pdf/index.d.ts +12 -0
- package/dist/pdf/index.js +81 -0
- package/dist/pdf/index.js.map +1 -0
- package/dist/pdf/index.mjs +79 -0
- package/dist/pdf/index.mjs.map +1 -0
- package/package.json +18 -3
package/README.md
CHANGED
|
@@ -19,6 +19,7 @@ Zero-dependency TypeScript library that scores a resume against a job descriptio
|
|
|
19
19
|
- **Explainable** — breakdown by category (skills / experience / keywords / education) plus matched and missing skill/keyword lists
|
|
20
20
|
- **Configurable** — adjust weights, add skill aliases, define custom penalty rules
|
|
21
21
|
- **Zero dependencies** — core library has no runtime deps; ships ESM + CJS
|
|
22
|
+
- **PDF input** — optional `/pdf` subpath extracts resume text from a PDF buffer (requires `pdfjs-dist` peer dep)
|
|
22
23
|
- **Built-in profiles** — software engineer, data scientist, product manager out of the box
|
|
23
24
|
|
|
24
25
|
---
|
|
@@ -184,6 +185,41 @@ const result = analyzeResume({
|
|
|
184
185
|
|
|
185
186
|
---
|
|
186
187
|
|
|
188
|
+
## PDF Input
|
|
189
|
+
|
|
190
|
+
Extract text from a PDF resume before passing it to `analyzeResume`. This uses `pdfjs-dist` as an optional peer dependency — the core library stays zero-dep.
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
npm install pdfjs-dist
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
import { extractTextFromPDF } from "@pranavraut033/ats-checker/pdf";
|
|
198
|
+
import { analyzeResume } from "@pranavraut033/ats-checker";
|
|
199
|
+
import { readFileSync } from "fs";
|
|
200
|
+
|
|
201
|
+
const bytes = readFileSync("resume.pdf");
|
|
202
|
+
const resumeText = await extractTextFromPDF(bytes);
|
|
203
|
+
|
|
204
|
+
const result = analyzeResume({ resumeText, jobDescription: "..." });
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
`extractTextFromPDF` accepts a `Uint8Array` or `ArrayBuffer` and returns a plain `string`. Works in Node.js and the browser (text-layer PDFs only).
|
|
208
|
+
|
|
209
|
+
**Multi-column layouts are handled automatically.** The extractor uses glyph x/y coordinates to detect column boundaries and process each column independently, so a two-column resume parses cleanly without interleaved text.
|
|
210
|
+
|
|
211
|
+
For PDFs that can't be recovered — scanned/image resumes or exports with no text layer — `analyzeResume` surfaces an actionable message in `result.warnings`. Always check it after PDF input:
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
const result = analyzeResume({ resumeText, jobDescription: "..." });
|
|
215
|
+
if (result.warnings.length) {
|
|
216
|
+
console.warn("Parsing issues:", result.warnings);
|
|
217
|
+
// e.g. "Almost no text was extracted — the resume may be a scanned/image PDF."
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
187
223
|
## LLM Integration (deprecated)
|
|
188
224
|
|
|
189
225
|
`analyzeResumeAsync` accepts an optional `llm` config that rewrites suggestion text via a caller-supplied LLM client. **This path is deprecated** — scores and breakdowns are never touched by LLM. Prefer calling `analyzeResume` and running your own LLM pass on `result.suggestions` if you want AI-enhanced wording.
|
package/dist/index.js
CHANGED
|
@@ -541,6 +541,16 @@ function parseResume(resumeText, config) {
|
|
|
541
541
|
}
|
|
542
542
|
const requiredSections = ["summary", "experience", "skills", "education"];
|
|
543
543
|
const warnings = [];
|
|
544
|
+
const lineCount = splitLines(resumeText).length;
|
|
545
|
+
if (resumeText.trim().length < 100) {
|
|
546
|
+
warnings.push(
|
|
547
|
+
"Almost no text was extracted \u2014 the resume may be a scanned/image PDF. Upload a text-based PDF or paste the text directly."
|
|
548
|
+
);
|
|
549
|
+
} else if (lineCount <= 2) {
|
|
550
|
+
warnings.push(
|
|
551
|
+
"Resume text has no line breaks \u2014 the PDF layout likely didn't export cleanly (common with multi-column designs). Export as a single-column PDF or paste plain text for accurate parsing."
|
|
552
|
+
);
|
|
553
|
+
}
|
|
544
554
|
for (const section of requiredSections) {
|
|
545
555
|
if (!detected.includes(section)) {
|
|
546
556
|
warnings.push(`${section} section not detected`);
|
|
@@ -920,6 +930,11 @@ var SuggestionEngine = class {
|
|
|
920
930
|
"Strengthen bullet points with impact verbs (led, built, improved, delivered)."
|
|
921
931
|
);
|
|
922
932
|
}
|
|
933
|
+
if (input.resume.detectedSections.length < 2 && input.resume.raw.trim().length > 300) {
|
|
934
|
+
suggestions.push(
|
|
935
|
+
"Your resume may use a multi-column layout. Export as a single-column PDF or paste plain text \u2014 most ATS systems and this parser work best with a linear layout."
|
|
936
|
+
);
|
|
937
|
+
}
|
|
923
938
|
return { suggestions, warnings };
|
|
924
939
|
}
|
|
925
940
|
};
|