hunter-mate 0.1.23 → 0.1.25

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.
Files changed (56) hide show
  1. package/dist/assets/extension/build-info.json +1 -1
  2. package/dist/assets/extension/manifest.json +3 -3
  3. package/dist/assets/server/chunks/{chunk-SAJB6JRK.mjs → chunk-VL7WHUEV.mjs} +556 -8
  4. package/dist/assets/server/chunks/{script-rule-ZJN6CEYX.mjs → script-rule-4RZQ2PQE.mjs} +1 -2
  5. package/dist/assets/server/main.mjs +220 -105
  6. package/dist/index.js +221 -38
  7. package/dist/web/dist/404.html +1 -1
  8. package/dist/web/dist/_next/static/chunks/253-a05d05b94bfbd7a4.js +1 -0
  9. package/dist/web/dist/_next/static/chunks/{852-248884963a986600.js → 852-ad19b97821a4cf9e.js} +1 -1
  10. package/dist/web/dist/_next/static/chunks/app/companies/{page-ec27ce9ab3610221.js → page-e8d02fe997579315.js} +1 -1
  11. package/dist/web/dist/_next/static/chunks/app/jobs/page-4827a9ef286b6483.js +1 -0
  12. package/dist/web/dist/_next/static/chunks/app/talents/{page-c0a0c250eb5f5459.js → page-0edef6d07b3cf69d.js} +1 -1
  13. package/dist/web/dist/_next/static/css/10ba1fa1d6ce23a7.css +3 -0
  14. package/dist/web/dist/admin/data.html +1 -1
  15. package/dist/web/dist/admin/data.txt +1 -1
  16. package/dist/web/dist/auth/verify.html +1 -1
  17. package/dist/web/dist/auth/verify.txt +1 -1
  18. package/dist/web/dist/companies.html +1 -1
  19. package/dist/web/dist/companies.txt +2 -2
  20. package/dist/web/dist/company/admin.html +1 -1
  21. package/dist/web/dist/company/admin.txt +1 -1
  22. package/dist/web/dist/entity.html +1 -1
  23. package/dist/web/dist/entity.txt +1 -1
  24. package/dist/web/dist/index.html +1 -1
  25. package/dist/web/dist/index.txt +1 -1
  26. package/dist/web/dist/jobs.html +1 -1
  27. package/dist/web/dist/jobs.txt +2 -2
  28. package/dist/web/dist/logs.html +1 -1
  29. package/dist/web/dist/logs.txt +1 -1
  30. package/dist/web/dist/matching/jobs/placeholder/talents.html +1 -1
  31. package/dist/web/dist/matching/jobs/placeholder/talents.txt +1 -1
  32. package/dist/web/dist/matching/portraits/placeholder/jobs.html +1 -1
  33. package/dist/web/dist/matching/portraits/placeholder/jobs.txt +1 -1
  34. package/dist/web/dist/parselog.html +1 -1
  35. package/dist/web/dist/parselog.txt +1 -1
  36. package/dist/web/dist/recordings.html +1 -1
  37. package/dist/web/dist/recordings.txt +1 -1
  38. package/dist/web/dist/resource-usage.html +1 -1
  39. package/dist/web/dist/resource-usage.txt +1 -1
  40. package/dist/web/dist/shared/placeholder.html +1 -1
  41. package/dist/web/dist/shared/placeholder.txt +1 -1
  42. package/dist/web/dist/snapshots/placeholder/agent-prompt.html +1 -1
  43. package/dist/web/dist/snapshots/placeholder/agent-prompt.txt +1 -1
  44. package/dist/web/dist/talents.html +1 -1
  45. package/dist/web/dist/talents.txt +2 -2
  46. package/dist/web/dist/team/insights.html +1 -1
  47. package/dist/web/dist/team/insights.txt +1 -1
  48. package/package.json +1 -1
  49. package/dist/assets/server/chunks/chunk-BLXHCSZD.mjs +0 -565
  50. package/dist/assets/server/chunks/esm-4U746B76.mjs +0 -29
  51. package/dist/web/dist/_next/static/chunks/954-fb0212fe71f60a52.js +0 -1
  52. package/dist/web/dist/_next/static/chunks/app/jobs/page-4175a90f1b42f87d.js +0 -1
  53. package/dist/web/dist/_next/static/css/bd072fee69ae8474.css +0 -3
  54. /package/dist/assets/extension/background/{service-worker.20261016165050.js → service-worker.20261017183328.js} +0 -0
  55. /package/dist/web/dist/_next/static/{a_JzW5lROd6a66UMqSE9Z → 5MA8faUttk6FzlxGWnOlM}/_buildManifest.js +0 -0
  56. /package/dist/web/dist/_next/static/{a_JzW5lROd6a66UMqSE9Z → 5MA8faUttk6FzlxGWnOlM}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- {"buildTime":"2026-10-16T16:50:50.748Z","version":"0.1.23"}
