Auto-deploy: 2026-08-05 18:11:15
This commit is contained in:
+32
-30
@@ -48,25 +48,6 @@
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Job Title (many fallbacks)
|
|
||||||
data.jobTitle = trySelectors([
|
|
||||||
'.job-details-jobs-unified-top-card__job-title h1 a',
|
|
||||||
'.job-details-jobs-unified-top-card__job-title h1',
|
|
||||||
'.jobs-unified-top-card__job-title h1',
|
|
||||||
'.jobs-unified-top-card__job-title',
|
|
||||||
'.job-details-jobs-unified-top-card__job-title',
|
|
||||||
'h2.job-details-jobs-unified-top-card__job-title',
|
|
||||||
'.jobs-unified-top-card__job-title a',
|
|
||||||
'h1.t-24',
|
|
||||||
'h1.t-18',
|
|
||||||
'h1[class*="job-title"]',
|
|
||||||
'h2[class*="job-title"]',
|
|
||||||
'.t-24.t-bold',
|
|
||||||
'.top-card-layout__title',
|
|
||||||
'a[class*="topcard__title"]',
|
|
||||||
'.topcard__title',
|
|
||||||
]);
|
|
||||||
|
|
||||||
// LinkedIn's job panel is full of text that is neither navigation nor the
|
// LinkedIn's job panel is full of text that is neither navigation nor the
|
||||||
// job title: screen-reader-only headings ("0 notifications"), and product
|
// job title: screen-reader-only headings ("0 notifications"), and product
|
||||||
// furniture inside the detail column itself ("Are these results helpful?",
|
// furniture inside the detail column itself ("Are these results helpful?",
|
||||||
@@ -98,33 +79,54 @@
|
|||||||
return text.length > 4 && text.length < 100 && !NAV_NOISE.test(text);
|
return text.length > 4 && text.length < 100 && !NAV_NOISE.test(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preferred fallback 1: Extract from active job link using currentJobId
|
// 1. Most Reliable Method: Extract from active job link using currentJobId
|
||||||
if (!data.jobTitle) {
|
|
||||||
let currentJobId = new URLSearchParams(window.location.search).get('currentJobId');
|
let currentJobId = new URLSearchParams(window.location.search).get('currentJobId');
|
||||||
if (!currentJobId) {
|
if (!currentJobId) {
|
||||||
const match = window.location.pathname.match(/\/jobs\/view\/(\d+)/);
|
const match = window.location.pathname.match(/\/jobs\/view\/(\d+)/);
|
||||||
if (match) currentJobId = match[1];
|
if (match) currentJobId = match[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentJobId) {
|
if (currentJobId) {
|
||||||
|
// Find all links containing this job ID
|
||||||
const links = document.querySelectorAll(`a[href*="/jobs/view/${currentJobId}"]`);
|
const links = document.querySelectorAll(`a[href*="/jobs/view/${currentJobId}"]`);
|
||||||
for (const link of links) {
|
for (const link of links) {
|
||||||
const text = link.innerText.trim();
|
const text = (link.textContent || '').trim();
|
||||||
// Filter out empty or obviously wrong texts
|
// Filter out empty or obviously wrong texts (like "Save", "Easy Apply")
|
||||||
if (plausibleTitle(text) && !text.includes('Easy Apply') && !text.includes('Save')) {
|
if (text && plausibleTitle(text) && !text.includes('Easy Apply') && !text.includes('Save')) {
|
||||||
data.jobTitle = text;
|
data.jobTitle = text;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2. Fallback: Try known selectors
|
||||||
|
if (!data.jobTitle) {
|
||||||
|
data.jobTitle = trySelectors([
|
||||||
|
'.job-details-jobs-unified-top-card__job-title h1 a',
|
||||||
|
'.job-details-jobs-unified-top-card__job-title h1',
|
||||||
|
'.jobs-unified-top-card__job-title h1',
|
||||||
|
'.jobs-unified-top-card__job-title',
|
||||||
|
'.job-details-jobs-unified-top-card__job-title',
|
||||||
|
'h2.job-details-jobs-unified-top-card__job-title',
|
||||||
|
'.jobs-unified-top-card__job-title a',
|
||||||
|
'h1.t-24',
|
||||||
|
'h1.t-18',
|
||||||
|
'h1[class*="job-title"]',
|
||||||
|
'h2[class*="job-title"]',
|
||||||
|
'.t-24.t-bold',
|
||||||
|
'.top-card-layout__title',
|
||||||
|
'a[class*="topcard__title"]',
|
||||||
|
'.topcard__title',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// If we grabbed garbage, reset it
|
||||||
|
if (data.jobTitle && !plausibleTitle(data.jobTitle)) {
|
||||||
|
data.jobTitle = '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preferred fallback 2: the browser tab title. LinkedIn sets it to
|
// 3. Last Resort Fallback: Browser tab title
|
||||||
// "(N) Job Title | Company | LinkedIn" on every job page, it is not part of
|
|
||||||
// the React DOM that keeps getting restructured, and it cannot pick up a
|
|
||||||
// stray card heading. This is far more reliable than guessing at headings,
|
|
||||||
// so it runs before the DOM scan, not after it.
|
|
||||||
if (!data.jobTitle) {
|
if (!data.jobTitle) {
|
||||||
// The "(N)" prefix is LinkedIn's unread counter and can read "(99+)".
|
|
||||||
const m = document.title.match(/^(?:\(\d+\+?\)\s*)?(.+?)\s*[|·]/);
|
const m = document.title.match(/^(?:\(\d+\+?\)\s*)?(.+?)\s*[|·]/);
|
||||||
if (m) {
|
if (m) {
|
||||||
const candidate = m[1].trim();
|
const candidate = m[1].trim();
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user