jsonresume-theme-developer-mono 0.1.0 → 0.2.0

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.
package/src/Resume.jsx CHANGED
@@ -4,346 +4,208 @@ import {
4
4
  Section,
5
5
  SectionTitle,
6
6
  DateRange,
7
+ Badge,
8
+ BadgeList,
7
9
  ContactInfo,
8
10
  Link,
9
- } from '@resume/core';
11
+ safeUrl,
12
+ } from '@jsonresume/core';
10
13
 
11
14
  const Layout = styled.div`
12
15
  max-width: 900px;
13
16
  margin: 0 auto;
14
- padding: 60px 50px;
15
- background: #ffffff;
16
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI',
17
- sans-serif;
17
+ padding: 40px 32px;
18
+ background: white;
19
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
18
20
  color: #1f2937;
19
21
  line-height: 1.7;
22
+ font-size: 15px;
20
23
 
21
24
  @media print {
22
- padding: 40px;
23
- }
24
-
25
- @media (max-width: 640px) {
26
- padding: 40px 20px;
25
+ padding: 24px;
27
26
  }
28
27
  `;
29
28
 
30
29
  const Header = styled.header`
31
- margin-bottom: 48px;
32
- padding-bottom: 24px;
33
- border-bottom: 3px solid #2563eb;
30
+ margin-bottom: 40px;
31
+ border-bottom: 2px solid #e5e7eb;
32
+ padding-bottom: 32px;
34
33
  `;
35
34
 
36
35
  const Name = styled.h1`
37
- font-size: 48px;
36
+ font-family: 'JetBrains Mono', monospace;
37
+ font-size: 36px;
38
38
  font-weight: 700;
39
- font-family: 'JetBrains Mono', 'Courier New', monospace;
39
+ margin: 0 0 8px 0;
40
40
  color: #111827;
41
- margin: 0 0 12px 0;
42
- letter-spacing: -1px;
41
+ letter-spacing: -0.5px;
43
42
  `;
44
43
 
45
- const Label = styled.p`
46
- font-size: 18px;
47
- font-weight: 500;
44
+ const Label = styled.div`
48
45
  font-family: 'JetBrains Mono', monospace;
46
+ font-size: 16px;
49
47
  color: #2563eb;
50
- margin: 0 0 20px 0;
51
- letter-spacing: 0.5px;
48
+ font-weight: 600;
49
+ margin-bottom: 16px;
52
50
  `;
53
51
 
54
- const StyledContactInfo = styled(ContactInfo)`
55
- font-size: 15px;
52
+ const ContactWrapper = styled.div`
53
+ display: flex;
54
+ flex-wrap: wrap;
55
+ gap: 16px;
56
+ font-size: 14px;
56
57
  color: #6b7280;
57
- margin-bottom: 20px;
58
-
59
- a {
60
- font-size: 15px;
61
- color: #2563eb;
62
- text-decoration: none;
63
- font-family: 'JetBrains Mono', monospace;
58
+ `;
64
59
 
65
- &:hover {
66
- text-decoration: underline;
67
- }
68
- }
60
+ const SummarySection = styled(Section)`
61
+ margin-bottom: 40px;
69
62
  `;
70
63
 
71
- const Summary = styled.p`
72
- font-size: 16px;
73
- line-height: 1.8;
64
+ const SummaryText = styled.p`
65
+ margin: 0;
66
+ font-size: 15px;
67
+ line-height: 1.7;
74
68
  color: #374151;
75
- margin: 20px 0 0 0;
76
- max-width: 750px;
77
69
  `;
78
70
 
79
- const StyledSection = styled(Section)`
80
- margin-bottom: 48px;
71
+ const MainSection = styled(Section)`
72
+ margin-bottom: 40px;
81
73
  `;
82
74
 
83
- const StyledSectionTitle = styled(SectionTitle)`
84
- font-size: 20px;
85
- font-weight: 700;
75
+ const MainSectionTitle = styled(SectionTitle)`
86
76
  font-family: 'JetBrains Mono', monospace;
87
- color: #111827;
88
- margin: 0 0 24px 0;
77
+ font-size: 14px;
78
+ font-weight: 700;
79
+ color: #6b7280;
80
+ margin: 0 0 20px 0;
89
81
  text-transform: uppercase;
90
82
  letter-spacing: 1px;