1
+ {"buildTime":"2026-10-17T18:33:28.755Z","version":"0.1.25"}
@@ -2,8 +2,8 @@
2
2
  "manifest_version": 3,
3
3
  "minimum_chrome_version": "116",
4
4
  "name": "__MSG_extName__",
5
- "description": "[build 10-16 16:50:50] __MSG_extDescription__",
6
- "version": "0.1.23",
5
+ "description": "[build 10-17 18:33:28] __MSG_extDescription__",
6
+ "version": "0.1.25",
7
7
  "default_locale": "zh_CN",
8
8
  "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAi/S88toqsiW6zleTj+V8jPUVTmrJiyDPvqTd+Cqrl/Ax9PCxaMsiXXUh2sNJh6sMj7xj0YBclCPMsI2wxIF8y4r6KnmWt49RuMg7EynvOT8fcRjxXBWGAz6hjGepWesOCMn9dgJ5IqgXP3j+Bfb+636IeW1nZxOedT25zJwJr81G4gIyc9kk+wCZPHUhQTsfNVxd8xfbxYQpcDuuVk1dDNEszeLUZGKYl9JcOQcaEQOWA4ED5avn67ZWQx5kzowB7XYtcTH0vz63cKNcK3O1iQ0hmFoohPKRWh9tNl545UQ2+mPaU6B/CNSZP2qwb+tgK7lVh5zG5qQkbaP8ZP8XaQIDAQAB",
9
9
  "permissions": [
@@ -27,7 +27,7 @@
27
27
  "<all_urls>"
28
28
  ],
29
29
  "background": {
30
- "service_worker": "background/service-worker.20261016165050.js",
30
+ "service_worker": "background/service-worker.20261017183328.js",
31
31
  "type": "module"
32
32
  },
