portosaurus 3.0.2 → 4.0.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.
Files changed (60) hide show
  1. package/README.md +26 -126
  2. package/bin/portosaurus.mjs +8 -0
  3. package/package.json +6 -3
  4. package/src/assets/img/icon.png +0 -0
  5. package/src/assets/img/{icon.svg → svg/icon.svg} +35 -37
  6. package/src/assets/img/svg/project-blank.svg +140 -0
  7. package/src/assets/sample-resume.pdf +0 -0
  8. package/src/cli/build.mjs +2 -5
  9. package/src/cli/dev.mjs +27 -5
  10. package/src/cli/init.mjs +6 -12
  11. package/src/cli/schema.mjs +211 -0
  12. package/src/core/buildDocuConfig.mjs +305 -188
  13. package/src/core/constants.mjs +7 -1
  14. package/src/template/config.yml +150 -0
  15. package/src/template/notes/welcome.mdx +6 -0
  16. package/src/template/package.json +3 -3
  17. package/src/theme/MDXComponents.js +0 -1
  18. package/src/theme/components/AboutSection/index.js +32 -17
  19. package/src/theme/components/AboutSection/styles.module.css +151 -344
  20. package/src/theme/components/ContactSection/index.js +23 -14
  21. package/src/theme/components/ContactSection/styles.module.css +19 -8
  22. package/src/theme/components/ExperienceSection/index.js +12 -5
  23. package/src/theme/components/HeroSection/index.js +4 -3
  24. package/src/theme/components/HeroSection/styles.module.css +17 -16
  25. package/src/theme/components/NavArrow/index.js +114 -0
  26. package/src/theme/components/NavArrow/styles.module.css +107 -0
  27. package/src/theme/components/NoteIndex/index.js +66 -95
  28. package/src/theme/components/NoteIndex/styles.module.css +85 -89
  29. package/src/theme/components/Preview/components/FeedbackStates.js +3 -1
  30. package/src/theme/components/Preview/components/PreviewContent.js +91 -0
  31. package/src/theme/components/Preview/components/PreviewHeader.js +41 -33
  32. package/src/theme/components/Preview/components/Triggers/Pv.js +129 -72
  33. package/src/theme/components/Preview/components/ViewerWindow.js +198 -234
  34. package/src/theme/components/Preview/hooks/useAdaptiveSizing.js +115 -0
  35. package/src/theme/components/Preview/hooks/useDeepLinkHash.js +18 -23
  36. package/src/theme/components/Preview/hooks/useDockLayout.js +48 -8
  37. package/src/theme/components/Preview/hooks/useTouchZoom.js +118 -0
  38. package/src/theme/components/Preview/renderers/CodeRenderer.js +64 -25
  39. package/src/theme/components/Preview/state/index.js +70 -17
  40. package/src/theme/components/Preview/styles.module.css +181 -45
  41. package/src/theme/components/Preview/utils/index.js +11 -10
  42. package/src/theme/components/ProjectsSection/index.js +138 -148
  43. package/src/theme/components/ProjectsSection/styles.module.css +178 -112
  44. package/src/theme/components/SocialLinks/index.js +9 -7
  45. package/src/theme/components/Tooltip/index.js +31 -20
  46. package/src/theme/components/Tooltip/styles.module.css +101 -38
  47. package/src/theme/config/iconMappings.js +2 -0
  48. package/src/theme/css/custom.css +72 -0
  49. package/src/theme/hooks/useScrollReveal.js +30 -0
  50. package/src/theme/pages/index.js +7 -27
  51. package/src/theme/pages/notes.js +2 -2
  52. package/src/theme/pages/tasks.js +12 -11
  53. package/src/utils/cliUtils.mjs +23 -51
  54. package/src/utils/configUtils.mjs +95 -84
  55. package/src/utils/systemUtils.mjs +171 -0
  56. package/src/template/config.js +0 -68
  57. package/src/theme/components/ScrollToTop/index.js +0 -95
  58. package/src/theme/components/ScrollToTop/styles.module.css +0 -97
  59. package/src/theme/config/metaTags.js +0 -21
  60. /package/src/template/{.nojekyll → static/.nojekyll} +0 -0
