jsonresume-theme-elegant-pink 0.1.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/package.json +39 -0
- package/src/Resume.jsx +649 -0
- package/src/index.js +93 -0
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jsonresume-theme-elegant-pink",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Professional storytelling resume theme with warm rose red tones, compelling narratives, and strong visual hierarchy for marketing and communications professionals",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./src/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.js"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"jsonresume",
|
|
12
|
+
"theme",
|
|
13
|
+
"resume",
|
|
14
|
+
"cv",
|
|
15
|
+
"pink",
|
|
16
|
+
"girly",
|
|
17
|
+
"elegant",
|
|
18
|
+
"feminine",
|
|
19
|
+
"pretty",
|
|
20
|
+
"ats-friendly"
|
|
21
|
+
],
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"react": "^19.2.0",
|
|
24
|
+
"react-dom": "^19.2.0",
|
|
25
|
+
"styled-components": "^6.1.19",
|
|
26
|
+
"@resume/core": "0.1.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"vitest": "^1.6.0"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
33
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"test": "vitest run",
|
|
37
|
+
"test:watch": "vitest"
|
|
38
|
+
}
|
|
39
|
+
}
|
package/src/Resume.jsx
ADDED
|
@@ -0,0 +1,649 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
import { Section, SectionTitle, DateRange, ContactInfo } from '@resume/core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Marketing Narrative Resume Theme
|
|
7
|
+
* Professional storytelling design with warm rose red tones, compelling narratives,
|
|
8
|
+
* and strong visual hierarchy for marketing/communications professionals
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const Layout = styled.div`
|
|
12
|
+
max-width: 950px;
|
|
13
|
+
margin: 0 auto;
|
|
14
|
+
padding: 0;
|
|
15
|
+
background: linear-gradient(to bottom, #fff1f2 0%, #ffffff 400px);
|
|
16
|
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI',
|
|
17
|
+
sans-serif;
|
|
18
|
+
color: #1f2937;
|
|
19
|
+
font-size: 11pt;
|
|
20
|
+
line-height: 1.6;
|
|
21
|
+
min-height: 100vh;
|
|
22
|
+
|
|
23
|
+
@media print {
|
|
24
|
+
background: white;
|
|
25
|
+
min-height: auto;
|
|
26
|
+
}
|
|
27
|
+
`;
|
|
28
|
+
|
|
29
|
+
const Header = styled.header`
|
|
30
|
+
background: linear-gradient(135deg, #9f1239 0%, #be123c 50%, #e11d48 100%);
|
|
31
|
+
color: white;
|
|
32
|
+
padding: 70px 60px 90px;
|
|
33
|
+
position: relative;
|
|
34
|
+
clip-path: polygon(0 0, 100% 0, 100% 85%, 0 100%);
|
|
35
|
+
|
|
36
|
+
@media print {
|
|
37
|
+
padding: 50px 40px 70px;
|
|
38
|
+
clip-path: none;
|
|
39
|
+
}
|
|
40
|
+
`;
|
|
41
|
+
|
|
42
|
+
const HeaderContent = styled.div`
|
|
43
|
+
max-width: 850px;
|
|
44
|
+
margin: 0 auto;
|
|
45
|
+
`;
|
|
46
|
+
|
|
47
|
+
const Name = styled.h1`
|
|
48
|
+
font-size: 56px;
|
|
49
|
+
font-weight: 800;
|
|
50
|
+
color: white;
|
|
51
|
+
margin: 0 0 16px 0;
|
|
52
|
+
letter-spacing: -1px;
|
|
53
|
+
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
|
54
|
+
|
|
55
|
+
@media print {
|
|
56
|
+
font-size: 48px;
|
|
57
|
+
}
|
|
58
|
+
`;
|
|
59
|
+
|
|
60
|
+
const Tagline = styled.div`
|
|
61
|
+
font-size: 22px;
|
|
62
|
+
color: #fecdd3;
|
|
63
|
+
margin-bottom: 24px;
|
|
64
|
+
font-weight: 500;
|
|
65
|
+
letter-spacing: 0.3px;
|
|
66
|
+
`;
|
|
67
|
+
|
|
68
|
+
const StyledContactInfo = styled(ContactInfo)`
|
|
69
|
+
font-size: 15px;
|
|
70
|
+
justify-content: flex-start;
|
|
71
|
+
color: #fecdd3;
|
|
72
|
+
|
|
73
|
+
a {
|
|
74
|
+
font-size: 15px;
|
|
75
|
+
color: white;
|
|
76
|
+
text-decoration: none;
|
|
77
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
|
|
78
|
+
transition: border-color 0.2s;
|
|
79
|
+
|
|
80
|
+
&:hover {
|
|
81
|
+
border-bottom-color: white;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@media print {
|
|
86
|
+
a {
|
|
87
|
+
border-bottom: none;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
`;
|
|
91
|
+
|
|
92
|
+
const Content = styled.div`
|
|
93
|
+
padding: 60px 60px 80px;
|
|
94
|
+
max-width: 850px;
|
|
95
|
+
margin: 0 auto;
|
|
96
|
+
|
|
97
|
+
@media print {
|
|
98
|
+
padding: 40px;
|
|
99
|
+
}
|
|
100
|
+
`;
|
|
101
|
+
|
|
102
|
+
const Summary = styled.div`
|
|
103
|
+
font-size: 18px;
|
|
104
|
+
line-height: 1.8;
|
|
105
|
+
color: #374151;
|
|
106
|
+
margin: 0 0 50px 0;
|
|
107
|
+
padding: 35px;
|
|
108
|
+
background: white;
|
|
109
|
+
border-radius: 12px;
|
|
110
|
+
box-shadow: 0 4px 12px rgba(159, 18, 57, 0.08);
|
|
111
|
+
border-left: 5px solid #e11d48;
|
|
112
|
+
position: relative;
|
|
113
|
+
|
|
114
|
+
&::before {
|
|
115
|
+
content: '"';
|
|
116
|
+
position: absolute;
|
|
117
|
+
top: 10px;
|
|
118
|
+
left: 15px;
|
|
119
|
+
font-size: 80px;
|
|
120
|
+
color: #fecdd3;
|
|
121
|
+
font-family: Georgia, serif;
|
|
122
|
+
line-height: 1;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
p {
|
|
126
|
+
margin: 0;
|
|
127
|
+
padding-left: 20px;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@media print {
|
|
131
|
+
box-shadow: none;
|
|
132
|
+
border: 1px solid #e5e7eb;
|
|
133
|
+
}
|
|
134
|
+
`;
|
|
135
|
+
|
|
136
|
+
const StyledSectionTitle = styled(SectionTitle)`
|
|
137
|
+
font-size: 26px;
|
|
138
|
+
font-weight: 700;
|
|
139
|
+
color: #9f1239;
|
|
140
|
+
margin: 0 0 30px 0;
|
|
141
|
+
text-transform: uppercase;
|
|
142
|
+
letter-spacing: 1px;
|
|
143
|
+
display: flex;
|
|
144
|
+
align-items: center;
|
|
145
|
+
gap: 16px;
|
|
146
|
+
|
|
147
|
+
&::after {
|
|
148
|
+
content: '';
|
|
149
|
+
flex: 1;
|
|
150
|
+
height: 3px;
|
|
151
|
+
background: linear-gradient(to right, #e11d48, transparent);
|
|
152
|
+
border-radius: 2px;
|
|
153
|
+
}
|
|
154
|
+
`;
|
|
155
|
+
|
|
156
|
+
const WorkItem = styled.div`
|
|
157
|
+
margin-bottom: 35px;
|
|
158
|
+
padding-bottom: 35px;
|
|
159
|
+
border-bottom: 1px solid #f3f4f6;
|
|
160
|
+
|
|
161
|
+
&:last-child {
|
|
162
|
+
border-bottom: none;
|
|
163
|
+
padding-bottom: 0;
|
|
164
|
+
margin-bottom: 0;
|
|
165
|
+
}
|
|
166
|
+
`;
|
|
167
|
+
|
|
168
|
+
const WorkHeader = styled.div`
|
|
169
|
+
margin-bottom: 12px;
|
|
170
|
+
`;
|
|
171
|
+
|
|
172
|
+
const Position = styled.h3`
|
|
173
|
+
font-size: 20px;
|
|
174
|
+
font-weight: 700;
|
|
175
|
+
color: #9f1239;
|
|
176
|
+
margin: 0 0 6px 0;
|
|
177
|
+
`;
|
|
178
|
+
|
|
179
|
+
const CompanyMeta = styled.div`
|
|
180
|
+
display: flex;
|
|
181
|
+
gap: 16px;
|
|
182
|
+
flex-wrap: wrap;
|
|
183
|
+
align-items: center;
|
|
184
|
+
margin-bottom: 8px;
|
|
185
|
+
`;
|
|
186
|
+
|
|
187
|
+
const Company = styled.div`
|
|
188
|
+
font-size: 17px;
|
|
189
|
+
color: #374151;
|
|
190
|
+
font-weight: 600;
|
|
191
|
+
`;
|
|
192
|
+
|
|
193
|
+
const DateText = styled.div`
|
|
194
|
+
font-size: 14px;
|
|
195
|
+
color: #6b7280;
|
|
196
|
+
font-weight: 500;
|
|
197
|
+
|
|
198
|
+
&::before {
|
|
199
|
+
content: '•';
|
|
200
|
+
margin-right: 8px;
|
|
201
|
+
color: #e11d48;
|
|
202
|
+
}
|
|
203
|
+
`;
|
|
204
|
+
|
|
205
|
+
const WorkSummary = styled.p`
|
|
206
|
+
margin: 14px 0;
|
|
207
|
+
color: #374151;
|
|
208
|
+
line-height: 1.8;
|
|
209
|
+
font-size: 15px;
|
|
210
|
+
font-style: italic;
|
|
211
|
+
border-left: 3px solid #fecdd3;
|
|
212
|
+
padding-left: 16px;
|
|
213
|
+
`;
|
|
214
|
+
|
|
215
|
+
const Highlights = styled.ul`
|
|
216
|
+
margin: 14px 0 0 0;
|
|
217
|
+
padding-left: 20px;
|
|
218
|
+
list-style-type: none;
|
|
219
|
+
|
|
220
|
+
li {
|
|
221
|
+
margin: 10px 0;
|
|
222
|
+
color: #4b5563;
|
|
223
|
+
line-height: 1.7;
|
|
224
|
+
padding-left: 8px;
|
|
225
|
+
position: relative;
|
|
226
|
+
|
|
227
|
+
&::before {
|
|
228
|
+
content: '▸';
|
|
229
|
+
position: absolute;
|
|
230
|
+
left: -12px;
|
|
231
|
+
color: #e11d48;
|
|
232
|
+
font-weight: bold;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
`;
|
|
236
|
+
|
|
237
|
+
const EducationGrid = styled.div`
|
|
238
|
+
display: grid;
|
|
239
|
+
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
|
|
240
|
+
gap: 24px;
|
|
241
|
+
`;
|
|
242
|
+
|
|
243
|
+
const EducationCard = styled.div`
|
|
244
|
+
padding: 24px;
|
|
245
|
+
background: white;
|
|
246
|
+
border-radius: 10px;
|
|
247
|
+
box-shadow: 0 2px 8px rgba(159, 18, 57, 0.06);
|
|
248
|
+
border-top: 4px solid #e11d48;
|
|
249
|
+
transition: all 0.2s ease;
|
|
250
|
+
|
|
251
|
+
&:hover {
|
|
252
|
+
box-shadow: 0 4px 16px rgba(159, 18, 57, 0.12);
|
|
253
|
+
transform: translateY(-2px);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
@media print {
|
|
257
|
+
box-shadow: none;
|
|
258
|
+
border: 1px solid #e5e7eb;
|
|
259
|
+
transform: none !important;
|
|
260
|
+
}
|
|
261
|
+
`;
|
|
262
|
+
|
|
263
|
+
const Institution = styled.h3`
|
|
264
|
+
font-size: 18px;
|
|
265
|
+
font-weight: 700;
|
|
266
|
+
color: #9f1239;
|
|
267
|
+
margin: 0 0 8px 0;
|
|
268
|
+
`;
|
|
269
|
+
|
|
270
|
+
const Degree = styled.div`
|
|
271
|
+
font-size: 16px;
|
|
272
|
+
color: #374151;
|
|
273
|
+
margin-bottom: 6px;
|
|
274
|
+
font-weight: 600;
|
|
275
|
+
`;
|
|
276
|
+
|
|
277
|
+
const EducationMeta = styled.div`
|
|
278
|
+
font-size: 14px;
|
|
279
|
+
color: #6b7280;
|
|
280
|
+
display: flex;
|
|
281
|
+
gap: 12px;
|
|
282
|
+
flex-wrap: wrap;
|
|
283
|
+
`;
|
|
284
|
+
|
|
285
|
+
const Courses = styled.div`
|
|
286
|
+
margin-top: 12px;
|
|
287
|
+
font-size: 13px;
|
|
288
|
+
color: #4b5563;
|
|
289
|
+
line-height: 1.6;
|
|
290
|
+
|
|
291
|
+
strong {
|
|
292
|
+
color: #374151;
|
|
293
|
+
display: block;
|
|
294
|
+
margin-bottom: 4px;
|
|
295
|
+
}
|
|
296
|
+
`;
|
|
297
|
+
|
|
298
|
+
const SkillsGrid = styled.div`
|
|
299
|
+
display: grid;
|
|
300
|
+
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
|
301
|
+
gap: 20px;
|
|
302
|
+
`;
|
|
303
|
+
|
|
304
|
+
const SkillCategory = styled.div`
|
|
305
|
+
padding: 20px;
|
|
306
|
+
background: linear-gradient(135deg, #fff1f2 0%, #ffe4e6 100%);
|
|
307
|
+
border-radius: 10px;
|
|
308
|
+
border-left: 4px solid #e11d48;
|
|
309
|
+
`;
|
|
310
|
+
|
|
311
|
+
const SkillName = styled.h4`
|
|
312
|
+
font-size: 15px;
|
|
313
|
+
font-weight: 700;
|
|
314
|
+
color: #9f1239;
|
|
315
|
+
margin: 0 0 10px 0;
|
|
316
|
+
text-transform: uppercase;
|
|
317
|
+
letter-spacing: 0.5px;
|
|
318
|
+
`;
|
|
319
|
+
|
|
320
|
+
const SkillTags = styled.div`
|
|
321
|
+
font-size: 14px;
|
|
322
|
+
color: #4b5563;
|
|
323
|
+
line-height: 1.7;
|
|
324
|
+
`;
|
|
325
|
+
|
|
326
|
+
const ProjectItem = styled(WorkItem)``;
|
|
327
|
+
|
|
328
|
+
const ProjectTitle = styled(Position)`
|
|
329
|
+
font-size: 18px;
|
|
330
|
+
`;
|
|
331
|
+
|
|
332
|
+
const ProjectMeta = styled.div`
|
|
333
|
+
display: flex;
|
|
334
|
+
gap: 12px;
|
|
335
|
+
margin-top: 6px;
|
|
336
|
+
font-size: 14px;
|
|
337
|
+
color: #6b7280;
|
|
338
|
+
flex-wrap: wrap;
|
|
339
|
+
`;
|
|
340
|
+
|
|
341
|
+
const ProjectLink = styled.a`
|
|
342
|
+
color: #e11d48;
|
|
343
|
+
text-decoration: none;
|
|
344
|
+
font-weight: 600;
|
|
345
|
+
|
|
346
|
+
&:hover {
|
|
347
|
+
text-decoration: underline;
|
|
348
|
+
}
|
|
349
|
+
`;
|
|
350
|
+
|
|
351
|
+
const AwardCard = styled(EducationCard)``;
|
|
352
|
+
|
|
353
|
+
const AwardTitle = styled(Institution)`
|
|
354
|
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI',
|
|
355
|
+
sans-serif;
|
|
356
|
+
font-size: 17px;
|
|
357
|
+
`;
|
|
358
|
+
|
|
359
|
+
const SimpleList = styled.div`
|
|
360
|
+
display: grid;
|
|
361
|
+
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
|
362
|
+
gap: 16px;
|
|
363
|
+
`;
|
|
364
|
+
|
|
365
|
+
const SimpleItem = styled.div`
|
|
366
|
+
font-size: 15px;
|
|
367
|
+
color: #4b5563;
|
|
368
|
+
padding: 14px;
|
|
369
|
+
background: white;
|
|
370
|
+
border-radius: 8px;
|
|
371
|
+
box-shadow: 0 2px 6px rgba(159, 18, 57, 0.05);
|
|
372
|
+
|
|
373
|
+
strong {
|
|
374
|
+
color: #9f1239;
|
|
375
|
+
font-weight: 600;
|
|
376
|
+
display: block;
|
|
377
|
+
margin-bottom: 4px;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
@media print {
|
|
381
|
+
box-shadow: none;
|
|
382
|
+
border: 1px solid #e5e7eb;
|
|
383
|
+
}
|
|
384
|
+
`;
|
|
385
|
+
|
|
386
|
+
function Resume({ resume }) {
|
|
387
|
+
const {
|
|
388
|
+
basics = {},
|
|
389
|
+
work = [],
|
|
390
|
+
education = [],
|
|
391
|
+
skills = [],
|
|
392
|
+
projects = [],
|
|
393
|
+
volunteer = [],
|
|
394
|
+
awards = [],
|
|
395
|
+
publications = [],
|
|
396
|
+
languages = [],
|
|
397
|
+
interests = [],
|
|
398
|
+
references = [],
|
|
399
|
+
} = resume;
|
|
400
|
+
|
|
401
|
+
return (
|
|
402
|
+
<Layout>
|
|
403
|
+
<Header>
|
|
404
|
+
<HeaderContent>
|
|
405
|
+
<Name>{basics.name}</Name>
|
|
406
|
+
{basics.label && <Tagline>{basics.label}</Tagline>}
|
|
407
|
+
<StyledContactInfo basics={basics} />
|
|
408
|
+
</HeaderContent>
|
|
409
|
+
</Header>
|
|
410
|
+
|
|
411
|
+
<Content>
|
|
412
|
+
{basics.summary && (
|
|
413
|
+
<Summary>
|
|
414
|
+
<p>{basics.summary}</p>
|
|
415
|
+
</Summary>
|
|
416
|
+
)}
|
|
417
|
+
|
|
418
|
+
{work?.length > 0 && (
|
|
419
|
+
<Section>
|
|
420
|
+
<StyledSectionTitle>Professional Experience</StyledSectionTitle>
|
|
421
|
+
{work.map((job, index) => (
|
|
422
|
+
<WorkItem key={index}>
|
|
423
|
+
<WorkHeader>
|
|
424
|
+
<Position>{job.position}</Position>
|
|
425
|
+
<CompanyMeta>
|
|
426
|
+
{job.name && <Company>{job.name}</Company>}
|
|
427
|
+
{(job.startDate || job.endDate) && (
|
|
428
|
+
<DateText>
|
|
429
|
+
<DateRange
|
|
430
|
+
startDate={job.startDate}
|
|
431
|
+
endDate={job.endDate}
|
|
432
|
+
/>
|
|
433
|
+
</DateText>
|
|
434
|
+
)}
|
|
435
|
+
</CompanyMeta>
|
|
436
|
+
</WorkHeader>
|
|
437
|
+
{job.summary && <WorkSummary>{job.summary}</WorkSummary>}
|
|
438
|
+
{job.highlights?.length > 0 && (
|
|
439
|
+
<Highlights>
|
|
440
|
+
{job.highlights.map((highlight, i) => (
|
|
441
|
+
<li key={i}>{highlight}</li>
|
|
442
|
+
))}
|
|
443
|
+
</Highlights>
|
|
444
|
+
)}
|
|
445
|
+
</WorkItem>
|
|
446
|
+
))}
|
|
447
|
+
</Section>
|
|
448
|
+
)}
|
|
449
|
+
|
|
450
|
+
{education?.length > 0 && (
|
|
451
|
+
<Section>
|
|
452
|
+
<StyledSectionTitle>Education</StyledSectionTitle>
|
|
453
|
+
<EducationGrid>
|
|
454
|
+
{education.map((edu, index) => (
|
|
455
|
+
<EducationCard key={index}>
|
|
456
|
+
<Institution>{edu.institution}</Institution>
|
|
457
|
+
<Degree>
|
|
458
|
+
{edu.studyType} in {edu.area}
|
|
459
|
+
</Degree>
|
|
460
|
+
<EducationMeta>
|
|
461
|
+
<DateText>
|
|
462
|
+
<DateRange
|
|
463
|
+
startDate={edu.startDate}
|
|
464
|
+
endDate={edu.endDate}
|
|
465
|
+
/>
|
|
466
|
+
</DateText>
|
|
467
|
+
{edu.score && <span>GPA: {edu.score}</span>}
|
|
468
|
+
</EducationMeta>
|
|
469
|
+
{edu.courses?.length > 0 && (
|
|
470
|
+
<Courses>
|
|
471
|
+
<strong>Key Coursework:</strong>
|
|
472
|
+
{edu.courses.join(', ')}
|
|
473
|
+
</Courses>
|
|
474
|
+
)}
|
|
475
|
+
</EducationCard>
|
|
476
|
+
))}
|
|
477
|
+
</EducationGrid>
|
|
478
|
+
</Section>
|
|
479
|
+
)}
|
|
480
|
+
|
|
481
|
+
{skills?.length > 0 && (
|
|
482
|
+
<Section>
|
|
483
|
+
<StyledSectionTitle>Core Competencies</StyledSectionTitle>
|
|
484
|
+
<SkillsGrid>
|
|
485
|
+
{skills.map((skill, index) => (
|
|
486
|
+
<SkillCategory key={index}>
|
|
487
|
+
<SkillName>{skill.name}</SkillName>
|
|
488
|
+
{skill.keywords?.length > 0 && (
|
|
489
|
+
<SkillTags>{skill.keywords.join(' • ')}</SkillTags>
|
|
490
|
+
)}
|
|
491
|
+
</SkillCategory>
|
|
492
|
+
))}
|
|
493
|
+
</SkillsGrid>
|
|
494
|
+
</Section>
|
|
495
|
+
)}
|
|
496
|
+
|
|
497
|
+
{projects?.length > 0 && (
|
|
498
|
+
<Section>
|
|
499
|
+
<StyledSectionTitle>Featured Projects</StyledSectionTitle>
|
|
500
|
+
{projects.map((project, index) => (
|
|
501
|
+
<ProjectItem key={index}>
|
|
502
|
+
<ProjectTitle>{project.name}</ProjectTitle>
|
|
503
|
+
<ProjectMeta>
|
|
504
|
+
{project.startDate && (
|
|
505
|
+
<DateText>
|
|
506
|
+
<DateRange
|
|
507
|
+
startDate={project.startDate}
|
|
508
|
+
endDate={project.endDate}
|
|
509
|
+
/>
|
|
510
|
+
</DateText>
|
|
511
|
+
)}
|
|
512
|
+
{project.url && (
|
|
513
|
+
<ProjectLink
|
|
514
|
+
href={project.url}
|
|
515
|
+
target="_blank"
|
|
516
|
+
rel="noopener noreferrer"
|
|
517
|
+
>
|
|
518
|
+
View Project →
|
|
519
|
+
</ProjectLink>
|
|
520
|
+
)}
|
|
521
|
+
</ProjectMeta>
|
|
522
|
+
{project.description && (
|
|
523
|
+
<WorkSummary>{project.description}</WorkSummary>
|
|
524
|
+
)}
|
|
525
|
+
{project.highlights?.length > 0 && (
|
|
526
|
+
<Highlights>
|
|
527
|
+
{project.highlights.map((highlight, i) => (
|
|
528
|
+
<li key={i}>{highlight}</li>
|
|
529
|
+
))}
|
|
530
|
+
</Highlights>
|
|
531
|
+
)}
|
|
532
|
+
</ProjectItem>
|
|
533
|
+
))}
|
|
534
|
+
</Section>
|
|
535
|
+
)}
|
|
536
|
+
|
|
537
|
+
{volunteer?.length > 0 && (
|
|
538
|
+
<Section>
|
|
539
|
+
<StyledSectionTitle>Community Involvement</StyledSectionTitle>
|
|
540
|
+
{volunteer.map((vol, index) => (
|
|
541
|
+
<WorkItem key={index}>
|
|
542
|
+
<WorkHeader>
|
|
543
|
+
<Position>{vol.position}</Position>
|
|
544
|
+
<CompanyMeta>
|
|
545
|
+
{vol.organization && <Company>{vol.organization}</Company>}
|
|
546
|
+
{(vol.startDate || vol.endDate) && (
|
|
547
|
+
<DateText>
|
|
548
|
+
<DateRange
|
|
549
|
+
startDate={vol.startDate}
|
|
550
|
+
endDate={vol.endDate}
|
|
551
|
+
/>
|
|
552
|
+
</DateText>
|
|
553
|
+
)}
|
|
554
|
+
</CompanyMeta>
|
|
555
|
+
</WorkHeader>
|
|
556
|
+
{vol.summary && <WorkSummary>{vol.summary}</WorkSummary>}
|
|
557
|
+
{vol.highlights?.length > 0 && (
|
|
558
|
+
<Highlights>
|
|
559
|
+
{vol.highlights.map((highlight, i) => (
|
|
560
|
+
<li key={i}>{highlight}</li>
|
|
561
|
+
))}
|
|
562
|
+
</Highlights>
|
|
563
|
+
)}
|
|
564
|
+
</WorkItem>
|
|
565
|
+
))}
|
|
566
|
+
</Section>
|
|
567
|
+
)}
|
|
568
|
+
|
|
569
|
+
{awards?.length > 0 && (
|
|
570
|
+
<Section>
|
|
571
|
+
<StyledSectionTitle>Recognition & Awards</StyledSectionTitle>
|
|
572
|
+
<EducationGrid>
|
|
573
|
+
{awards.map((award, index) => (
|
|
574
|
+
<AwardCard key={index}>
|
|
575
|
+
<AwardTitle>{award.title}</AwardTitle>
|
|
576
|
+
{award.awarder && <Degree>Awarded by {award.awarder}</Degree>}
|
|
577
|
+
{award.date && <DateText>{award.date}</DateText>}
|
|
578
|
+
{award.summary && <WorkSummary>{award.summary}</WorkSummary>}
|
|
579
|
+
</AwardCard>
|
|
580
|
+
))}
|
|
581
|
+
</EducationGrid>
|
|
582
|
+
</Section>
|
|
583
|
+
)}
|
|
584
|
+
|
|
585
|
+
{publications?.length > 0 && (
|
|
586
|
+
<Section>
|
|
587
|
+
<StyledSectionTitle>Publications</StyledSectionTitle>
|
|
588
|
+
<EducationGrid>
|
|
589
|
+
{publications.map((pub, index) => (
|
|
590
|
+
<AwardCard key={index}>
|
|
591
|
+
<AwardTitle>{pub.name}</AwardTitle>
|
|
592
|
+
{pub.publisher && (
|
|
593
|
+
<Degree>Published by {pub.publisher}</Degree>
|
|
594
|
+
)}
|
|
595
|
+
{pub.releaseDate && <DateText>{pub.releaseDate}</DateText>}
|
|
596
|
+
{pub.summary && <WorkSummary>{pub.summary}</WorkSummary>}
|
|
597
|
+
</AwardCard>
|
|
598
|
+
))}
|
|
599
|
+
</EducationGrid>
|
|
600
|
+
</Section>
|
|
601
|
+
)}
|
|
602
|
+
|
|
603
|
+
{languages?.length > 0 && (
|
|
604
|
+
<Section>
|
|
605
|
+
<StyledSectionTitle>Languages</StyledSectionTitle>
|
|
606
|
+
<SimpleList>
|
|
607
|
+
{languages.map((lang, index) => (
|
|
608
|
+
<SimpleItem key={index}>
|
|
609
|
+
<strong>{lang.language}</strong>
|
|
610
|
+
{lang.fluency && <span>{lang.fluency}</span>}
|
|
611
|
+
</SimpleItem>
|
|
612
|
+
))}
|
|
613
|
+
</SimpleList>
|
|
614
|
+
</Section>
|
|
615
|
+
)}
|
|
616
|
+
|
|
617
|
+
{interests?.length > 0 && (
|
|
618
|
+
<Section>
|
|
619
|
+
<StyledSectionTitle>Interests</StyledSectionTitle>
|
|
620
|
+
<SkillsGrid>
|
|
621
|
+
{interests.map((interest, index) => (
|
|
622
|
+
<SkillCategory key={index}>
|
|
623
|
+
<SkillName>{interest.name}</SkillName>
|
|
624
|
+
{interest.keywords?.length > 0 && (
|
|
625
|
+
<SkillTags>{interest.keywords.join(' • ')}</SkillTags>
|
|
626
|
+
)}
|
|
627
|
+
</SkillCategory>
|
|
628
|
+
))}
|
|
629
|
+
</SkillsGrid>
|
|
630
|
+
</Section>
|
|
631
|
+
)}
|
|
632
|
+
|
|
633
|
+
{references?.length > 0 && (
|
|
634
|
+
<Section>
|
|
635
|
+
<StyledSectionTitle>Testimonials</StyledSectionTitle>
|
|
636
|
+
{references.map((ref, index) => (
|
|
637
|
+
<WorkItem key={index}>
|
|
638
|
+
<AwardTitle>{ref.name}</AwardTitle>
|
|
639
|
+
{ref.reference && <WorkSummary>{ref.reference}</WorkSummary>}
|
|
640
|
+
</WorkItem>
|
|
641
|
+
))}
|
|
642
|
+
</Section>
|
|
643
|
+
)}
|
|
644
|
+
</Content>
|
|
645
|
+
</Layout>
|
|
646
|
+
);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
export default Resume;
|
package/src/index.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { renderToString } from 'react-dom/server';
|
|
2
|
+
import { ServerStyleSheet } from 'styled-components';
|
|
3
|
+
import Resume from './Resume.jsx';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Marketing Narrative Resume Theme (elegant-pink)
|
|
7
|
+
* Professional storytelling theme with warm rose red tones, compelling narratives,
|
|
8
|
+
* and strong visual hierarchy for marketing and communications professionals
|
|
9
|
+
*
|
|
10
|
+
* @param {Object} resume - JSON Resume object
|
|
11
|
+
* @param {Object} [options] - Rendering options
|
|
12
|
+
* @returns {string} Complete HTML document
|
|
13
|
+
*/
|
|
14
|
+
export function render(resume, options = {}) {
|
|
15
|
+
const {
|
|
16
|
+
locale = 'en',
|
|
17
|
+
dir = 'ltr',
|
|
18
|
+
title = resume.basics?.name || 'Resume',
|
|
19
|
+
} = options;
|
|
20
|
+
|
|
21
|
+
const sheet = new ServerStyleSheet();
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const html = renderToString(
|
|
25
|
+
sheet.collectStyles(<Resume resume={resume} />)
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const styles = sheet.getStyleTags();
|
|
29
|
+
|
|
30
|
+
const designTokens = `
|
|
31
|
+
:root {
|
|
32
|
+
--resume-color-primary: #9f1239;
|
|
33
|
+
--resume-color-secondary: #be123c;
|
|
34
|
+
--resume-color-accent: #e11d48;
|
|
35
|
+
--resume-color-bg: #fff1f2;
|
|
36
|
+
--resume-color-card: #ffffff;
|
|
37
|
+
}
|
|
38
|
+
`;
|
|
39
|
+
|
|
40
|
+
const globalStyles = `
|
|
41
|
+
* {
|
|
42
|
+
margin: 0;
|
|
43
|
+
padding: 0;
|
|
44
|
+
box-sizing: border-box;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
body {
|
|
48
|
+
margin: 0;
|
|
49
|
+
background: linear-gradient(to bottom, #fff1f2 0%, #ffffff 400px);
|
|
50
|
+
-webkit-font-smoothing: antialiased;
|
|
51
|
+
-moz-osx-font-smoothing: grayscale;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@media print {
|
|
55
|
+
body {
|
|
56
|
+
background: white;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@page {
|
|
60
|
+
size: A4;
|
|
61
|
+
margin: 0.5in;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
`;
|
|
65
|
+
|
|
66
|
+
return `<!DOCTYPE html>
|
|
67
|
+
<html lang="${locale}" dir="${dir}">
|
|
68
|
+
<head>
|
|
69
|
+
<meta charset="UTF-8">
|
|
70
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
71
|
+
<title>${title}</title>
|
|
72
|
+
|
|
73
|
+
<style>
|
|
74
|
+
${designTokens}
|
|
75
|
+
</style>
|
|
76
|
+
|
|
77
|
+
${styles}
|
|
78
|
+
|
|
79
|
+
<style>
|
|
80
|
+
${globalStyles}
|
|
81
|
+
</style>
|
|
82
|
+
</head>
|
|
83
|
+
<body>
|
|
84
|
+
${html}
|
|
85
|
+
</body>
|
|
86
|
+
</html>`;
|
|
87
|
+
} finally {
|
|
88
|
+
sheet.seal();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export { Resume };
|
|
93
|
+
export default { render };
|