33
33
  "content_scripts": [
@@ -14408,14 +14408,562 @@ var { merge: merge2 } = static_exports;
14408
14408
  var { parseHTML: parseHTML2 } = static_exports;
14409
14409
  var { root: root2 } = static_exports;
14410
14410
 
14411
+ // dist/.server-tsc/extraction/linkedin-extractor.js
14412
+ var SECTION_KEYWORDS = /* @__PURE__ */ new Set([
14413
+ "About",
14414
+ "Experience",
14415
+ "Education",
14416
+ "Skills",
14417
+ "Projects",
14418
+ "Featured",
14419
+ "Activity",
14420
+ "People you may know",
14421
+ "You might like",
14422
+ "Ad Options",
14423
+ "Don\u2019t want to see this",
14424
+ "Explore Premium profiles",
14425
+ "People who follow"
14426
+ ]);
14427
+ function isSectionLike(text3) {
14428
+ const t = text3.trim();
14429
+ if (!t)
14430
+ return true;
14431
+ for (const kw of SECTION_KEYWORDS) {
14432
+ if (t.includes(kw))
14433
+ return true;
14434
+ }
14435
+ return false;
14436
+ }
14437
+ var NON_NAME_KEYWORDS = /notifications|messages|jobs|network|home|search/i;
14438
+ function looksLikeName(text3) {
14439
+ const t = text3.trim();
14440
+ return t.length > 0 && t.length <= 80 && !isSectionLike(t) && !NON_NAME_KEYWORDS.test(t);
14441
+ }
14442
+ function isPunctuationOnly(text3) {
14443
+ return /^[^\p{L}\p{N}]*$/u.test(text3.trim());
14444
+ }
14445
+ function looksLikeLocation(text3) {
14446
+ const t = text3.trim();
14447
+ const parts = t.split(",").map((s) => s.trim()).filter(Boolean);
14448
+ if (parts.length === 0 || parts.length > 3)
14449
+ return false;
14450
+ return parts.every((p) => /^[A-Za-zÀ-ſ\s'-]{2,40}$/.test(p) && !/\d/.test(p));
14451
+ }
14452
+ function looksLikeUrl(text3) {
14453
+ return /^https?:\/\//.test(text3.trim());
14454
+ }
14455
+ function looksLikeFollowers(text3) {
14456
+ const t = text3.trim();
14457
+ return /followers|connections/i.test(t) || /^[\d,]+\+?\s*$/.test(t);
14458
+ }
14459
+ function looksLikeExperienceLocation(text3) {
14460
+ const t = text3.trim();
14461
+ if (t.length > 60)
14462
+ return false;
14463
+ if (/\b(Area|Region|City|Metropolitan)\b/i.test(t))
14464
+ return true;
14465
+ if (/^[A-Z][a-z]+(?:\s+[A-Z][a-z]+){0,5}(?:\s+(Area|Region|City|Metropolitan))?$/i.test(t))
14466
+ return true;
14467
+ return false;
14468
+ }
14469
+ function looksLikeDateRange(text3) {
14470
+ const t = text3.trim();
14471
+ const hasYear = /\b(19|20)\d{2}\b/.test(t);
14472
+ const hasMonthOrPresent = /\b(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec|Present|present|至今)\b/.test(t);
14473
+ const yearRange = /\b(19|20)\d{2}\b\s*[-–—]\s*\b(19|20)\d{2}\b/.test(t);
14474
+ return hasYear && (hasMonthOrPresent || yearRange);
14475
+ }
14476
+ function firstText($2, container) {
14477
+ return $2(container).text().replace(/\s+/g, " ").trim();
14478
+ }
14479
+ function extractLinkedInProfile(html3) {
14480
+ const $2 = typeof html3 === "string" ? load(html3) : html3;
14481
+ const out = {};
14482
+ const h2s = $2("h2");
14483
+ let name = null;
14484
+ let nameEl = null;
14485
+ h2s.each((_i, el) => {
14486
+ if (name)
14487
+ return;
14488
+ const $el = $2(el);
14489
+ const cls = $el.attr("class") || "";
14490
+ const parentCls = $el.parent().attr("class") || "";
14491
+ const t = $el.text().replace(/\s+/g, " ").trim().replace(/\s*\|\s*$/, "");
14492
+ if (looksLikeName(t) && (cls.includes("_1f667e81") || parentCls.includes("a8841267"))) {
14493
+ name = t;
14494
+ nameEl = $el;
14495
+ }
14496
+ });
14497
+ if (!name) {
14498
+ h2s.each((_i, el) => {
14499
+ if (name)
14500
+ return;
14501
+ const t = $2(el).text().replace(/\s+/g, " ").trim().replace(/\s*\|\s*$/, "");
14502
+ if (looksLikeName(t)) {
14503
+ name = t;
14504
+ nameEl = $2(el);
14505
+ }
14506
+ });
14507
+ }
14508
+ if (name)
14509
+ out.name = name;
14510
+ const topCard = nameEl ? nameEl.closest("section").first() : h2s.first().closest("section").first();
14511
+ const topTexts = [];
14512
+ topCard.find("p").each((_i, el) => {
14513
+ const t = $2(el).text().replace(/\s+/g, " ").trim();
14514
+ if (t && !topTexts.includes(t))
14515
+ topTexts.push(t);
14516
+ });
14517
+ const meaningfulTop = topTexts.filter((t) => !/^·\s*\d+(?:rd|th|nd|st)?$/.test(t));
14518
+ if (meaningfulTop[0] && !isSectionLike(meaningfulTop[0])) {
14519
+ out.headline = meaningfulTop[0];
14520
+ }
14521
+ if (meaningfulTop[1] && !isSectionLike(meaningfulTop[1]) && !isPunctuationOnly(meaningfulTop[1])) {
14522
+ out.currentCompany = meaningfulTop[1];
14523
+ }
14524
+ for (let i = 0; i < meaningfulTop.length; i++) {
14525
+ const t = meaningfulTop[i];
14526
+ if (t === out.headline || t === out.currentCompany)
14527
+ continue;
14528
+ if (!out.location && looksLikeLocation(t))
14529
+ out.location = t;
14530
+ if (looksLikeUrl(t))
14531
+ out.website = t;
14532
+ if (looksLikeFollowers(t)) {
14533
+ const next2 = meaningfulTop[i + 1];
14534
+ out.followers = next2 && /connections|followers/i.test(next2) ? `${t} ${next2}` : t;
14535
+ if (next2 && /connections|followers/i.test(next2))
14536
+ i++;
14537
+ }
14538
+ }
14539
+ const aboutH2 = h2s.filter((_i, el) => $2(el).text().includes("About")).first();
14540
+ if (aboutH2.length) {
14541
+ let cursor = aboutH2.parent().next();
14542
+ const summaryParts = [];
14543
+ for (let i = 0; i < 6 && cursor.length; i++) {
14544
+ const tag = cursor.prop("tagName")?.toLowerCase();
14545
+ if (tag === "h2")
14546
+ break;
14547
+ const t = firstText($2, cursor);
14548
+ if (t.length > 20 && !isSectionLike(t))
14549
+ summaryParts.push(t);
14550
+ cursor = cursor.next();
14551
+ }
14552
+ if (summaryParts.length)
14553
+ out.summary = summaryParts.join(" ");
14554
+ }
14555
+ const expH2 = h2s.filter((_i, el) => $2(el).text().includes("Experience")).first();
14556
+ if (expH2.length) {
14557
+ const section = expH2.closest("section").first();
14558
+ const pTexts = [];
14559
+ section.find("p").each((_i, el) => {
14560
+ const t = firstText($2, el);
14561
+ if (t && !isSectionLike(t))
14562
+ pTexts.push(t);
14563
+ });
14564
+ const experiences = [];
14565
+ let lastDateIdx = -1;
14566
+ for (let i = 0; i < pTexts.length; i++) {
14567
+ if (looksLikeDateRange(pTexts[i])) {
14568
+ const item = { duration: pTexts[i] };
14569
+ if (pTexts[i - 1])
14570
+ item.company = pTexts[i - 1];
14571
+ if (pTexts[i - 2])
14572
+ item.title = pTexts[i - 2];
14573
+ if (experiences.length > 0 && lastDateIdx >= 0) {
14574
+ const desc = pTexts.slice(lastDateIdx + 1, i - 2);
14575
+ if (desc.length) {
14576
+ const first2 = desc[0];
14577
+ if (looksLikeExperienceLocation(first2)) {
14578
+ experiences[experiences.length - 1].location = first2;
14579
+ if (desc.length > 1) {
14580
+ experiences[experiences.length - 1].description = desc.slice(1).join(" ");
14581
+ }
14582
+ } else {
14583
+ experiences[experiences.length - 1].description = desc.join(" ");
14584
+ }
14585
+ }
14586
+ }
14587
+ if (Object.keys(item).length > 1)
14588
+ experiences.push(item);
14589
+ lastDateIdx = i;
14590
+ }
14591
+ }
14592
+ if (experiences.length)
14593
+ out.experiences = experiences;
14594
+ }
14595
+ const eduH2 = h2s.filter((_i, el) => $2(el).text().includes("Education")).first();
14596
+ if (eduH2.length) {
14597
+ const section = eduH2.closest("section").first();
14598
+ const pTexts = [];
14599
+ section.find("p").each((_i, el) => {
14600
+ const t = firstText($2, el);
14601
+ if (t && !isSectionLike(t))
14602
+ pTexts.push(t);
14603
+ });
14604
+ const education = [];
14605
+ let lastDateIdx = -1;
14606
+ for (let i = 0; i < pTexts.length; i++) {
14607
+ if (looksLikeDateRange(pTexts[i])) {
14608
+ const item = { years: pTexts[i] };
14609
+ if (pTexts[i - 2]) {
14610
+ item.school = pTexts[i - 2];
14611
+ item.degree = pTexts[i - 1];
14612
+ } else if (pTexts[i - 1]) {
14613
+ item.school = pTexts[i - 1];
14614
+ }
14615
+ if (Object.keys(item).length > 1)
14616
+ education.push(item);
14617
+ lastDateIdx = i;
14618
+ }
14619
+ }
14620
+ if (lastDateIdx >= 0 && lastDateIdx < pTexts.length - 1) {
14621
+ const tail = pTexts.slice(lastDateIdx + 1);
14622
+ if (tail.length >= 2) {
14623
+ education.push({ school: tail[0], degree: tail[1] });
14624
+ } else if (tail.length === 1) {
14625
+ education.push({ school: tail[0] });
14626
+ }
14627
+ }
14628
+ if (education.length)
14629
+ out.education = education;
14630
+ }
14631
+ const skillH2 = h2s.filter((_i, el) => $2(el).text().includes("Skills")).first();
14632
+ if (skillH2.length) {
14633
+ const section = skillH2.closest("section, div").first();
14634
+ const skills = /* @__PURE__ */ new Set();
14635
+ section.find('span, button, a, li, div[role="listitem"]').each((_i, el) => {
14636
+ const t = firstText($2, el);
14637
+ if (t && t.length <= 50 && t.length >= 2 && !isSectionLike(t) && !looksLikeDateRange(t) && !looksLikeFollowers(t) && !looksLikeUrl(t)) {
14638
+ skills.add(t);
14639
+ }
14640
+ });
14641
+ if (skills.size)
14642
+ out.skills = Array.from(skills).slice(0, 50);
14643
+ }
14644
+ return out;
14645
+ }
14646
+
14647
+ // dist/.server-tsc/extraction/talent-entity.js
14648
+ var LIEPIN_CONSUMED_SECTION_KEYS = /* @__PURE__ */ new Set([
14649
+ "single",
14650
+ "basic-info",
14651
+ "job-exp-info",
14652
+ "job-expectancy-info-wrap",
14653
+ "work-info",
14654
+ "project-info",
14655
+ "edu-info",
14656
+ "lang-info",
14657
+ "skill-info",
14658
+ "self-eva-info",
14659
+ "self-evaluation-info",
14660
+ "operation-wrap"
14661
+ ]);
14662
+ var LIEPIN_WORK_KNOWN_COLS = /* @__PURE__ */ new Set([
14663
+ "\u6240\u5728\u90E8\u95E8",
14664
+ "\u5DE5\u4F5C\u5730\u70B9",
14665
+ "\u4E0B\u5C5E\u4EBA\u6570",
14666
+ "\u6C47\u62A5\u5BF9\u8C61",
14667
+ "\u804C\u8D23\u4E1A\u7EE9"
14668
+ ]);
14669
+ var LIEPIN_PROJECT_KNOWN_COLS = /* @__PURE__ */ new Set(["\u9879\u76EE\u804C\u52A1", "\u6240\u5728\u516C\u53F8", "\u9879\u76EE\u63CF\u8FF0", "\u9879\u76EE\u804C\u8D23"]);
14670
+ function pickUnmappedCols(cols, known) {
14671
+ const out = {};
14672
+ for (const [k, v] of Object.entries(cols)) {
14673
+ if (!known.has(k))
14674
+ out[k] = v;
14675
+ }
14676
+ return Object.keys(out).length ? out : void 0;
14677
+ }
14678
+
14679
+ // dist/.server-tsc/extraction/liepin-extractor.js
14680
+ var clean = (s) => {
14681
+ if (s == null)
14682
+ return null;
14683
+ const t = s.replace(/\s+/g, " ").trim();
14684
+ return t || null;
14685
+ };
14686
+ function splitByI($2, el) {
14687
+ const html3 = $2(el).html() || "";
14688
+ return html3.replace(/<i[^>]*>\s*<\/i>/g, "|").split("|").map((s) => clean($2(s).text?.() ?? s) ?? clean(s.replace(/<[^>]+>/g, ""))).map((s) => s || "").filter(Boolean);
14689
+ }
14690
+ function parsePeriod(text3) {
14691
+ const m = text3.match(/[((]\s*([^))]*?)\s*[))]/);
14692
+ if (!m)
14693
+ return { start: null, end: null, duration: null };
14694
+ const parts = m[1].split(",").map((s) => clean(s)).filter(Boolean);
14695
+ const range = (parts[0] || "").split("-").map((s) => clean(s));
14696
+ return {
14697
+ start: range[0] || null,
14698
+ end: range[1] || null,
14699
+ duration: parts[1] || null
14700
+ };
14701
+ }
14702
+ function readInfoCols($2, root3) {
14703
+ const out = {};
14704
+ root3.find(".rd-info-col").each((_i, col) => {
14705
+ const title = clean($2(col).find(".rd-info-col-title").first().text());
14706
+ const cont = clean($2(col).find(".rd-info-col-cont").first().text());
14707
+ if (title && cont)
14708
+ out[title.replace(/[::]\s*$/, "")] = cont;
14709
+ });
14710
+ return out;
14711
+ }
14712
+ function extractBasic($2) {
14713
+ const root3 = $2("#resume-detail-basic-info, .resume-detail-basic-info").first();
14714
+ if (!root3.length)
14715
+ return {};
14716
+ const name = clean(root3.find(".name-box .name").first().text());
14717
+ const sepInfos = root3.find(".basic-cont .sep-info, .sep-info").toArray();
14718
+ const sepParts = sepInfos.map((el) => splitByI($2, el));
14719
+ const contactIdx = sepParts.findIndex((p) => /方便联系时间/.test(p.join(" ")));
14720
+ const personalIdx = sepParts.findIndex((p) => /岁|工作\s*\d+\s*年/.test(p.join(" ")));
14721
+ const partsP = personalIdx >= 0 ? sepParts[personalIdx] : sepParts[0] ?? [];
14722
+ const companyIdx = sepParts.findIndex((p, i) => i !== personalIdx && i !== contactIdx && p.join(" ").trim().length > 0);
14723
+ const partsC = companyIdx >= 0 ? sepParts[companyIdx] : [];
14724
+ const joined0 = partsP.join(" ");
14725
+ const age = joined0.match(/(\d+)\s*岁/)?.[1] ?? null;
14726
+ const workYears = joined0.match(/工作\s*(\d+)\s*年/)?.[1] ?? null;
14727
+ const gender = partsP.find((p) => /^(男|女)$/.test(p)) ?? null;
14728
+ const currentPosition = partsC.length ? partsC[0] : null;
14729
+ const personalLast = partsP.length ? partsP[partsP.length - 1] ?? null : null;
14730
+ const companyFromLine = partsC.length > 1 ? partsC.slice(1).join(" ") : null;
14731
+ const currentCompany = personalLast === "\u4FDD\u5BC6" ? "\u4FDD\u5BC6" : companyFromLine ?? personalLast;
14732
+ const companyMasked = currentCompany === "\u4FDD\u5BC6" ? true : partsP.includes("\u4FDD\u5BC6") || (currentCompany ? /保密/.test(currentCompany) : false) ? true : void 0;
14733
+ const contactTimeRaw = clean(root3.find(".res-status-box").first().text());
14734
+ return {
14735
+ name,
14736
+ nameMasked: name ? /\*/.test(name) : void 0,
14737
+ statusTag: clean(root3.find(".user-status-tag").first().text()),
14738
+ gender,
14739
+ age: age ? Number(age) : null,
14740
+ city: partsP.find((p) => /^(北京|上海|广州|深圳|天津|重庆|杭州|南京|苏州|成都|武汉|西安)$/.test(p)) ?? partsP.find((p) => /^[一-鿿]{2,6}$/.test(p) && !/^(男|女|保密)$/.test(p) && !/岁|年/.test(p) && !/(博士|硕士|MBA|本科|大专|专科|高中|中专|初中)/.test(p)) ?? null,
14741
+ degree: partsP.find((p) => /(博士|硕士|MBA|本科|大专|专科|高中|中专|初中)/.test(p)) ?? null,
14742
+ workYears: workYears ? Number(workYears) : null,
14743
+ workYearsText: joined0.match(/工作[^|]*/) ? joined0.match(/工作\s*\d+\s*年/)?.[0] ?? null : null,
14744
+ currentCompany: currentCompany ?? null,
14745
+ currentCompanyMasked: companyMasked,
14746
+ currentPosition,
14747
+ contactTime: contactTimeRaw ? contactTimeRaw.replace(/^方便联系时间[::]\s*/, "") : null,
14748
+ photoUrl: root3.find(".logo-box img").first().attr("src") ?? null
14749
+ };
14750
+ }
14751
+ function extractIntent($2) {
14752
+ const root3 = $2("#resume-detail-job-exp-info, .resume-detail-job-expectancy-info-wrap").first();
14753
+ if (!root3.length)
14754
+ return {};
14755
+ const labels = root3.find(".lebels-wrap span").toArray().map((el) => clean($2(el).text())).filter(Boolean);
14756
+ return {
14757
+ position: clean(root3.find(".tabs .title").first().attr("title")) ?? clean(root3.find(".tabs .title").first().text()),
14758
+ salary: clean(root3.find(".tabs .salary").first().text()),
14759
+ city: clean(root3.find(".dqname-wrap").first().text()),
14760
+ industries: labels
14761
+ };
14762
+ }
14763
+ function extractWorkExperiences($2) {
14764
+ const out = [];
14765
+ $2("#resume-detail-work-info .rd-work-item-cont, .resume-detail-work-info .rd-info-tpl-item").each((_i, el) => {
14766
+ const item = $2(el);
14767
+ const periodText = clean(item.find(".rd-work-time").first().text()) ?? "";
14768
+ const cols = readInfoCols($2, item);
14769
+ const extra = pickUnmappedCols(cols, LIEPIN_WORK_KNOWN_COLS);
14770
+ out.push({
14771
+ company: clean(item.find(".rd-work-comp h5").first().attr("title")) ?? clean(item.find(".rd-work-comp h5").first().text()),
14772
+ ...parsePeriod(periodText),
14773
+ position: clean(item.find(".job-name").first().text()),
14774
+ department: cols["\u6240\u5728\u90E8\u95E8"] ?? null,
14775
+ location: cols["\u5DE5\u4F5C\u5730\u70B9"] ?? null,
14776
+ subordinates: cols["\u4E0B\u5C5E\u4EBA\u6570"] != null ? Number(cols["\u4E0B\u5C5E\u4EBA\u6570"]) : null,
14777
+ reportsTo: cols["\u6C47\u62A5\u5BF9\u8C61"] ?? null,
14778
+ responsibilities: cols["\u804C\u8D23\u4E1A\u7EE9"] ?? null,
14779
+ ...extra ? { extra } : {}
14780
+ });
14781
+ });
14782
+ return out;
14783
+ }
14784
+ function extractProjects($2) {
14785
+ const out = [];
14786
+ $2("#resume-detail-project-info .rd-project-item-cont, .resume-detail-project-info .rd-project-item-cont, .resume-detail-project-info .rd-info-tpl-item").each((_i, el) => {
14787
+ const item = $2(el);
14788
+ const periodText = clean(item.find(".rd-project-time").first().text()) ?? "";
14789
+ const cols = readInfoCols($2, item);
14790
+ const extra = pickUnmappedCols(cols, LIEPIN_PROJECT_KNOWN_COLS);
14791
+ out.push({
14792
+ name: clean(item.find(".rd-project-name h5").first().attr("title")) ?? clean(item.find(".rd-project-name h5").first().text()),
14793
+ ...parsePeriod(periodText),
14794
+ role: cols["\u9879\u76EE\u804C\u52A1"] ?? null,
14795
+ company: cols["\u6240\u5728\u516C\u53F8"] ?? null,
14796
+ description: cols["\u9879\u76EE\u63CF\u8FF0"] ?? null,
14797
+ duties: cols["\u9879\u76EE\u804C\u8D23"] ?? null,
14798
+ ...extra ? { extra } : {}
14799
+ });
14800
+ });
14801
+ return out;
14802
+ }
14803
+ function extractEducation($2) {
14804
+ const out = [];
14805
+ $2("#resume-detail-edu-info .rd-edu-info-item, .resume-detail-edu-info .rd-edu-info-item").each((_i, el) => {
14806
+ const item = $2(el);
14807
+ const raw = clean(item.text()) ?? "";
14808
+ const segs = raw.split("\xB7").map((s) => clean(s)).filter(Boolean);
14809
+ const periodM = raw.match(/\d{4}\.\d{2}\s*-\s*(?:\d{4}\.\d{2}|至今)/);
14810
+ const segEdu = (segs.length > 2 ? segs[2] : segs.length > 1 ? segs[1] : "").match(/(博士|硕士|MBA|本科|大专|专科|高中|中专|初中)/);
14811
+ out.push({
14812
+ school: clean(item.find(".school-name").first().attr("title")) ?? clean(item.find(".school-name").first().text()),
14813
+ major: clean(item.find(".school-special").first().attr("title")) ?? clean(item.find(".school-special").first().text()) ?? (segs.length > 1 ? /^(博士|硕士|MBA|本科|大专|专科|高中|中专|初中)/.test(segs[1]) ? null : segs[1] : null),
14814
+ degree: clean(item.find(".school-degree").first().attr("title")) ?? clean(item.find(".school-degree").first().text()) ?? (segEdu ? segEdu[0] : null),
14815
+ period: clean(item.find(".school-time").first().text()) ?? (periodM ? periodM[0] : null),
14816
+ tags: item.find(".edu-school-tags .tag-item, .tag-item").toArray().map((t) => clean($2(t).text())).filter(Boolean)
14817
+ });
14818
+ });
14819
+ return out;
14820
+ }
14821
+ function extractResId($2) {
14822
+ const scm = $2("[data-tlg-scm]").first().attr("data-tlg-scm") || "";
14823
+ const m = scm.match(/cid=([^&]+)/);
14824
+ return m?.[1] ?? null;
14825
+ }
14826
+ function sweepExtraSections($2) {
14827
+ const sections = [];
14828
+ const seen = /* @__PURE__ */ new Set();
14829
+ $2('[id^="resume-detail-"], [class*="resume-detail-"]').each((_i, el) => {
14830
+ const $el = $2(el);
14831
+ const id = $el.attr("id") || "";
14832
+ const cls = ($el.attr("class") || "").split(/\s+/).find((c) => c.startsWith("resume-detail-") && c !== "resume-detail-template" && c !== "resume-detail-template-cont") || "";
14833
+ const key = (id || cls).replace(/^resume-detail-/, "");
14834
+ if (!key || seen.has(key))
14835
+ return;
14836
+ const isSection = $el.find(".resume-detail-template-cont").length > 0 || $el.parents('[id^="resume-detail-"], [class*="resume-detail-"]').length === 0;
14837
+ if (!isSection)
14838
+ return;
14839
+ seen.add(key);
14840
+ if (LIEPIN_CONSUMED_SECTION_KEYS.has(key))
14841
+ return;
14842
+ const text3 = clean($el.text());
14843
+ if (!text3)
14844
+ return;
14845
+ const title = clean($el.find(".resume-detail-template-title, .template-title").first().text()) ?? clean($el.find("h3, h4").first().text());
14846
+ sections.push({ key, title, text: text3.length > 2e3 ? `${text3.slice(0, 2e3)}\u2026` : text3 });
14847
+ });
14848
+ return sections;
14849
+ }
14850
+ function extractLiepinTalent(html3) {
14851
+ const $2 = typeof html3 === "string" ? load(html3) : html3;
14852
+ const isTalentPage = $2("#resume-detail-basic-info, .resume-detail-basic-info").length > 0;
14853
+ if (!isTalentPage)
14854
+ return { platform: "liepin", pageType: "unknown" };
14855
+ const languages = $2("#resume-detail-lang-info .rd-lang-item .lang-name, .resume-detail-lang-info .rd-lang-item .lang-name").toArray().map((el) => clean($2(el).text())).filter(Boolean);
14856
+ const skills = $2("#resume-detail-skill-info .skill-tag, .resume-detail-skill-info .skill-tag").toArray().map((el) => clean($2(el).text())).filter(Boolean);
14857
+ const basic = extractBasic($2);
14858
+ const workExperiences = extractWorkExperiences($2);
14859
+ const projects = extractProjects($2);
14860
+ const education = extractEducation($2);
14861
+ const extraSections = sweepExtraSections($2);
14862
+ return {
14863
+ platform: "liepin",
14864
+ pageType: "talent",
14865
+ resId: extractResId($2),
14866
+ ...basic,
14867
+ intent: extractIntent($2),
14868
+ workExperiences,
14869
+ projects,
14870
+ education,
14871
+ languages,
14872
+ skills,
14873
+ selfEvaluation: clean($2("#resume-detail-self-eva-info .resume-detail-template-cont").first().text()) ?? clean($2(".resume-detail-self-evaluation-info").first().text()),
14874
+ statement: clean($2(".c-detail-statement").first().text()),
14875
+ hasAntiScrapeWatermark: $2(".cozue").length > 0,
14876
+ ...extraSections.length ? { extra: { sections: extraSections } } : {},
14877
+ _counts: {
14878
+ workExperiences: workExperiences.length,
14879
+ projects: projects.length,
14880
+ education: education.length,
14881
+ languages: languages.length,
14882
+ skills: skills.length,
14883
+ extraSections: extraSections.length
14884
+ }
14885
+ };
14886
+ }
14887
+
14888
+ // dist/.server-tsc/extraction/script-rule.js
14889
+ function readField($2, root3, rule) {
14890
+ const el = rule.self ? root3.first() : root3.find(rule.selector).first();
14891
+ if (!el.length)
14892
+ return null;
14893
+ let value;
14894
+ if (!rule.attr || rule.attr === "text")
14895
+ value = el.text().trim();
14896
+ else if (rule.attr === "html")
14897
+ value = el.html();
14898
+ else
14899
+ value = el.attr(rule.attr) ?? null;
14900
+ if (value == null)
14901
+ return null;
14902
+ if (rule.regex) {
14903
+ const m = value.match(new RegExp(rule.regex, "s"));
14904
+ value = m?.[1]?.trim() ?? null;
14905
+ }
14906
+ return value || null;
14907
+ }
14908
+ function toCheerio(html3) {
14909
+ return typeof html3 === "string" ? load(html3) : html3;
14910
+ }
14911
+ function applyScriptRule(html3, payload) {
14912
+ if (payload.engine === "linkedin-profile") {
14913
+ return extractLinkedInProfile(html3);
14914
+ }
14915
+ if (payload.engine === "liepin-talent") {
14916
+ return extractLiepinTalent(html3);
14917
+ }
14918
+ const $2 = toCheerio(html3);
14919
+ const out = {};
14920
+ for (const [field, rule] of Object.entries(payload.fields || {})) {
14921
+ out[field] = readField($2, $2("body").length ? $2("body") : $2.root(), rule);
14922
+ }
14923
+ for (const [listName, listRule] of Object.entries(payload.lists || {})) {
14924
+ const items = [];
14925
+ $2(listRule.selector).each((_i, el) => {
14926
+ const item = {};
14927
+ for (const [field, rule] of Object.entries(listRule.fields)) {
14928
+ item[field] = readField($2, $2(el), rule);
14929
+ }
14930
+ if (Object.values(item).some((v) => v != null))
14931
+ items.push(item);
14932
+ });
14933
+ if (items.length) {
14934
+ const seen = /* @__PURE__ */ new Set();
14935
+ out[listName] = items.filter((item) => {
14936
+ const key = JSON.stringify(item, Object.keys(item).sort());
14937
+ if (seen.has(key))
14938
+ return false;
14939
+ seen.add(key);
14940
+ return true;
14941
+ });
14942
+ }
14943
+ }
14944
+ if (payload.entityList) {
14945
+ const items = [];
14946
+ $2(payload.entityList.selector).each((_i, el) => {
14947
+ const item = {};
14948
+ for (const [field, rule] of Object.entries(payload.entityList.fields)) {
14949
+ item[field] = readField($2, $2(el), rule);
14950
+ }
14951
+ if (Object.values(item).some((v) => v != null))
14952
+ items.push(item);
14953
+ });
14954
+ const seen = /* @__PURE__ */ new Set();
14955
+ out.__entityList = items.filter((item) => {
14956
+ const key = JSON.stringify(item, Object.keys(item).sort());
14957
+ if (seen.has(key))
14958
+ return false;
14959
+ seen.add(key);
14960
+ return true;
14961
+ });
14962
+ }
14963
+ return out;
14964
+ }
14965
+
14411
14966
  export {
14412
- html,
14413
- xml,
14414
- text,
14415
14967
  load,
14416
- esm_default2 as esm_default,
14417
- contains2 as contains,
14418
- merge2 as merge,
14419
- parseHTML2 as parseHTML,
14420
- root2 as root
14968
+ applyScriptRule
14421
14969
  };
@@ -6,8 +6,7 @@ const __filename = __f2p(import.meta.url);
6
6
  const __dirname = __dirnameFn(__filename);
7
7
  import {
8
8
  applyScriptRule
9
- } from "./chunk-BLXHCSZD.mjs";
10
- import "./chunk-SAJB6JRK.mjs";
9
+ } from "./chunk-VL7WHUEV.mjs";
11
10
  import "./chunk-GNM26E3H.mjs";
12
11
  export {
13
12
  applyScriptRule