Skip to content

Commit

Permalink
Merge pull request #66 from housamz/housamz-matching-resumejson
Browse files Browse the repository at this point in the history
Update to match the latest Resume.JSON format
  • Loading branch information
JMPerez authored Aug 22, 2024
2 parents f7d1c54 + d4474ea commit 5d8b017
Show file tree
Hide file tree
Showing 2 changed files with 204 additions and 20 deletions.
126 changes: 111 additions & 15 deletions src/js/converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@ interface Output {
references?: object;
skills?: object;
work?: object;
volunteer?: object;
awards?: object;
certificates: object;
}

interface Position {
company: string;
name: string;
position: string;
website: string;
url: string;
startDate: string;
summary: string;
highlights: Array<string>;
Expand All @@ -25,10 +28,11 @@ interface Position {

interface Education {
institution: string;
url?: string;
area: string;
studyType: string;
startDate: string;
gpa: string;
score: string;
courses: Array<string>;
endDate?: string;
}
Expand All @@ -47,6 +51,7 @@ class LinkedInToJsonResume {
"volunteer",
"education",
"awards",
"certificates",
"publications",
"skills",
"languages",
Expand All @@ -72,27 +77,44 @@ class LinkedInToJsonResume {
processProfile(source) {
this.target.basics = this.target.basics || {};

const ccItem = CountryCodes.find((item) => item.name === source.country);
// Splitting the address into city, region and country
// and trimming the values
// example: "Dublin, Leinster, Ireland" => ["Dublin", "Leinster", "Ireland"]
const addressArray = source.geoLocation
.split(",")
.map((item) => item.trim());

const ccItem = CountryCodes.find(
(item) => item.name === addressArray[addressArray.length - 1]
);
let countryCode = "";
if (ccItem) {
countryCode = ccItem["alpha-2"];
}

// Extracting the URL from the LinkedIn profile
// this regex will match the first URL in the format [NETWORK:URL]
// This regex will remove the network part and extract the URL
// it applies for https and http URLs
// e.g. [Twitter:https://twitter.com/housamz] will return https://twitter.com/housamz
const websiteRegex = /\[([A-Z]+):(https?:\/\/[^\s,\]]+)/;

this._extend(this.target.basics, {
name: `${source.firstName} ${source.lastName}`,
label: source.headline,
picture: "",
image: "",
email: "",
website: source.websites
? source.websites.split(",")[0].split(":").slice(1).join(":")
phone: "",
url: source.websites
? source.websites.match(websiteRegex)[2]
: "",
summary: source.summary,
location: {
address: source.address,
postalCode: source.zipCode,
city: source.location ? source.location.name : "",
city: source.geoLocation ? addressArray[0] : "",
countryCode: countryCode,
region: "",
region: addressArray[1],
},
profiles: source.twitterHandles
? [
Expand All @@ -114,16 +136,20 @@ class LinkedInToJsonResume {
processPosition(source) {
function processPosition(position) {
let object = <Position>{
company: position.companyName,
name: position.companyName,
position: position.title || "",
website: "",
url: "",
startDate: `${position.startDate}`,
endDate: "",
summary: position.description,
highlights: [],
};

// ensure the end date is after the start date directly
if (position.endDate) {
object.endDate = `${position.endDate}`;
} else {
delete object.endDate;
}

return object;
Expand All @@ -136,15 +162,20 @@ class LinkedInToJsonResume {
function processEducation(education) {
let object = <Education>{
institution: education.schoolName,
url: "",
area: "",
studyType: education.degree,
startDate: `${education.startDate}`,
gpa: "",
endDate: "",
score: "",
courses: [],
};

// ensure the end date is after the start date directly
if (education.endDate) {
object.endDate = `${education.endDate}`;
} else {
delete object.endDate;
}

return object;
Expand Down Expand Up @@ -192,9 +223,11 @@ class LinkedInToJsonResume {
processProjects(projects) {
this.target.projects = projects.map((project) => ({
...{
name: project.title,
name: project.name,
startDate: `${project.startDate}`,
summary: project.description,
endDate: project.endDate ? `${project.endDate}` : "",
description: project.description,
highlights: project.highlights,
url: project.url,
},
...(project.endDate ? { endDate: `${project.endDate}` } : {}),
Expand All @@ -206,7 +239,7 @@ class LinkedInToJsonResume {
name: publication.name,
publisher: publication.publisher,
releaseDate: publication.date,
website: publication.url,
url: publication.url,
summary: publication.description,
}));
}
Expand All @@ -216,6 +249,69 @@ class LinkedInToJsonResume {
phone: number.number,
});
}

processAwards(awards) {
this.target.awards = awards.map((award) => ({
...{
title: award.title,
date: `${award.date}`,
awarder: award.awarder,
summary: award.summary,
},
}));
}

processCertificates(certificates) {
this.target.certificates = certificates.map((certificate) => ({
...{
name: certificate.name,
date: `${certificate.date}`,
issuer: certificate.issuer,
url: certificate.url,
},
}));
}

processEndorsements(endorsements) {
// This will update the level in this.target.skills
// according to how many endorsements the skill has
const processedSkills = new Set<string>();
this.target.skills.map((skill) => {
endorsements.filter((endorsement) => {
if (endorsement.name === skill.name) {
skill.level = endorsement.level;
processedSkills.add(skill.name);
}
});
});

// This will add the skills that have endorsements but
// are not in the skills array
endorsements.forEach((endorsement) => {
if (!processedSkills.has(endorsement.name)) {
this.target.skills.push({ ...endorsement, keywords: [] });
processedSkills.add(endorsement.name);
}
});

// Sort the skills by level
this.target.skills.sort((a, b) => {
return b.level - a.level;
});
}

processFollows(interests) {
if (!this.target.interests) {
this.target.interests = [];
}
interests.forEach((interest) => {
if (
this.target.interests &&
this.target.interests.filter((i) => i.name === interest).length === 0
)
this.target.interests.push({... interest});
});
}
}

export default LinkedInToJsonResume;
98 changes: 93 additions & 5 deletions src/js/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,17 @@ function fileSelectHandler(e) {
};

getEntries(file, (entries) => {
// Ensuring that "Profile.csv" is the first file in the zip
// Solving the phone number being processed before the profile
// Find the index of "Profile.csv", move it to the beginning
const profileIndex = entries.findIndex(
(entry) => entry.filename === "Profile.csv"
);
if (profileIndex !== -1) {
const [profileEntry] = entries.splice(profileIndex, 1);
entries.unshift(profileEntry);
}

const promises = entries.map((entry) => {
switch (true) {
case entry.filename.indexOf("Skills.csv") !== -1:
Expand Down Expand Up @@ -160,7 +171,7 @@ function fileSelectHandler(e) {
return;
});

case entry.filename.indexOf("Recommendations Received.csv") !== -1:
case entry.filename.indexOf("Recommendations_Received.csv") !== -1:
return readEntryContents(entry).then((contents) => {
const elements = csvToArray(contents);
const recommendations = elements
Expand Down Expand Up @@ -207,7 +218,9 @@ function fileSelectHandler(e) {
return readEntryContents(entry).then((contents) => {
const elements = csvToArray(contents, "\t"); // yes, recommendations use tab-delimiter
const email = elements
.slice(1, elements.length - 1)
.flat()
.slice(1)
.map(elem => (elem as string).split(","))
.map((elem) => ({
address: elem[0],
status: elem[1],
Expand Down Expand Up @@ -239,13 +252,14 @@ function fileSelectHandler(e) {
const projects = elements
.slice(1, elements.length - 1)
.map((elem) => ({
title: elem[0],
description: elem[1],
url: elem[2],
name: elem[0],
startDate: moment(elem[3]).format("YYYY-MM-DD"),
endDate: elem[4]
? moment(elem[4]).format("YYYY-MM-DD")
: null,
description: elem[1],
highlights: [],
url: elem[2],
}));
linkedinToJsonResume.processProjects(
projects.sort(
Expand Down Expand Up @@ -275,6 +289,7 @@ function fileSelectHandler(e) {

case entry.filename.indexOf("PhoneNumbers.csv") !== -1:
return readEntryContents(entry).then((contents) => {

const elements = csvToArray(contents);
elements.shift();
const elementsWithNumber = elements.filter(
Expand All @@ -291,6 +306,79 @@ function fileSelectHandler(e) {
return;
});

case entry.filename.indexOf("Honors.csv") !== -1:
return readEntryContents(entry).then((contents) => {
const elements = csvToArray(contents);
const awards = elements
.slice(1, elements.length - 1)
.map((elem) => ({
title: elem[0],
date: moment(elem[3]).format("YYYY-MM-DD"),
awarder: "",
summary: elem[1],
}));
linkedinToJsonResume.processAwards(
awards.sort((p1, p2) => -p1.date.localeCompare(p2.date))
);
return;
});

case entry.filename.indexOf("Certifications.csv") !== -1:
return readEntryContents(entry).then((contents) => {
const elements = csvToArray(contents);
const certificates = elements
.slice(1, elements.length - 1)
.map((elem) => ({
name: elem[0],
date: moment(elem[3]).format("YYYY-MM-DD"),
issuer: elem[2],
summary: "",
}));
linkedinToJsonResume.processCertificates(
certificates.sort((p1, p2) => -p1.date.localeCompare(p2.date))
);
return;
});

case entry.filename.indexOf("Endorsement_Received_Info.csv") !== -1:
return readEntryContents(entry).then((contents) => {
const elements = csvToArray(contents);

// increment the endorsement count every time the name is found
const endorsements: {name: string; level: number}[] = [];
(elements as [])
.slice(1, elements.length - 1)
.forEach((elem) => {
const current = endorsements.find((endorsement) => endorsement.name === elem[1]);
if (current) {
current.level += 1;
} else {
endorsements.push({
name: elem[1],
level: 1,
});
}
}
);
linkedinToJsonResume.processEndorsements(endorsements);
return;
});

case entry.filename.indexOf("Causes You Care About.csv") !== -1:
case entry.filename.indexOf("Company Follows.csv") !== -1:
case entry.filename.indexOf("Hashtag_Follows.csv") !== -1:
return readEntryContents(entry).then((contents) => {
const elements = csvToArray(contents);
const interests = elements
.slice(1, elements.length - 1)
.map((elem) => ({
name: elem[0],
keywords: [],
}));
linkedinToJsonResume.processFollows(interests);
return;
});

default:
return Promise.resolve([]);
}
Expand Down

0 comments on commit 5d8b017

Please sign in to comment.