mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2025-11-15 01:01:43 +10:00
fix(parser): make reactive-resume v3 parser more lenient with validation
This commit is contained in:
@ -59,13 +59,15 @@ export class ReactiveResumeV3Parser implements Parser<Json, ReactiveResumeV3> {
|
|||||||
const result = JSON.parse(JSON.stringify(defaultResumeData)) as ResumeData;
|
const result = JSON.parse(JSON.stringify(defaultResumeData)) as ResumeData;
|
||||||
|
|
||||||
// Basics
|
// Basics
|
||||||
result.basics.name = data.basics.name;
|
result.basics.name = data.basics.name ?? "";
|
||||||
result.basics.email = data.basics.email;
|
result.basics.email = data.basics.email;
|
||||||
result.basics.phone = data.basics.phone;
|
result.basics.phone = data.basics.phone ?? "";
|
||||||
result.basics.headline = data.basics.headline;
|
result.basics.headline = data.basics.headline ?? "";
|
||||||
result.basics.location = data.basics.location.address;
|
result.basics.location = data.basics.location.address ?? "";
|
||||||
result.sections.summary.content = data.basics.summary;
|
result.sections.summary.content =
|
||||||
result.basics.picture.url = isUrl(data.basics.photo.url) ? data.basics.photo.url : "";
|
(typeof data.basics.summary === "string" ? data.basics.summary : data.basics.summary?.body) ??
|
||||||
|
"";
|
||||||
|
result.basics.picture.url = isUrl(data.basics.photo.url) ? data.basics.photo.url! : "";
|
||||||
|
|
||||||
// Profiles
|
// Profiles
|
||||||
if (data.basics.profiles) {
|
if (data.basics.profiles) {
|
||||||
@ -73,10 +75,10 @@ export class ReactiveResumeV3Parser implements Parser<Json, ReactiveResumeV3> {
|
|||||||
result.sections.profiles.items.push({
|
result.sections.profiles.items.push({
|
||||||
...defaultProfile,
|
...defaultProfile,
|
||||||
id: createId(),
|
id: createId(),
|
||||||
network: profile.network,
|
network: profile.network ?? "",
|
||||||
username: profile.username,
|
username: profile.username ?? "",
|
||||||
icon: profile.network.toLocaleLowerCase(),
|
icon: (profile.network ?? "").toLocaleLowerCase(),
|
||||||
url: { ...defaultProfile.url, href: isUrl(profile.url) ? profile.url : "" },
|
url: { ...defaultProfile.url, href: isUrl(profile.url) ? profile.url! : "" },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,14 +86,16 @@ export class ReactiveResumeV3Parser implements Parser<Json, ReactiveResumeV3> {
|
|||||||
// Work
|
// Work
|
||||||
if (data.sections.work.items) {
|
if (data.sections.work.items) {
|
||||||
for (const work of data.sections.work.items) {
|
for (const work of data.sections.work.items) {
|
||||||
|
if (!work) continue;
|
||||||
|
|
||||||
result.sections.experience.items.push({
|
result.sections.experience.items.push({
|
||||||
...defaultExperience,
|
...defaultExperience,
|
||||||
id: createId(),
|
id: createId(),
|
||||||
company: work.name,
|
company: work.name ?? "",
|
||||||
position: work.position,
|
position: work.position ?? "",
|
||||||
summary: work.summary,
|
summary: work.summary ?? "",
|
||||||
date: `${work.date.start} - ${work.date.end}`,
|
date: `${work.date?.start} - ${work.date?.end}`,
|
||||||
url: { ...defaultExperience.url, href: isUrl(work.url) ? work.url : "" },
|
url: { ...defaultExperience.url, href: isUrl(work.url) ? work.url! : "" },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,14 +103,16 @@ export class ReactiveResumeV3Parser implements Parser<Json, ReactiveResumeV3> {
|
|||||||
// Awards
|
// Awards
|
||||||
if (data.sections.awards.items) {
|
if (data.sections.awards.items) {
|
||||||
for (const award of data.sections.awards.items) {
|
for (const award of data.sections.awards.items) {
|
||||||
|
if (!award) continue;
|
||||||
|
|
||||||
result.sections.awards.items.push({
|
result.sections.awards.items.push({
|
||||||
...defaultAward,
|
...defaultAward,
|
||||||
id: createId(),
|
id: createId(),
|
||||||
title: award.title,
|
title: award.title ?? "",
|
||||||
awarder: award.awarder,
|
awarder: award.awarder ?? "",
|
||||||
date: award.date,
|
date: award.date ?? "",
|
||||||
summary: award.summary,
|
summary: award.summary ?? "",
|
||||||
url: { ...defaultAward.url, href: isUrl(award.url) ? award.url : "" },
|
url: { ...defaultAward.url, href: isUrl(award.url) ? award.url! : "" },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,13 +120,17 @@ export class ReactiveResumeV3Parser implements Parser<Json, ReactiveResumeV3> {
|
|||||||
// Skills
|
// Skills
|
||||||
if (data.sections.skills.items) {
|
if (data.sections.skills.items) {
|
||||||
for (const skill of data.sections.skills.items) {
|
for (const skill of data.sections.skills.items) {
|
||||||
|
if (!skill) continue;
|
||||||
|
|
||||||
result.sections.skills.items.push({
|
result.sections.skills.items.push({
|
||||||
...defaultSkill,
|
...defaultSkill,
|
||||||
id: createId(),
|
id: createId(),
|
||||||
name: skill.name,
|
name: skill.name ?? "",
|
||||||
level: Math.floor(skill.levelNum / 2),
|
level: Math.floor(skill.levelNum / 2),
|
||||||
description: skill.level,
|
description: skill.level ?? "",
|
||||||
keywords: skill.keywords,
|
keywords: Array.isArray(skill.keywords)
|
||||||
|
? (skill.keywords.filter(Boolean) as string[])
|
||||||
|
: [],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,15 +138,19 @@ export class ReactiveResumeV3Parser implements Parser<Json, ReactiveResumeV3> {
|
|||||||
// Projects
|
// Projects
|
||||||
if (data.sections.projects.items) {
|
if (data.sections.projects.items) {
|
||||||
for (const project of data.sections.projects.items) {
|
for (const project of data.sections.projects.items) {
|
||||||
|
if (!project) continue;
|
||||||
|
|
||||||
result.sections.projects.items.push({
|
result.sections.projects.items.push({
|
||||||
...defaultProject,
|
...defaultProject,
|
||||||
id: createId(),
|
id: createId(),
|
||||||
name: project.name,
|
name: project.name ?? "",
|
||||||
summary: project.summary,
|
summary: project.summary ?? "",
|
||||||
description: project.description,
|
description: project.description ?? "",
|
||||||
date: `${project.date.start} - ${project.date.end}`,
|
date: `${project.date?.start} - ${project.date?.end}`,
|
||||||
keywords: project.keywords,
|
keywords: Array.isArray(project.keywords)
|
||||||
url: { ...defaultProject.url, href: isUrl(project.url) ? project.url : "" },
|
? (project.keywords.filter(Boolean) as string[])
|
||||||
|
: [],
|
||||||
|
url: { ...defaultProject.url, href: isUrl(project.url) ? project.url! : "" },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,16 +158,18 @@ export class ReactiveResumeV3Parser implements Parser<Json, ReactiveResumeV3> {
|
|||||||
// Education
|
// Education
|
||||||
if (data.sections.education.items) {
|
if (data.sections.education.items) {
|
||||||
for (const education of data.sections.education.items) {
|
for (const education of data.sections.education.items) {
|
||||||
|
if (!education) continue;
|
||||||
|
|
||||||
result.sections.education.items.push({
|
result.sections.education.items.push({
|
||||||
...defaultEducation,
|
...defaultEducation,
|
||||||
id: createId(),
|
id: createId(),
|
||||||
institution: education.institution,
|
institution: education.institution ?? "",
|
||||||
studyType: education.degree,
|
studyType: education.degree ?? "",
|
||||||
area: education.area,
|
area: education.area ?? "",
|
||||||
score: education.score,
|
score: education.score ?? "",
|
||||||
summary: education.summary,
|
summary: education.summary ?? "",
|
||||||
date: `${education.date.start} - ${education.date.end}`,
|
date: `${education.date?.start} - ${education.date?.end}`,
|
||||||
url: { ...defaultEducation.url, href: isUrl(education.url) ? education.url : "" },
|
url: { ...defaultEducation.url, href: isUrl(education.url) ? education.url! : "" },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,11 +177,15 @@ export class ReactiveResumeV3Parser implements Parser<Json, ReactiveResumeV3> {
|
|||||||
// Interests
|
// Interests
|
||||||
if (data.sections.interests.items) {
|
if (data.sections.interests.items) {
|
||||||
for (const interest of data.sections.interests.items) {
|
for (const interest of data.sections.interests.items) {
|
||||||
|
if (!interest) continue;
|
||||||
|
|
||||||
result.sections.interests.items.push({
|
result.sections.interests.items.push({
|
||||||
...defaultInterest,
|
...defaultInterest,
|
||||||
id: createId(),
|
id: createId(),
|
||||||
name: interest.name,
|
name: interest.name ?? "",
|
||||||
keywords: interest.keywords,
|
keywords: Array.isArray(interest.keywords)
|
||||||
|
? (interest.keywords.filter(Boolean) as string[])
|
||||||
|
: [],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,11 +193,13 @@ export class ReactiveResumeV3Parser implements Parser<Json, ReactiveResumeV3> {
|
|||||||
// Languages
|
// Languages
|
||||||
if (data.sections.languages.items) {
|
if (data.sections.languages.items) {
|
||||||
for (const language of data.sections.languages.items) {
|
for (const language of data.sections.languages.items) {
|
||||||
|
if (!language) continue;
|
||||||
|
|
||||||
result.sections.languages.items.push({
|
result.sections.languages.items.push({
|
||||||
...defaultLanguage,
|
...defaultLanguage,
|
||||||
id: createId(),
|
id: createId(),
|
||||||
name: language.name,
|
name: language.name ?? "",
|
||||||
description: language.level,
|
description: language.level ?? "",
|
||||||
level: Math.floor(language.levelNum / 2),
|
level: Math.floor(language.levelNum / 2),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -186,14 +208,16 @@ export class ReactiveResumeV3Parser implements Parser<Json, ReactiveResumeV3> {
|
|||||||
// Volunteer
|
// Volunteer
|
||||||
if (data.sections.volunteer.items) {
|
if (data.sections.volunteer.items) {
|
||||||
for (const volunteer of data.sections.volunteer.items) {
|
for (const volunteer of data.sections.volunteer.items) {
|
||||||
|
if (!volunteer) continue;
|
||||||
|
|
||||||
result.sections.volunteer.items.push({
|
result.sections.volunteer.items.push({
|
||||||
...defaultVolunteer,
|
...defaultVolunteer,
|
||||||
id: createId(),
|
id: createId(),
|
||||||
organization: volunteer.organization,
|
organization: volunteer.organization ?? "",
|
||||||
position: volunteer.position,
|
position: volunteer.position ?? "",
|
||||||
summary: volunteer.summary,
|
summary: volunteer.summary ?? "",
|
||||||
date: `${volunteer.date.start} - ${volunteer.date.end}`,
|
date: `${volunteer.date?.start} - ${volunteer.date?.end}`,
|
||||||
url: { ...defaultVolunteer.url, href: isUrl(volunteer.url) ? volunteer.url : "" },
|
url: { ...defaultVolunteer.url, href: isUrl(volunteer.url) ? volunteer.url! : "" },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,12 +225,14 @@ export class ReactiveResumeV3Parser implements Parser<Json, ReactiveResumeV3> {
|
|||||||
// References
|
// References
|
||||||
if (data.sections.references.items) {
|
if (data.sections.references.items) {
|
||||||
for (const reference of data.sections.references.items) {
|
for (const reference of data.sections.references.items) {
|
||||||
|
if (!reference) continue;
|
||||||
|
|
||||||
result.sections.references.items.push({
|
result.sections.references.items.push({
|
||||||
...defaultReference,
|
...defaultReference,
|
||||||
id: createId(),
|
id: createId(),
|
||||||
name: reference.name,
|
name: reference.name ?? "",
|
||||||
summary: reference.summary,
|
summary: reference.summary ?? "",
|
||||||
description: reference.relationship,
|
description: reference.relationship ?? "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,13 +240,15 @@ export class ReactiveResumeV3Parser implements Parser<Json, ReactiveResumeV3> {
|
|||||||
// Publications
|
// Publications
|
||||||
if (data.sections.publications.items) {
|
if (data.sections.publications.items) {
|
||||||
for (const publication of data.sections.publications.items) {
|
for (const publication of data.sections.publications.items) {
|
||||||
|
if (!publication) continue;
|
||||||
|
|
||||||
result.sections.publications.items.push({
|
result.sections.publications.items.push({
|
||||||
...defaultPublication,
|
...defaultPublication,
|
||||||
id: createId(),
|
id: createId(),
|
||||||
name: publication.name,
|
name: publication.name ?? "",
|
||||||
summary: publication.summary,
|
summary: publication.summary ?? "",
|
||||||
date: publication.date,
|
date: publication.date ?? "",
|
||||||
url: { ...defaultPublication.url, href: isUrl(publication.url) ? publication.url : "" },
|
url: { ...defaultPublication.url, href: isUrl(publication.url) ? publication.url! : "" },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -228,16 +256,18 @@ export class ReactiveResumeV3Parser implements Parser<Json, ReactiveResumeV3> {
|
|||||||
// Certifications
|
// Certifications
|
||||||
if (data.sections.certifications.items) {
|
if (data.sections.certifications.items) {
|
||||||
for (const certification of data.sections.certifications.items) {
|
for (const certification of data.sections.certifications.items) {
|
||||||
|
if (!certification) continue;
|
||||||
|
|
||||||
result.sections.certifications.items.push({
|
result.sections.certifications.items.push({
|
||||||
...defaultCertification,
|
...defaultCertification,
|
||||||
id: createId(),
|
id: createId(),
|
||||||
name: certification.name,
|
name: certification.name ?? "",
|
||||||
issuer: certification.issuer,
|
issuer: certification.issuer ?? "",
|
||||||
summary: certification.summary,
|
summary: certification.summary ?? "",
|
||||||
date: certification.date,
|
date: certification.date ?? "",
|
||||||
url: {
|
url: {
|
||||||
...defaultCertification.url,
|
...defaultCertification.url,
|
||||||
href: isUrl(certification.url) ? certification.url : "",
|
href: isUrl(certification.url) ? certification.url! : "",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,36 +1,47 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
const dateSchema = z.object({ start: z.string(), end: z.string() });
|
const dateSchema = z
|
||||||
|
.object({ start: z.string().optional(), end: z.string().optional() })
|
||||||
|
.optional();
|
||||||
|
|
||||||
const profileSchema = z.object({
|
const profileSchema = z.object({
|
||||||
id: z.string(),
|
id: z.string().optional(),
|
||||||
url: z.string(),
|
url: z.string().optional(),
|
||||||
network: z.string(),
|
network: z.string().optional(),
|
||||||
username: z.string(),
|
username: z.string().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const basicsSchema = z.object({
|
const basicsSchema = z.object({
|
||||||
name: z.string(),
|
name: z.string().optional(),
|
||||||
email: z.literal("").or(z.string().email()),
|
email: z.literal("").or(z.string().email()),
|
||||||
phone: z.string(),
|
phone: z.string().optional(),
|
||||||
headline: z.string(),
|
headline: z.string().optional(),
|
||||||
summary: z.string(),
|
summary: z
|
||||||
|
.string()
|
||||||
|
.or(
|
||||||
|
z.object({
|
||||||
|
body: z.string().optional(),
|
||||||
|
visible: z.boolean().default(true),
|
||||||
|
heading: z.string().optional(),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.optional(),
|
||||||
birthdate: z.string().optional(),
|
birthdate: z.string().optional(),
|
||||||
website: z.string(),
|
website: z.string().optional(),
|
||||||
profiles: z.array(profileSchema),
|
profiles: z.array(profileSchema),
|
||||||
location: z.object({
|
location: z.object({
|
||||||
address: z.string(),
|
address: z.string().optional(),
|
||||||
postalCode: z.string(),
|
postalCode: z.string().optional(),
|
||||||
city: z.string(),
|
city: z.string().optional(),
|
||||||
country: z.string(),
|
country: z.string().optional(),
|
||||||
region: z.string(),
|
region: z.string().optional(),
|
||||||
}),
|
}),
|
||||||
photo: z.object({
|
photo: z.object({
|
||||||
visible: z.boolean(),
|
visible: z.boolean(),
|
||||||
url: z.string(),
|
url: z.string().optional(),
|
||||||
filters: z.object({
|
filters: z.object({
|
||||||
shape: z.string(),
|
shape: z.string().nullable().optional(),
|
||||||
size: z.number(),
|
size: z.coerce.number(),
|
||||||
border: z.boolean(),
|
border: z.boolean(),
|
||||||
grayscale: z.boolean(),
|
grayscale: z.boolean(),
|
||||||
}),
|
}),
|
||||||
@ -38,122 +49,158 @@ const basicsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const sectionSchema = z.object({
|
const sectionSchema = z.object({
|
||||||
id: z.string(),
|
id: z.string().optional(),
|
||||||
name: z.string(),
|
name: z.string().optional(),
|
||||||
type: z.enum(["basic", "work", "custom"]),
|
type: z.enum(["basic", "work", "custom"]),
|
||||||
columns: z.number().or(z.null()),
|
columns: z.coerce.number().or(z.null()).default(1),
|
||||||
visible: z.boolean(),
|
visible: z.boolean(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const workSchema = z.object({
|
const workSchema = z
|
||||||
id: z.string(),
|
.object({
|
||||||
url: z.string(),
|
id: z.string().optional(),
|
||||||
date: dateSchema,
|
url: z.string().optional(),
|
||||||
name: z.string(),
|
date: dateSchema,
|
||||||
position: z.string(),
|
name: z.string().optional(),
|
||||||
summary: z.string(),
|
position: z.string().optional(),
|
||||||
});
|
summary: z.string().nullable().optional(),
|
||||||
|
})
|
||||||
|
.nullable();
|
||||||
|
|
||||||
const awardSchema = z.object({
|
const awardSchema = z
|
||||||
id: z.string(),
|
.object({
|
||||||
url: z.string(),
|
id: z.string().optional(),
|
||||||
date: z.string(),
|
url: z.string().optional(),
|
||||||
title: z.string(),
|
date: z.string().optional(),
|
||||||
awarder: z.string(),
|
title: z.string().optional(),
|
||||||
summary: z.string(),
|
awarder: z.string().optional(),
|
||||||
});
|
summary: z.string().nullable().optional(),
|
||||||
|
})
|
||||||
|
.nullable();
|
||||||
|
|
||||||
const skillSchema = z.object({
|
const skillSchema = z
|
||||||
id: z.string(),
|
.object({
|
||||||
name: z.string(),
|
id: z.string().optional(),
|
||||||
level: z.string(),
|
name: z.string().optional(),
|
||||||
keywords: z.array(z.string()),
|
level: z.coerce.string().optional(),
|
||||||
levelNum: z.number(),
|
keywords: z.array(z.string().nullable()).optional(),
|
||||||
});
|
levelNum: z.coerce.number(),
|
||||||
|
})
|
||||||
|
.nullable();
|
||||||
|
|
||||||
const projectSchema = z.object({
|
const projectSchema = z
|
||||||
id: z.string(),
|
.object({
|
||||||
url: z.string(),
|
id: z.string().optional(),
|
||||||
date: dateSchema,
|
url: z.string().optional(),
|
||||||
name: z.string(),
|
date: dateSchema,
|
||||||
summary: z.string(),
|
name: z.string().optional(),
|
||||||
keywords: z.array(z.string()),
|
summary: z.string().nullable().optional(),
|
||||||
description: z.string(),
|
keywords: z.array(z.string().nullable()).optional(),
|
||||||
});
|
description: z.string().optional(),
|
||||||
|
})
|
||||||
|
.nullable();
|
||||||
|
|
||||||
const educationSchema = z.object({
|
const educationSchema = z
|
||||||
id: z.string(),
|
.object({
|
||||||
url: z.string(),
|
id: z.string().optional(),
|
||||||
area: z.string(),
|
url: z.string().optional(),
|
||||||
date: dateSchema,
|
area: z.string().optional(),
|
||||||
score: z.string(),
|
date: dateSchema,
|
||||||
degree: z.string(),
|
score: z.string().optional(),
|
||||||
courses: z.array(z.string()),
|
degree: z.string().optional(),
|
||||||
summary: z.string(),
|
courses: z.array(z.string().nullable()).optional(),
|
||||||
institution: z.string(),
|
summary: z.string().nullable().optional(),
|
||||||
});
|
institution: z.string().optional(),
|
||||||
|
})
|
||||||
|
.nullable();
|
||||||
|
|
||||||
const interestSchema = z.object({
|
const interestSchema = z
|
||||||
id: z.string(),
|
.object({
|
||||||
name: z.string(),
|
id: z.string().optional(),
|
||||||
keywords: z.array(z.string()),
|
name: z.string().optional(),
|
||||||
});
|
keywords: z.array(z.string().nullable()).optional(),
|
||||||
|
})
|
||||||
|
.nullable();
|
||||||
|
|
||||||
const languageSchema = z.object({
|
const languageSchema = z
|
||||||
id: z.string(),
|
.object({
|
||||||
name: z.string(),
|
id: z.string().optional(),
|
||||||
level: z.string(),
|
name: z.string().optional(),
|
||||||
levelNum: z.number(),
|
level: z.string().optional(),
|
||||||
});
|
levelNum: z.coerce.number(),
|
||||||
|
})
|
||||||
|
.nullable();
|
||||||
|
|
||||||
const volunteerSchema = z.object({
|
const volunteerSchema = z
|
||||||
id: z.string(),
|
.object({
|
||||||
organization: z.string(),
|
id: z.string().optional(),
|
||||||
position: z.string(),
|
organization: z.string().optional(),
|
||||||
date: dateSchema,
|
position: z.string().optional(),
|
||||||
url: z.string(),
|
date: dateSchema,
|
||||||
summary: z.string(),
|
url: z.string().optional(),
|
||||||
});
|
summary: z.string().nullable().optional(),
|
||||||
|
})
|
||||||
|
.nullable();
|
||||||
|
|
||||||
const referenceSchema = z.object({
|
const referenceSchema = z
|
||||||
id: z.string(),
|
.object({
|
||||||
name: z.string(),
|
id: z.string().optional(),
|
||||||
email: z.string(),
|
name: z.string().optional(),
|
||||||
phone: z.string(),
|
email: z.string().optional(),
|
||||||
summary: z.string(),
|
phone: z.string().optional(),
|
||||||
relationship: z.string(),
|
summary: z.string().nullable().optional(),
|
||||||
});
|
relationship: z.string().optional(),
|
||||||
|
})
|
||||||
|
.nullable();
|
||||||
|
|
||||||
const publicationSchema = z.object({
|
const publicationSchema = z
|
||||||
id: z.string(),
|
.object({
|
||||||
url: z.string(),
|
id: z.string().optional(),
|
||||||
date: z.string(),
|
url: z.string().optional(),
|
||||||
name: z.string(),
|
date: z.string().optional(),
|
||||||
publisher: z.string(),
|
name: z.string().optional(),
|
||||||
summary: z.string(),
|
publisher: z.string().optional(),
|
||||||
});
|
summary: z.string().nullable().optional(),
|
||||||
|
})
|
||||||
|
.nullable();
|
||||||
|
|
||||||
const certificationSchema = z.object({
|
const certificationSchema = z
|
||||||
id: z.string(),
|
.object({
|
||||||
url: z.string(),
|
id: z.string().optional(),
|
||||||
date: z.string(),
|
url: z.string().optional(),
|
||||||
name: z.string(),
|
date: z.string().optional(),
|
||||||
issuer: z.string(),
|
name: z.string().optional(),
|
||||||
summary: z.string(),
|
issuer: z.string().optional(),
|
||||||
});
|
summary: z.string().nullable().optional(),
|
||||||
|
})
|
||||||
|
.nullable();
|
||||||
|
|
||||||
const metadataSchema = z.object({
|
const metadataSchema = z
|
||||||
css: z.object({ value: z.string(), visible: z.boolean() }),
|
.object({
|
||||||
date: z.object({ format: z.string() }),
|
css: z.object({ value: z.string().optional(), visible: z.boolean() }).optional(),
|
||||||
theme: z.object({ text: z.string(), primary: z.string(), background: z.string() }),
|
date: z.object({ format: z.string().optional() }).optional(),
|
||||||
layout: z.array(z.array(z.array(z.string()))),
|
theme: z
|
||||||
locale: z.string().optional(),
|
.object({
|
||||||
template: z.string(),
|
text: z.string().optional(),
|
||||||
typography: z.object({
|
primary: z.string().optional(),
|
||||||
size: z.object({ body: z.number(), heading: z.number() }),
|
background: z.string().optional(),
|
||||||
family: z.object({ body: z.string(), heading: z.string() }),
|
})
|
||||||
}),
|
.optional(),
|
||||||
});
|
layout: z.array(z.array(z.array(z.string().nullable()))).optional(),
|
||||||
|
locale: z.string().optional(),
|
||||||
|
template: z.string().optional(),
|
||||||
|
typography: z
|
||||||
|
.object({
|
||||||
|
size: z
|
||||||
|
.object({ body: z.coerce.number().optional(), heading: z.coerce.number().optional() })
|
||||||
|
.optional(),
|
||||||
|
family: z
|
||||||
|
.object({ body: z.string().optional(), heading: z.string().optional() })
|
||||||
|
.optional(),
|
||||||
|
})
|
||||||
|
.optional(),
|
||||||
|
})
|
||||||
|
.optional();
|
||||||
|
|
||||||
export const reactiveResumeV3Schema = z.object({
|
export const reactiveResumeV3Schema = z.object({
|
||||||
public: z.boolean(),
|
public: z.boolean(),
|
||||||
|
|||||||
@ -9,7 +9,9 @@ export const getInitials = (name: string) => {
|
|||||||
return ((initials.shift()?.[1] || "") + (initials.pop()?.[1] || "")).toUpperCase();
|
return ((initials.shift()?.[1] || "") + (initials.pop()?.[1] || "")).toUpperCase();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isUrl = (string: string) => {
|
export const isUrl = (string: string | null | undefined) => {
|
||||||
|
if (!string) return false;
|
||||||
|
|
||||||
const urlRegex = /https?:\/\/[^ \n]+/i;
|
const urlRegex = /https?:\/\/[^ \n]+/i;
|
||||||
|
|
||||||
return urlRegex.test(string);
|
return urlRegex.test(string);
|
||||||
|
|||||||
Reference in New Issue
Block a user