diff --git a/README.md b/README.md index f30dd48..f1acfac 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ When in doubt, refresh the profile page before using this tool. ## Updates: Date | Release | Notes --- | --- | --- +7/31/2020 | 1.4.1 | Fix: In some cases, wrong profileUrnId was extracted from current profile, which led to work history API call being ran against a *different* profile (e.g. from "recommended section", or something like that). 7/21/2020 | 1.4.0 | Fix: For vCard exports, Previous profile was getting grabbed after SPA navigation between profiles. 7/6/2020 | 1.3.0 | Fix: Incomplete work position entries for some users; LI was limiting the amount of pre-fetched data. Had to implement request paging to fix.

Also refactored a lot of code, improved result caching, and other tweaks. 6/18/2020 | 1.2.0 | Fix / Improve VCard export feature. diff --git a/package-lock.json b/package-lock.json index a9e3900..7bd36ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "linkedin-to-json-resume-exporter", - "version": "1.4.0", + "version": "1.4.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 2714e50..4a1b32c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "linkedin-to-json-resume-exporter", - "version": "1.4.0", + "version": "1.4.1", "description": "Browser tool to grab details from your open LinkedIn profile page and export to JSON Resume Schema", "private": true, "main": "src/main.js", diff --git a/src/main.js b/src/main.js index b71469b..9378dee 100644 --- a/src/main.js +++ b/src/main.js @@ -488,7 +488,7 @@ window.LinkedinToResumeJson = (() => { } /** - * + * Main parser for giant profile JSON block * @param {LinkedinToResumeJson} instance * @param {LiResponse} profileObj */ @@ -518,7 +518,9 @@ window.LinkedinToResumeJson = (() => { resultSummary.localeStr = _this.preferLocale; } try { + // Build db object const db = buildDbFromLiSchema(profileObj); + // Parse basics / profile let profileGrabbed = false; db.getValuesByKey(_liSchemaKeys.profile).forEach((profile) => { @@ -869,8 +871,9 @@ window.LinkedinToResumeJson = (() => { if (fullProfileView && typeof fullProfileView.data === 'object') { // Try to use the same parser that I use for embedded const profileParserResult = await parseProfileSchemaJSON(this, fullProfileView); + this.debugConsole.log(`Parse full profile via internal API, success = ${profileParserResult.parseSuccess}`); if (profileParserResult.parseSuccess) { - this.debugConsole.log('Was able to parse full profile via internal API'); + this.profileParseSummary = profileParserResult; } // Some sections might require additional fetches to fill missing data if (profileParserResult.sections.work === 'incomplete') { @@ -1193,11 +1196,11 @@ window.LinkedinToResumeJson = (() => { if (_this.parseSuccess) { if (_this.scannedPageUrl === _this.getUrlWithoutQuery() && localeStayedSame) { // No need to reparse! - this.debugConsole.log('Skipped re-parse; page has not changed'); + _this.debugConsole.log('Skipped re-parse; page has not changed'); resolve(true); } else { // Parse already done, but page changed (ajax) - this.debugConsole.warn('Re-parsing for new results; page has changed between scans'); + _this.debugConsole.warn('Re-parsing for new results; page has changed between scans'); await _this.forceReParse(localeToUse); resolve(true); } @@ -1216,7 +1219,7 @@ window.LinkedinToResumeJson = (() => { } else { await _this.parseViaInternalApi(); if (!_this.parseSuccess) { - await this.parseEmbeddedLiSchema(); + await _this.parseEmbeddedLiSchema(); } } _this.scannedPageUrl = _this.getUrlWithoutQuery(); @@ -1431,16 +1434,35 @@ window.LinkedinToResumeJson = (() => { * Get the internal URN ID of the active profile * - Not needed for JSON Resume, but for Voyager calls * - ID is also used as part of other URNs - * @param {boolean} [allowFetch] If DOM search fails, allow Voyager call to determine profile URN. Be careful about recursion... + * @param {boolean} [allowFetch] If DOM search fails, allow Voyager call to determine profile URN. * @returns {Promise} profile URN ID */ - LinkedinToResumeJson.prototype.getProfileUrnId = async function getProfileUrnId(allowFetch = false) { + LinkedinToResumeJson.prototype.getProfileUrnId = async function getProfileUrnId(allowFetch = true) { + const profileViewUrnPatt = /urn:li:fs_profileView:(.+)$/i; + if (this.profileUrnId && this.scannedPageUrl === this.getUrlWithoutQuery()) { return this.profileUrnId; } - // Try to find in DOM - const urnPatt = /fsd_profile:([A-Za-z0-9-_]+)/g; + // Try to use cache + if (this.profileParseSummary && this.profileParseSummary.parseSuccess) { + const profileDb = buildDbFromLiSchema(this.profileParseSummary.profileObj); + this.profileUrnId = profileDb.tableOfContents['entityUrn'].match(profileViewUrnPatt)[1]; + return this.profileUrnId; + } + + const endpoint = _voyagerEndpoints.fullProfileView; + // Make a new API call to get ID - be wary of recursive calls + if (allowFetch && !endpoint.includes(`{profileUrnId}`)) { + const fullProfileView = await this.voyagerFetch(endpoint); + const profileDb = buildDbFromLiSchema(fullProfileView); + this.profileUrnId = profileDb.tableOfContents['entityUrn'].match(profileViewUrnPatt)[1]; + return this.profileUrnId; + } + this.debugConsole.warn('Could not scrape profileUrnId from cache, but fetch is disallowed. Might be using a stale ID!'); + + // Try to find in DOM, as last resort + const urnPatt = /miniprofiles\/([A-Za-z0-9-_]+)/g; const matches = document.body.innerHTML.match(urnPatt); if (matches && matches.length > 1) { // eslint-disable-next-line prettier/prettier @@ -1449,15 +1471,6 @@ window.LinkedinToResumeJson = (() => { return this.profileUrnId; } - if (allowFetch) { - const fullProfileView = await this.voyagerFetch(_voyagerEndpoints.fullProfileView); - const profileDb = buildDbFromLiSchema(fullProfileView); - const profileViewUrnPatt = /urn:li:fs_profileView:(.+)$/i; - this.profileUrnId = profileDb.tableOfContents['entityUrn'].match(profileViewUrnPatt)[1]; - } else { - this.debugConsole.warn('Could not scrape profileUrnId from DOM, but fetch is disallowed. Might be using a stale ID!'); - } - return this.profileUrnId; };