91
- padding: 8px 0;
92
- border-bottom: 2px solid #e5e7eb;
93
- display: inline-block;
94
- min-width: 200px;
95
-
96
- &::before {
97
- content: '# ';
98
- color: #2563eb;
99
- }
100
83
  `;
101
84
 
102
85
  const WorkItem = styled.div`
103
- margin-bottom: 36px;
104
- padding-left: 20px;
105
- border-left: 3px solid #e5e7eb;
86
+ margin-bottom: 32px;
87
+ padding-bottom: 32px;
88
+ border-bottom: 1px solid #f3f4f6;
106
89
 
107
90
  &:last-child {
91
+ border-bottom: none;
108
92
  margin-bottom: 0;
109
- }
110
-
111
- &:hover {
112
- border-left-color: #2563eb;
93
+ padding-bottom: 0;
113
94
  }
114
95
  `;
115
96
 
116
97
  const WorkHeader = styled.div`
117
- margin-bottom: 12px;
118
- `;
119
-
120
- const WorkTitle = styled.div`
121
98
  display: flex;
122
99
  justify-content: space-between;
123
100
  align-items: baseline;
124
- flex-wrap: wrap;
125
- gap: 12px;
126
101
  margin-bottom: 8px;
102
+ flex-wrap: wrap;
103
+ gap: 8px;
127
104
  `;
128
105
 
129
- const Position = styled.h3`
106
+ const WorkTitle = styled.h3`
107
+ font-family: 'JetBrains Mono', monospace;
130
108
  font-size: 18px;
131
109
  font-weight: 600;
132
- font-family: 'JetBrains Mono', monospace;
133
- color: #111827;
134
110
  margin: 0;
111
+ color: #111827;
135
112
  `;
136
113
 
137
- const Company = styled.div`
138
- font-size: 16px;
114
+ const WorkMeta = styled.div`
115
+ font-family: 'JetBrains Mono', monospace;
116
+ font-size: 13px;
117
+ color: #6b7280;
139
118
  font-weight: 500;
140
- color: #2563eb;
141
- margin-top: 4px;
142
119
  `;
143
120
 
144
- const StyledDateRange = styled(DateRange)`
145
- font-size: 14px;
146
- font-family: 'JetBrains Mono', monospace;
147
- color: #6b7280;
121
+ const WorkCompany = styled.div`
122
+ font-size: 15px;
123
+ color: #2563eb;
124
+ font-weight: 600;
125
+ margin-bottom: 8px;
148
126
  `;
149
127
 
150
- const WorkSummary = styled.p`
151
- margin: 12px 0;
152
- color: #4b5563;
153
- line-height: 1.7;
128
+ const WorkDescription = styled.p`
154
129
  font-size: 15px;
130
+ line-height: 1.7;
131
+ margin: 12px 0;
132
+ color: #374151;
155
133
  `;
156
134
 
157
- const HighlightsList = styled.ul`
135
+ const WorkHighlights = styled.ul`
158
136
  margin: 12px 0 0 0;
159
137
  padding-left: 20px;
160
138
  list-style: none;
161
139
 
162
140
  li {
163
- position: relative;
164
141
  margin-bottom: 8px;
165
- padding-left: 0;
142
+ font-size: 15px;
143
+ line-height: 1.6;
166
144
  color: #374151;
167
- line-height: 1.7;
145
+ position: relative;
146
+ padding-left: 12px;
168
147
 
169
148
  &::before {
170
149
  content: '→';
171
150
  position: absolute;
172
- left: -20px;
151
+ left: 0;
173
152
  color: #2563eb;
174
- font-weight: bold;
153
+ font-weight: 600;
175
154
  }
176
155
  }
177
156
  `;
178
157
 
179
- const EducationItem = styled.div`
180
- margin-bottom: 28px;
181
- padding: 20px;
182
- background: #f9fafb;
183
- border-left: 3px solid #2563eb;
184
- border-radius: 2px;
185
-
186
- &:last-child {
187
- margin-bottom: 0;
188
- }
189
- `;
190
-
191
- const EducationHeader = styled.div`
192
- display: flex;
193
- justify-content: space-between;
194
- align-items: baseline;
195
- flex-wrap: wrap;
196
- gap: 8px;
197
- margin-bottom: 8px;
198
- `;
199
-
200
- const Degree = styled.h3`
201
- font-size: 17px;
202
- font-weight: 600;
203
- font-family: 'JetBrains Mono', monospace;
204
- color: #111827;
205
- margin: 0;
206
- `;
207
-
208
- const Institution = styled.div`
209
- font-size: 15px;
210
- color: #6b7280;
211
- margin-top: 4px;
212
- `;
213
-
214
- const StudyType = styled.div`
215
- font-size: 14px;
216
- color: #2563eb;
217
- margin-top: 4px;
218
- `;
219
-
220
158
  const SkillsGrid = styled.div`
221
159
  display: grid;
222
- grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
223
- gap: 16px;
160
+ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
161
+ gap: 24px;
224
162
  `;