@@ -1,16 +1,9 @@
1
- /* Animations*/
1
+ /* Animations */
2
2
 
3
- @keyframes skillAppear {
4
- to {
5
- opacity: 1;
6
- transform: translateY(0);
7
- }
8
- }
9
-
10
- @keyframes fadeSlideIn {
3
+ @keyframes slideUp {
11
4
  from {
12
5
  opacity: 0;
13
- transform: translateY(10px);
6
+ transform: translateY(30px);
14
7
  }
15
8
  to {
16
9
  opacity: 1;
@@ -18,258 +11,214 @@
18
11
  }
19
12
  }
20
13
 
21
- @keyframes slideUp {
14
+ @keyframes fadeIn {
22
15
  from {
23
16
  opacity: 0;
24
- transform: translateY(20px);
25
17
  }
26
18
  to {
27
19
  opacity: 1;
28
- transform: translateY(0);
29
20
  }
30
21
  }
31
22
 
32
- @keyframes fadeIn {
23
+ @keyframes scaleIn {
33
24
  from {
34
25
  opacity: 0;
26
+ transform: scale(0.9);
35
27
  }
36
28
  to {
37
29
  opacity: 1;
30
+ transform: scale(1);
38
31
  }
39
32
  }
40
33
 
41
- /* Styles */
42
-
34
+ /* Base Section */
43
35
  .aboutSection {
44
36
  scroll-margin-top: var(--ifm-scroll-margin-top);
45
- padding: 0.5rem 0 9.5rem;
37
+ padding: 2rem 0 4rem;
46
38
  background-color: var(--ifm-background-color);
39
+ width: 100%;
47
40
  min-height: 100vh;
48
41
  display: flex;
42
+ flex-direction: column;
49
43
  align-items: center;
50
- justify-content: center;
51
- position: relative;
52
- width: 100%;
44
+ justify-content: flex-start;
53
45
  }
54
46
 
55
47
  .aboutContainer {
56
- max-width: 1200px;
48
+ max-width: 1100px;
57
49
  margin: 0 auto;
58
- padding: 0 2rem;
59
- width: 100%;
60
- position: relative;
61
- z-index: 1;
50
+ padding: 3rem 2rem 0;
62
51
  }
63
52
 
64
53
  .aboutHeader {
65
54
  text-align: center;
66
- margin-bottom: 4.7rem;
55
+ margin-bottom: 2.5rem;
67
56
  }
68
57
 
69
58
  .aboutHeading {
70
- font-size: 2.8rem;
59
+ font-size: 2.5rem;
71
60
  font-weight: 600;
72
61
  color: var(--ifm-color-primary);
73
62
  margin-bottom: 0.6rem;
74
- animation: slideUp 0.5s ease-out forwards;
63
+ opacity: 0;
75
64
  position: relative;
76
65
  display: inline-block;
77
66
  }
78
67
 
68
+ :global(.is-visible) .aboutHeading {
69
+ animation: slideUp 0.6s ease-out forwards;
70
+ }
71
+
79
72
  .aboutHeading::after {
80
73
  content: "";
81
74
  position: absolute;
82
- width: 30%;
75
+ width: 40px;
83
76
  height: 3px;
84
77
  bottom: -0.5rem;
85
- left: 35%;
78
+ left: 50%;
79
+ transform: translateX(-50%);
86
80
  background-color: var(--ifm-color-primary);
87
- border-radius: var(--ifm-global-radius);
81
+ border-radius: 2px;
88
82
  }
89
83
 
90
- .aboutContent {
84
+ /* The Main Card */
85
+ .aboutCard {
91
86
  display: flex;
92
- flex-direction: column;
93
- gap: 3rem;
94
- padding: 0;
95
- animation: fadeIn 0.8s ease-out 0.3s both;
96
- align-items: center;
87
+ background-color: var(--ifm-card-background-color);
88
+ border: 1px solid var(--ifm-color-emphasis-200);
89
+ border-radius: 24px;
90
+ overflow: hidden;
91
+ box-shadow: var(--ifm-global-shadow-md);
92
+ opacity: 0;
93
+ transform: translateY(20px);
94
+ transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
97
95
  }
98
96
 
99
- .aboutBio {
100
- display: flex;
101
- flex-direction: row;
102
- gap: 4rem;
103
- width: 100%;
104
- align-items: center;
97
+ :global(.is-visible) .aboutCard {
98
+ animation: slideUp 0.8s ease-out forwards;
105
99
  }
106
100
 
101
+ /* Left Column: Image & Resume */
107
102
  .bioImageContainer {
108
- flex: 1;
103
+ flex: 0.8;
104
+ background-color: rgba(var(--ifm-color-primary-rgb), 0.03);
105
+ padding: 3rem 2rem;
109
106
  display: flex;
110
- justify-content: center;
107
+ flex-direction: column;
111
108
  align-items: center;
112
- padding-top: 0;
113
- align-self: stretch;
114
- margin-bottom: 1.3rem;
109
+ justify-content: center;
110
+ gap: 3.5rem;
111
+ border-right: 1px solid var(--ifm-color-emphasis-200);
115
112
  }
116
113
 
117
114
  .imageWrapper {
118
- position: relative;
119
- border-radius: var(--ifm-card-border-radius);
120
- overflow: hidden;
121
- box-shadow: 0 10px 20px var(--ifm-shadow-color);
122
- transform: none;
123
- transition:
124
- transform 0.4s ease,
125
- box-shadow 0.4s ease;
126
- max-width: 350px;
127
- margin: auto 0;
128
- }
129
-
130
- .imageWrapper::before {
131
- content: "";
132
- position: absolute;
133
- top: 0;
134
- left: 0;
135
- right: 0;
136
- bottom: 0;
137
- border: 2px solid var(--ifm-color-primary);
138
- border-radius: var(--ifm-card-border-radius);
139
- opacity: 0.2;
140
- pointer-events: none;
141
- z-index: 1;
115
+ width: 200px;
116
+ height: 200px;
117
+ border-radius: 50%;
118
+ padding: 6px;
119
+ background: linear-gradient(
120
+ 135deg,
121
+ var(--ifm-color-primary),
122
+ var(--ifm-color-primary-light)
123
+ );
124
+ box-shadow: 0 10px 30px rgba(var(--ifm-color-primary-rgb), 0.2);
125
+ transition: transform 0.3s ease;
142
126
  }
143
127
 
144
128
  .imageWrapper:hover {
145
- transform: translateY(-8px);
146
- box-shadow: 0 15px 30px var(--ifm-shadow-color);
129
+ transform: scale(1.05);
147
130
  }
148
131
 
149
132
  .aboutImage {
150
- display: block;
151
- max-width: 100%;
152
- height: auto;
153
- border-radius: var(--ifm-global-radius);
133
+ width: 100%;
134
+ height: 100%;
154
135
  object-fit: cover;
155
- transition: filter 0.3s ease;
136
+ border-radius: 50%;
137
+ border: 4px solid var(--ifm-card-background-color);
156
138
  }
157
139
 
158
- .bioTextContainer {
159
- flex: 1.5;
140
+ .resumeContainer {
141
+ width: 100%;
160
142
  display: flex;
161
- flex-direction: column;
162
- gap: 1.2rem;
163
- align-self: flex-start;
143
+ justify-content: center;
164
144
  }
165
145
 
166
- .bioText {
167
- display: flex;
168
- flex-direction: column;
169
- gap: 8px;
170
- align-self: flex-start;
171
- margin-top: -0.5rem;
146
+ .resumeButton {
147
+ display: inline-flex;
148
+ align-items: center;
149
+ gap: 0.6rem;
150
+ padding: 0.7rem 1.4rem;
151
+ background-color: var(--ifm-color-primary);
152
+ color: var(--ifm-background-color);
153
+ border: 1px solid var(--ifm-color-primary);
154
+ border-radius: 12px;
155
+ font-size: 0.9rem;
156
+ font-weight: 600;
157
+ text-decoration: none !important;
158
+ transition: all 0.2s ease;
172
159
  }
173
160
 
174
- .aboutParagraph {
175
- margin-bottom: 0.2rem;
176
- font-size: 1.05rem;
177
- line-height: 1.8;
178
- color: var(--ifm-font-color-base);
179
- position: relative;
180
- padding-left: 0.8rem;
181
- opacity: 0;
182
- animation: fadeSlideIn 0.5s ease-out forwards;
183
- animation-delay: calc(0.3s + var(--paragraph-index, 0) * 0.15s);
161
+ .resumeButton:hover {
162
+ background-color: var(--ifm-background-surface-color);
163
+ color: var(--ifm-color-primary);
164
+ transform: translateY(-2px);
165
+ box-shadow: 0 5px 15px rgba(var(--ifm-color-primary-rgb), 0.2);
184
166
  }
185
167
 
186
- .aboutParagraph:last-child {
187
- margin-bottom: 0;
168
+ /* Right Column: Bio & Skills */
169
+ .bioTextContainer {
170
+ flex: 1.2;
171
+ padding: 3rem;
172
+ display: flex;
173
+ flex-direction: column;
174
+ gap: 0.4rem;
188
175
  }
189
176
 
190
- .aboutParagraph::before {
191
- content: "";
192
- position: absolute;
193
- left: 0;
194
- top: 0.5rem;
195
- bottom: 0.5rem;
196
- width: 3px;
197
- background: linear-gradient(to bottom, var(--ifm-color-primary), transparent);
198
- border-radius: var(--ifm-global-radius);
199
- opacity: 0.7;
177
+ .bioText {
178
+ display: flex;
179
+ flex-direction: column;
180
+ gap: 0.8rem;
181
+ max-height: 320px;
182
+ overflow-y: auto;
183
+ padding-right: 1rem;
200
184
  }
201
185
 
202
- .resumeButtonWrapper {
203
- margin-top: 1rem;
186
+ /* Custom Scrollbar for Bio */
187
+ .bioText::-webkit-scrollbar {
188
+ width: 5px;
204
189
  }
205
190
 
206
- .resumeButton {
207
- display: inline-block;
208
- padding: 0.6rem 1.5rem;
209
- font-size: 0.95rem;
210
- font-weight: 500;
211
- text-decoration: none;
212
- color: var(--ifm-background-color);
213
- background-color: var(--ifm-color-primary);
214
- border-radius: var(--ifm-global-radius);
215
- transition:
216
- all 0.3s ease,
217
- transform 0.2s ease;
218
- border: 2px solid var(--ifm-color-primary);
219
- position: relative;
220
- overflow: hidden;
221
- z-index: 1;
222
- box-shadow: var(--ifm-global-shadow-lw);
191
+ .bioText::-webkit-scrollbar-track {
192
+ background: rgba(var(--ifm-color-primary-rgb), 0.05);
193
+ border-radius: 10px;
223
194
  }
224
195
 
225
- .resumeButton::before {
226
- content: "";
227
- position: absolute;
228
- top: 0;
229
- left: -100%;
230
- width: 100%;
231
- height: 100%;
232
- background: linear-gradient(
233
- 90deg,
234
- transparent,
235
- rgba(255, 255, 255, 0.2),
236
- transparent
237
- );
238
- transition: left 0.7s ease;
239
- z-index: -1;
196
+ .bioText::-webkit-scrollbar-thumb {
197
+ background: rgba(var(--ifm-color-primary-rgb), 0.2);
198
+ border-radius: 10px;
240
199
  }
241
200
 
242
- .resumeButton:hover {
243
- background-color: transparent;
244
- color: var(--ifm-color-primary);
245
- transform: translateY(-3px);
246
- box-shadow: var(--ifm-global-shadow-md);
247
- text-decoration: none;
248
- }
249
-
250
- .resumeButton:hover::before {
251
- left: 100%;
201
+ .bioText::-webkit-scrollbar-thumb:hover {
202
+ background: var(--ifm-color-primary);
252
203
  }
253
204
 
254
- .buttonText {
255
- position: relative;
256
- z-index: 2;
205
+ .aboutParagraph {
206
+ font-size: 1.1rem;
207
+ line-height: 1.4;
208
+ color: var(--ifm-font-color-base);
209
+ margin: 0;
257
210
  }
258
211
 
212
+ /* Skills Grid */
259
213
  .skillsContainer {
260
- width: 100%;
261
- padding: 0.8rem 0 0.5rem;
262
- position: relative;
263
- overflow: hidden;
264
- margin-top: 0;
214
+ margin-top: 1.7rem;
265
215
  }
266
216
 
267
217
  .skillsTitle {
268
218
  font-size: 1.4rem;
269
- margin-bottom: 1.2rem;
270
219
  color: var(--ifm-color-primary);
220
+ margin-bottom: 1.4rem;
271
221
  font-weight: 600;
272
- padding-left: 0;
273
222
  position: relative;
274
223
  display: inline-block;
275
224
  }
@@ -277,226 +226,84 @@
277
226
  .skillsTitle::after {
278
227
  content: "";
279
228
  position: absolute;
280
- width: 40%;
229
+ width: 30px;
281
230
  height: 2px;
282
231
  bottom: -0.4rem;
283
232
  left: 0;
284
233
  background-color: var(--ifm-color-primary);
285
- opacity: 0.5;
286
- border-radius: var(--ifm-global-radius);
234
+ border-radius: 1px;
235
+ opacity: 0.6;
287
236
  }
288
237
 
289
238
  .skillsGrid {
290
239
  display: flex;
291
240
  flex-wrap: wrap;
292
- gap: 0.9rem;
293
- padding-left: 0;
294
- padding-top: 0.4rem;
295
- margin-bottom: 0.5rem;
296
- }
297
-
298
- .skillBadge {
299
- background-color: rgba(var(--ctp-lavender-rgb), 0.08);
300
- color: var(--ctp-lavender);
301
- border-radius: 20px;
302
- padding: 0.5rem 1rem;
303
- font-size: 0.95rem;
304
- font-weight: 500;
305
- transition: all 0.3s ease;
306
- border: 1px solid rgba(var(--ctp-lavender-rgb), 0.15);
307
- display: flex;
308
- align-items: center;
309
- justify-content: center;
310
- opacity: 0;
311
- animation-delay: calc(0.1s + (var(--card-index, 0) * 0.1s));
312
- box-shadow: var(--ifm-global-shadow-lw);
241
+ gap: 0.6rem;
313
242
  }
314
243
 
315
- .skillBadge:hover {
316
- transform: translateY(-3px);
317
- box-shadow: var(--ifm-global-shadow-md);
318
- background-color: rgba(var(--ctp-lavender-rgb), 0.15);
319
- border-color: rgba(var(--ctp-lavender-rgb), 0.3);
244
+ .skillTag {
245
+ background-color: var(--ifm-background-surface-color);
246
+ color: var(--ifm-font-color-tertiary);
247
+ padding: 0.4rem 0.8rem;
248
+ border-radius: 8px;
249
+ font-size: 0.8rem;
250
+ font-weight: 600;
251
+ border: 1px solid var(--ifm-color-emphasis-200);
252
+ transition: all 0.2s ease;
253
+ cursor: default;
320
254
  }
321
255
 
322
- /* Responsive styles */
323
- @media (max-width: 992px) {
324
- .aboutBio {
325
- gap: 3rem;
326
- }
256
+ .skillTag:hover {
257
+ border-color: var(--ifm-color-primary);
258
+ color: var(--ifm-color-primary);
259
+ transform: translateY(-2px);
260
+ background-color: rgba(var(--ifm-color-primary-rgb), 0.05);
327
261
  }
328
262
 
329
- @media (max-width: 768px) {
330
- .aboutSection {
331
- scroll-margin-top: var(--ifm-scroll-margin-top-mobile);
332
- padding: 1.5rem 0 4rem;
333
- }
334
-
335
- .aboutContainer {
336
- padding: 0 1.5rem;
337
- }
338
-
339
- .aboutHeader {
340
- margin-bottom: 2rem;
341
- }
342
-
343
- .aboutHeading {
344
- font-size: 2.4rem;
345
- }
346
-
347
- .aboutBio {
263
+ /* Responsive */
264
+ @media (max-width: 992px) {
265
+ .aboutCard {
348
266
  flex-direction: column;
349
- gap: 2rem;
350
267
  }
351
268
 
352
269
  .bioImageContainer {
353
- width: 100%;
354
- padding-top: 0;
355
- padding-bottom: 0.8rem;
356
- margin-bottom: 0.8rem;
357
- }
358
-
359
- .imageWrapper {
360
- transform: none;
361
- max-width: 300px;
362
- margin: 0 auto;
270
+ border-right: none;
271
+ border-bottom: 1px solid var(--ifm-color-emphasis-200);
272
+ padding: 2.5rem;
363
273
  }
364
274
 
365
275
  .bioTextContainer {
366
- width: 100%;
367
- gap: 1rem;
368
- }
369
-
370
- .skillsContainer {
371
- padding: 0.6rem 0 0.5rem;
372
- margin-top: 0;
373
- }
374
-
375
- .skillsTitle {
376
- margin-bottom: 1rem;
377
- display: block;
378
- text-align: center;
379
- width: 100%;
380
- }
381
-
382
- .skillsTitle::after {
383
- width: 40px;
384
- left: 50%;
385
- transform: translateX(-50%);
386
- }
387
-
388
- .skillsGrid {
389
- justify-content: center;
276
+ padding: 2rem;
390
277
  }
391
278
  }
392
279
 
393
- @media (max-width: 480px) {
280
+ @media (max-width: 768px) {
394
281
  .aboutSection {
395
- scroll-margin-top: 25px;
396
- padding: 0.5rem 0 2.5rem;
397
- min-height: auto;
398
- }
399
-
400
- .aboutContainer {
401
- padding: 0 1rem;
402
- }
403
-
404
- .aboutHeader {
405
- margin-bottom: 1.4rem;
282
+ padding: 4rem 0;
406
283
  }
407
284
 
408
285
  .aboutHeading {
409
- font-size: 1.8rem;
410
- }
411
-
412
- .aboutContent {
413
- gap: 1.5rem;
414
- }
415
-
416
- .aboutBio {
417
- gap: 1.6rem;
418
- }
419
-
420
- .bioImageContainer {
421
- padding-top: 0;
422
- padding-bottom: 0.3rem;
423
- margin-bottom: 0;
286
+ font-size: 2rem;
424
287
  }
425
288
 
426
289
  .imageWrapper {
427
- max-width: 200px;
428
- margin: 0 auto 0.5rem;
290
+ width: 160px;
291
+ height: 160px;
429
292
  }
430
293
 
431
294
  .aboutParagraph {
432
- font-size: 0.95rem;
433
- line-height: 1.6;
434
- padding-left: 0.6rem;
435
- }
436
-
437
- .aboutParagraph::before {
438
- width: 2px;
439
- }
440
-
441
- .skillsTitle {
442
- font-size: 1.1rem;
443
- margin-bottom: 0.8rem;
444
- text-align: center;
445
- }
446
-
447
- .skillsGrid {
448
- gap: 0.6rem;
449
- justify-content: center;
450
- padding-top: 0.3rem;
451
- }
452
-
453
- .skillBadge {
454
- font-size: 0.8rem;
455
- padding: 0.35rem 0.8rem;
456
- border-radius: 16px;
457
- }
458
-
459
- .bioTextContainer {
460
- gap: 0.6rem;
461
- }
462
-
463
- .skillsContainer {
464
- padding: 0.3rem 0 0.5rem;
465
- }
466
- }
467
-
468
- @media (max-width: 350px) {
469
- .aboutHeading {
470
- font-size: 1.6rem;
471
- }
472
-
473
- .imageWrapper {
474
- max-width: 180px;
475
- }
476
-
477
- .skillBadge {
478
- font-size: 0.75rem;
479
- padding: 0.3rem 0.7rem;
480
- }
481
-
482
- .aboutParagraph {
483
- font-size: 0.9rem;
484
- line-height: 1.5;
295
+ font-size: 1rem;
485
296
  }
486
297
  }
487
298
 
488
299
  @media (prefers-reduced-motion: reduce) {
489
- .aboutHeading,
490
- .aboutContent,
491
- .aboutImage,
492
- .resumeButton,
493
- .skillBadge,
300
+ .aboutCard,
494
301
  .imageWrapper,
495
- .resumeButton::before,
496
- .aboutParagraph {
302
+ .resumeButton,
303
+ .skillTag {
497
304
  animation: none !important;
498
305
  transition: none !important;
499
- opacity: 1;
306
+ opacity: 1 !important;
500
307
  transform: none !important;
501
308
  }
502
309
  }