225
163
 
226
- const SkillCard = styled.div`
227
- padding: 16px;
228
- background: #f9fafb;
229
- border: 1px solid #e5e7eb;
230
- border-radius: 2px;
231
- transition: all 0.2s ease;
164
+ const SkillItem = styled.div`
165
+ margin-bottom: 16px;
232
166
 
233
- &:hover {
234
- border-color: #2563eb;
235
- background: #eff6ff;
167
+ &:last-child {
168
+ margin-bottom: 0;
236
169
  }
237
170
  `;
238
171
 
239
172
  const SkillName = styled.h4`
240
- font-size: 15px;
241
- font-weight: 600;
242
173
  font-family: 'JetBrains Mono', monospace;
243
- color: #111827;
174
+ font-size: 13px;
175
+ font-weight: 700;
244
176
  margin: 0 0 10px 0;
177
+ color: #2563eb;
178
+ text-transform: uppercase;
179
+ letter-spacing: 0.5px;
245
180
  `;
246
181
 
247
- const KeywordList = styled.div`
182
+ const SkillCodeBlock = styled.div`
183
+ font-family: 'JetBrains Mono', monospace;
248
184
  font-size: 13px;
249
- color: #6b7280;
185
+ background: #f9fafb;
186
+ padding: 12px;
187
+ border-radius: 4px;
188
+ border-left: 3px solid #2563eb;
250
189
  line-height: 1.6;
251
- `;
252
-
253
- const ProjectItem = styled.div`
254
- margin-bottom: 32px;
255
- padding-bottom: 32px;
256
- border-bottom: 1px solid #e5e7eb;
257
-
258
- &:last-child {
259
- border-bottom: none;
260
- padding-bottom: 0;
261
- margin-bottom: 0;
262
- }
263
- `;
264
-
265
- const ProjectHeader = styled.div`
266
- margin-bottom: 12px;
267
- `;
268
-
269
- const ProjectName = styled.h3`
270
- font-size: 17px;
271
- font-weight: 600;
272
- font-family: 'JetBrains Mono', monospace;
273
- color: #111827;
274
- margin: 0 0 8px 0;
275
- `;
276
-
277
- const ProjectDescription = styled.p`
278
- font-size: 15px;
279
190
  color: #4b5563;
280
- line-height: 1.7;
281
- margin: 0;
282
- `;
283
-
284
- const ProjectHighlights = styled.ul`
285
- margin: 12px 0 0 0;
286
- padding-left: 20px;
287
- list-style: none;
288
-
289
- li {
290
- position: relative;
291
- margin-bottom: 6px;
292
- padding-left: 0;
293
- color: #4b5563;
294
- font-size: 14px;
295
-
296
- &::before {
297
- content: '•';
298
- position: absolute;
299
- left: -20px;
300
- color: #2563eb;
301
- }
302
- }
303
191
  `;
304
192
 
305
193
  const SimpleList = styled.div`
306
194
  display: grid;
307
- grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
195
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
308
196
  gap: 16px;
309
197
  `;
310
198
 
311
199
  const SimpleItem = styled.div`
312
- padding: 16px;
313
- background: #f9fafb;
314
- border-left: 2px solid #2563eb;
315
- border-radius: 2px;
316
- `;
317
-
318
- const ItemTitle = styled.h4`
319
200
  font-size: 15px;
320
- font-weight: 600;
321
- font-family: 'JetBrains Mono', monospace;
322
- color: #111827;
323
- margin: 0 0 8px 0;
324
- `;
325
-
326
- const ItemMeta = styled.div`
327
- font-size: 13px;
328
- color: #6b7280;
329
- margin-bottom: 6px;
330
- `;
331
-
332
- const ItemDescription = styled.p`
333
- font-size: 14px;
334
- color: #4b5563;
335
- margin: 8px 0 0 0;
336
201
  line-height: 1.6;
337
- `;
202
+ padding-bottom: 16px;
203
+ border-bottom: 1px solid #f3f4f6;
338
204
 
339
- const CodeBlock = styled.pre`
340
- font-family: 'JetBrains Mono', monospace;
341
- font-size: 13px;
342
- color: #1f2937;
343
- background: #f9fafb;
344
- padding: 2px 6px;
345
- border-radius: 2px;
346
- display: inline;
205
+ strong {
206
+ font-weight: 600;
207
+ color: #111827;
208
+ }
347
209
  `;
348
210
 
349
211
  function Resume({ resume }) {
@@ -355,6 +217,7 @@ function Resume({ resume }) {
355
217
  projects = [],
356
218
  volunteer = [],
357
219
  awards = [],
220
+ certificates = [],
358
221
  publications = [],
359
222
  languages = [],
360
223
  interests = [],
@@ -364,229 +227,280 @@ function Resume({ resume }) {
364
227
  return (
365
228
  <Layout>
366
229
  <Header>
367
- <Name>{basics.name}</Name>
230
+ {basics.name && <Name>{basics.name}</Name>}
368
231
  {basics.label && <Label>{basics.label}</Label>}
369
- <StyledContactInfo basics={basics} />
370
- {basics.summary && <Summary>{basics.summary}</Summary>}
232
+ <ContactWrapper>
233
+ {basics.email && (
234
+ <ContactInfo type="email">{basics.email}</ContactInfo>
235
+ )}
236
+ {basics.phone && (
237
+ <ContactInfo type="phone">{basics.phone}</ContactInfo>
238
+ )}
239
+ {basics.location?.city && basics.location?.region && (
240
+ <ContactInfo type="location">
241
+ {basics.location.city}, {basics.location.region}
242
+ </ContactInfo>
243
+ )}
244
+ {basics.url && (
245
+ <ContactInfo type="url">
246
+ <a href={safeUrl(basics.url)}>{basics.url}</a>
247
+ </ContactInfo>
248
+ )}
249
+ {basics.profiles?.map((profile, index) => (
250
+ <ContactInfo key={index} type="social">
251
+ <a href={safeUrl(profile.url)}>{profile.network}</a>
252
+ </ContactInfo>
253
+ ))}
254
+ </ContactWrapper>
371
255
  </Header>
372
256
 
373
- {work && work.length > 0 && (
374
- <StyledSection>
375
- <StyledSectionTitle>Experience</StyledSectionTitle>
257
+ {basics.summary && (
258
+ <SummarySection>
259
+ <SummaryText>{basics.summary}</SummaryText>
260
+ </SummarySection>
261
+ )}
262
+
263
+ {work.length > 0 && (
264
+ <MainSection>
265
+ <MainSectionTitle>Experience</MainSectionTitle>
376
266
  {work.map((job, index) => (
377
267
  <WorkItem key={index}>
378
268
  <WorkHeader>
379
- <WorkTitle>
380
- <div>
381
- <Position>{job.position}</Position>
382
- <Company>{job.name}</Company>
383
- </div>
384
- <StyledDateRange
385
- startDate={job.startDate}
386
- endDate={job.endDate}
387
- />
388
- </WorkTitle>
269
+ <WorkTitle>{job.position || job.name}</WorkTitle>
270
+ <WorkMeta>
271
+ <DateRange startDate={job.startDate} endDate={job.endDate} />
272
+ </WorkMeta>
389
273
  </WorkHeader>
390
- {job.summary && <WorkSummary>{job.summary}</WorkSummary>}
274
+ {job.name && <WorkCompany>{job.name}</WorkCompany>}
275
+ {job.summary && <WorkDescription>{job.summary}</WorkDescription>}
391
276
  {job.highlights && job.highlights.length > 0 && (
392
- <HighlightsList>
277
+ <WorkHighlights>
393
278
  {job.highlights.map((highlight, i) => (
394
- <li
395
- key={i}
396
- dangerouslySetInnerHTML={{ __html: highlight }}
397
- />
279
+ <li key={i}>{highlight}</li>
398
280
  ))}
399
- </HighlightsList>
281
+ </WorkHighlights>
400
282
  )}
401
283
  </WorkItem>
402
284
  ))}
403
- </StyledSection>
285
+ </MainSection>
404
286
  )}
405
287
 
406
- {skills && skills.length > 0 && (
407
- <StyledSection>
408
- <StyledSectionTitle>Skills</StyledSectionTitle>
288
+ {skills.length > 0 && (
289
+ <MainSection>
290
+ <MainSectionTitle>Skills</MainSectionTitle>
409
291
  <SkillsGrid>
410
292
  {skills.map((skill, index) => (
411
- <SkillCard key={index}>
293
+ <SkillItem key={index}>
412
294
  <SkillName>{skill.name}</SkillName>
413
- {skill.keywords && skill.keywords.length > 0 && (
414
- <KeywordList>{skill.keywords.join(' • ')}</KeywordList>
415
- )}
416
- </SkillCard>
295
+ <SkillCodeBlock>{skill.keywords?.join(', ')}</SkillCodeBlock>
296
+ </SkillItem>
417
297
  ))}
418
298
  </SkillsGrid>
419
- </StyledSection>
299
+ </MainSection>
420
300
  )}
421
301
 
422
- {education && education.length > 0 && (
423
- <StyledSection>
424
- <StyledSectionTitle>Education</StyledSectionTitle>
425
- {education.map((edu, index) => (
426
- <EducationItem key={index}>
427
- <EducationHeader>
428
- <div>
429
- <Degree>{edu.area}</Degree>
430
- {edu.studyType && <StudyType>{edu.studyType}</StudyType>}
431
- <Institution>{edu.institution}</Institution>
432
- </div>
433
- <StyledDateRange
434
- startDate={edu.startDate}
435
- endDate={edu.endDate}
436
- />
437
- </EducationHeader>
438
- {edu.score && <ItemMeta>GPA: {edu.score}</ItemMeta>}
439
- {edu.courses && edu.courses.length > 0 && (
440
- <ItemDescription>{edu.courses.join(', ')}</ItemDescription>
441
- )}
442
- </EducationItem>
443
- ))}
444
- </StyledSection>
445
- )}
446
-
447
- {projects && projects.length > 0 && (
448
- <StyledSection>
449
- <StyledSectionTitle>Projects</StyledSectionTitle>
302
+ {projects.length > 0 && (
303
+ <MainSection>
304
+ <MainSectionTitle>Projects</MainSectionTitle>
450
305
  {projects.map((project, index) => (
451
- <ProjectItem key={index}>
452
- <ProjectHeader>
453
- <ProjectName>
306
+ <WorkItem key={index}>
307
+ <WorkHeader>
308
+ <WorkTitle>
454
309
  {project.url ? (
455
- <Link href={project.url}>{project.name}</Link>
310
+ <Link href={safeUrl(project.url)}>{project.name}</Link>
456
311
  ) : (
457
312
  project.name
458
313
  )}
459
- </ProjectName>
460
- {project.description && (
461
- <ProjectDescription>{project.description}</ProjectDescription>
314
+ </WorkTitle>
315
+ {(project.startDate || project.endDate) && (
316
+ <WorkMeta>
317
+ <DateRange
318
+ startDate={project.startDate}
319
+ endDate={project.endDate}
320
+ />
321
+ </WorkMeta>
462
322
  )}
463
- </ProjectHeader>
323
+ </WorkHeader>
324
+ {project.description && (
325
+ <WorkDescription>{project.description}</WorkDescription>
326
+ )}
464
327
  {project.highlights && project.highlights.length > 0 && (
465
- <ProjectHighlights>
328
+ <WorkHighlights>
466
329
  {project.highlights.map((highlight, i) => (
467
330
  <li key={i}>{highlight}</li>
468
331
  ))}
469
- </ProjectHighlights>
332
+ </WorkHighlights>
470
333
  )}
471
- </ProjectItem>
334
+ </WorkItem>
472
335
  ))}
473
- </StyledSection>
336
+ </MainSection>
474
337
  )}
475
338
 
476
- {volunteer && volunteer.length > 0 && (
477
- <StyledSection>
478
- <StyledSectionTitle>Volunteer</StyledSectionTitle>
339
+ {education.length > 0 && (
340
+ <MainSection>
341
+ <MainSectionTitle>Education</MainSectionTitle>
342
+ {education.map((edu, index) => (
343
+ <WorkItem key={index}>
344
+ <WorkHeader>
345
+ <WorkTitle>{edu.institution}</WorkTitle>
346
+ <WorkMeta>
347
+ <DateRange startDate={edu.startDate} endDate={edu.endDate} />
348
+ </WorkMeta>
349
+ </WorkHeader>
350
+ {edu.studyType && edu.area && (
351
+ <WorkCompany>
352
+ {edu.studyType} in {edu.area}
353
+ </WorkCompany>
354
+ )}
355
+ {edu.score && <WorkDescription>GPA: {edu.score}</WorkDescription>}
356
+ </WorkItem>
357
+ ))}
358
+ </MainSection>
359
+ )}
360
+
361
+ {volunteer.length > 0 && (
362
+ <MainSection>
363
+ <MainSectionTitle>Volunteer</MainSectionTitle>
364
+ {volunteer.map((vol, index) => (
365
+ <WorkItem key={index}>
366
+ <WorkHeader>
367
+ <WorkTitle>{vol.position}</WorkTitle>
368
+ <WorkMeta>
369
+ <DateRange startDate={vol.startDate} endDate={vol.endDate} />
370
+ </WorkMeta>
371
+ </WorkHeader>
372
+ <WorkCompany>{vol.organization}</WorkCompany>
373
+ {vol.summary && <WorkDescription>{vol.summary}</WorkDescription>}
374
+ {vol.highlights && vol.highlights.length > 0 && (
375
+ <WorkHighlights>
376
+ {vol.highlights.map((highlight, i) => (
377
+ <li key={i}>{highlight}</li>
378
+ ))}
379
+ </WorkHighlights>
380
+ )}
381
+ </WorkItem>
382
+ ))}
383
+ </MainSection>
384
+ )}
385
+
386
+ {awards.length > 0 && (
387
+ <MainSection>
388
+ <MainSectionTitle>Awards</MainSectionTitle>
479
389
  <SimpleList>
480
- {volunteer.map((vol, index) => (
390
+ {awards.map((award, index) => (
481
391
  <SimpleItem key={index}>
482
- <ItemTitle>{vol.position}</ItemTitle>
483
- <ItemMeta>
484
- {vol.organization}
485
- {vol.startDate && (
486
- <>
487
- {' '}
488
- <DateRange
489
- startDate={vol.startDate}
490
- endDate={vol.endDate}
491
- />
492
- </>
493
- )}
494
- </ItemMeta>
495
- {vol.summary && (
496
- <ItemDescription>{vol.summary}</ItemDescription>
392
+ <strong>{award.title}</strong>
393
+ {award.awarder && ` — ${award.awarder}`}
394
+ {award.date && (
395
+ <div
396
+ style={{
397
+ fontSize: '13px',
398
+ color: '#6b7280',
399
+ marginTop: '4px',
400
+ }}
401
+ >
402
+ {award.date}
403
+ </div>
497
404
  )}
498
405
  </SimpleItem>
499
406
  ))}
500
407
  </SimpleList>
501
- </StyledSection>
408
+ </MainSection>
502
409
  )}
503
410
 
504
- {awards && awards.length > 0 && (
505
- <StyledSection>
506
- <StyledSectionTitle>Awards</StyledSectionTitle>
411
+ {certificates.length > 0 && (
412
+ <MainSection>
413
+ <MainSectionTitle>Certificates</MainSectionTitle>
507
414
  <SimpleList>
508
- {awards.map((award, index) => (
415
+ {certificates.map((cert, index) => (
509
416
  <SimpleItem key={index}>
510
- <ItemTitle>{award.title}</ItemTitle>
511
- <ItemMeta>
512
- {award.awarder}
513
- {award.date && <> • {award.date}</>}
514
- </ItemMeta>
515
- {award.summary && (
516
- <ItemDescription>{award.summary}</ItemDescription>
417
+ <strong>
418
+ {cert.url ? (
419
+ <Link href={safeUrl(cert.url)}>{cert.name}</Link>
420
+ ) : (
421
+ cert.name
422
+ )}
423
+ </strong>
424
+ {cert.issuer && ` — ${cert.issuer}`}
425
+ {cert.date && (
426
+ <div
427
+ style={{
428
+ fontSize: '13px',
429
+ color: '#6b7280',
430
+ marginTop: '4px',
431
+ }}
432
+ >
433
+ {cert.date}
434
+ </div>
517
435
  )}
518
436
  </SimpleItem>
519
437
  ))}
520
438
  </SimpleList>
521
- </StyledSection>
439
+ </MainSection>
522
440
  )}
523
441
 
524
- {publications && publications.length > 0 && (
525
- <StyledSection>
526
- <StyledSectionTitle>Publications</StyledSectionTitle>
527
- {publications.map((pub, index) => (
528
- <ProjectItem key={index}>
529
- <ProjectHeader>
530
- <ProjectName>
531
- {pub.url ? <Link href={pub.url}>{pub.name}</Link> : pub.name}
532
- </ProjectName>
533
- <ItemMeta>
534
- {pub.publisher}
535
- {pub.releaseDate && <> • {pub.releaseDate}</>}
536
- </ItemMeta>
537
- </ProjectHeader>
538
- {pub.summary && (
539
- <ProjectDescription>{pub.summary}</ProjectDescription>
540
- )}
541
- </ProjectItem>
542
- ))}
543
- </StyledSection>
442
+ {publications.length > 0 && (
443
+ <MainSection>
444
+ <MainSectionTitle>Publications</MainSectionTitle>
445
+ <SimpleList>
446
+ {publications.map((pub, index) => (
447
+ <SimpleItem key={index}>
448
+ <strong>{pub.name}</strong>
449
+ {pub.publisher && ` — ${pub.publisher}`}
450
+ {pub.releaseDate && (
451
+ <div
452
+ style={{
453
+ fontSize: '13px',
454
+ color: '#6b7280',
455
+ marginTop: '4px',
456
+ }}
457
+ >
458
+ {pub.releaseDate}
459
+ </div>
460
+ )}
461
+ </SimpleItem>
462
+ ))}
463
+ </SimpleList>
464
+ </MainSection>
544
465
  )}
545
466
 
546
- {languages && languages.length > 0 && (
547
- <StyledSection>
548
- <StyledSectionTitle>Languages</StyledSectionTitle>
467
+ {languages.length > 0 && (
468
+ <MainSection>
469
+ <MainSectionTitle>Languages</MainSectionTitle>
549
470
  <SimpleList>
550
471
  {languages.map((lang, index) => (
551
472
  <SimpleItem key={index}>
552
- <ItemTitle>{lang.language}</ItemTitle>
553
- {lang.fluency && <ItemMeta>{lang.fluency}</ItemMeta>}
473
+ <strong>{lang.language}</strong>
474
+ {lang.fluency && ` — ${lang.fluency}`}
554
475
  </SimpleItem>
555
476
  ))}
556
477
  </SimpleList>
557
- </StyledSection>
478
+ </MainSection>
558
479
  )}
559
480
 
560
- {interests && interests.length > 0 && (
561
- <StyledSection>
562
- <StyledSectionTitle>Interests</StyledSectionTitle>
481
+ {interests.length > 0 && (
482
+ <MainSection>
483
+ <MainSectionTitle>Interests</MainSectionTitle>
563
484
  <SimpleList>
564
485
  {interests.map((interest, index) => (
565
- <SimpleItem key={index}>
566
- <ItemTitle>{interest.name}</ItemTitle>
567
- {interest.keywords && interest.keywords.length > 0 && (
568
- <ItemDescription>
569
- {interest.keywords.join(', ')}
570
- </ItemDescription>
571
- )}
572
- </SimpleItem>
486
+ <SimpleItem key={index}>{interest.name}</SimpleItem>
573
487
  ))}
574
488
  </SimpleList>
575
- </StyledSection>
489
+ </MainSection>
576
490
  )}
577
491
 
578
- {references && references.length > 0 && (
579
- <StyledSection>
580
- <StyledSectionTitle>References</StyledSectionTitle>
492
+ {references.length > 0 && (
493
+ <MainSection>
494
+ <MainSectionTitle>References</MainSectionTitle>
581
495
  {references.map((ref, index) => (
582
- <ProjectItem key={index}>
583
- <ItemTitle>{ref.name}</ItemTitle>
496
+ <WorkItem key={index}>
497
+ <WorkTitle>{ref.name}</WorkTitle>
584
498
  {ref.reference && (
585
- <ItemDescription>{ref.reference}</ItemDescription>
499
+ <WorkDescription>{ref.reference}</WorkDescription>
586
500
  )}
587
- </ProjectItem>
501
+ </WorkItem>
588
502
  ))}
589
- </StyledSection>
503
+ </MainSection>
590
504
  )}
591
505
  </Layout>
592
506
  );