portosaurus 0.14.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.

Potentially problematic release.


This version of portosaurus might be problematic. Click here for more details.

Files changed (64) hide show
  1. package/.vscode/snippets.code-snippets +79 -0
  2. package/AGENTS.md +37 -0
  3. package/GG/config.js +233 -0
  4. package/GG/package.json +14 -0
  5. package/GG/static/.nojekyll +0 -0
  6. package/GG/static/docusaurus-snippet.css +3 -0
  7. package/GG/static/img/icon-bg.png +0 -0
  8. package/GG/static/img/icon-old.png +0 -0
  9. package/GG/static/img/icon.png +0 -0
  10. package/GG/static/img/project-blank.png +0 -0
  11. package/GG/static/img/social-card.jpeg +0 -0
  12. package/LICENSE +674 -0
  13. package/README.md +57 -0
  14. package/bin/portosaurus.js +136 -0
  15. package/package.json +36 -0
  16. package/src/config/iconMappings.js +329 -0
  17. package/src/config/metaTags.js +240 -0
  18. package/src/config/prism.js +179 -0
  19. package/src/config/sidebar.js +20 -0
  20. package/src/configLoader.js +99 -0
  21. package/src/index.js +79 -0
  22. package/src/pages/index.js +98 -0
  23. package/src/pages/notes.js +88 -0
  24. package/src/pages/tasks.js +251 -0
  25. package/src/theme/components/AboutSection/index.js +67 -0
  26. package/src/theme/components/AboutSection/styles.module.css +492 -0
  27. package/src/theme/components/ContactSection/index.js +87 -0
  28. package/src/theme/components/ContactSection/styles.module.css +327 -0
  29. package/src/theme/components/ExperienceSection/index.js +25 -0
  30. package/src/theme/components/ExperienceSection/styles.module.css +180 -0
  31. package/src/theme/components/HeroSection/index.js +63 -0
  32. package/src/theme/components/HeroSection/styles.module.css +471 -0
  33. package/src/theme/components/NoteIndex/index.js +119 -0
  34. package/src/theme/components/NoteIndex/styles.module.css +143 -0
  35. package/src/theme/components/ProjectsSection/index.js +529 -0
  36. package/src/theme/components/ProjectsSection/styles.module.css +830 -0
  37. package/src/theme/components/ScrollToTop/index.js +98 -0
  38. package/src/theme/components/ScrollToTop/styles.module.css +96 -0
  39. package/src/theme/components/SocialLinks/index.js +129 -0
  40. package/src/theme/components/SocialLinks/styles.module.css +55 -0
  41. package/src/theme/components/Tooltip/index.js +30 -0
  42. package/src/theme/components/Tooltip/styles.module.css +92 -0
  43. package/src/theme/css/bootstrap.css +6 -0
  44. package/src/theme/css/catppuccin.css +632 -0
  45. package/src/theme/css/custom.css +186 -0
  46. package/src/theme/css/tasks.css +868 -0
  47. package/src/theme/staticLink/.nojekyll +0 -0
  48. package/src/theme/staticLink/docusaurus-snippet.css +3 -0
  49. package/src/theme/staticLink/img/icon-bg.png +0 -0
  50. package/src/theme/staticLink/img/icon-old.png +0 -0
  51. package/src/theme/staticLink/img/icon.png +0 -0
  52. package/src/theme/staticLink/img/project-blank.png +0 -0
  53. package/src/theme/staticLink/img/social-card.jpeg +0 -0
  54. package/src/utils/HashNavigation.js +250 -0
  55. package/src/utils/appVersion.js +27 -0
  56. package/src/utils/cssUtils.js +99 -0
  57. package/src/utils/filterEnabledItems.js +21 -0
  58. package/src/utils/generateFavicon.js +256 -0
  59. package/src/utils/generateRobotsTxt.js +97 -0
  60. package/src/utils/iconExtractor.js +159 -0
  61. package/src/utils/imageDownloader.js +88 -0
  62. package/src/utils/imageProcessor.js +134 -0
  63. package/src/utils/linkShortner.js +0 -0
  64. package/src/utils/updateTitle.js +107 -0
@@ -0,0 +1,492 @@
1
+
2
+ /* Animations*/
3
+
4
+ @keyframes skillAppear {
5
+ to {
6
+ opacity: 1;
7
+ transform: translateY(0);
8
+ }
9
+ }
10
+
11
+ @keyframes fadeSlideIn {
12
+ from {
13
+ opacity: 0;
14
+ transform: translateY(10px);
15
+ }
16
+ to {
17
+ opacity: 1;
18
+ transform: translateY(0);
19
+ }
20
+ }
21
+
22
+ @keyframes slideUp {
23
+ from {
24
+ opacity: 0;
25
+ transform: translateY(20px);
26
+ }
27
+ to {
28
+ opacity: 1;
29
+ transform: translateY(0);
30
+ }
31
+ }
32
+
33
+ @keyframes fadeIn {
34
+ from { opacity: 0; }
35
+ to { opacity: 1; }
36
+ }
37
+
38
+
39
+ /* Styles */
40
+
41
+ .aboutSection {
42
+ scroll-margin-top: var(--ifm-scroll-margin-top);
43
+ padding: 0.5rem 0 9.5rem;
44
+ background-color: var(--ifm-background-color);
45
+ min-height: 100vh;
46
+ display: flex;
47
+ align-items: center;
48
+ justify-content: center;
49
+ position: relative;
50
+ width: 100%;
51
+ }
52
+
53
+ .aboutContainer {
54
+ max-width: 1200px;
55
+ margin: 0 auto;
56
+ padding: 0 2rem;
57
+ width: 100%;
58
+ position: relative;
59
+ z-index: 1;
60
+ }
61
+
62
+ .aboutHeader {
63
+ text-align: center;
64
+ margin-bottom: 4.7rem;
65
+ }
66
+
67
+ .aboutHeading {
68
+ font-size: 2.8rem;
69
+ font-weight: 600;
70
+ color: var(--ifm-color-primary);
71
+ margin-bottom: 0.6rem;
72
+ animation: slideUp 0.5s ease-out forwards;
73
+ position: relative;
74
+ display: inline-block;
75
+ }
76
+
77
+ .aboutHeading::after {
78
+ content: '';
79
+ position: absolute;
80
+ width: 30%;
81
+ height: 3px;
82
+ bottom: -0.5rem;
83
+ left: 35%;
84
+ background-color: var(--ifm-color-primary);
85
+ border-radius: 2px;
86
+ }
87
+
88
+ .aboutContent {
89
+ display: flex;
90
+ flex-direction: column;
91
+ gap: 3rem;
92
+ padding: 0;
93
+ animation: fadeIn 0.8s ease-out 0.3s both;
94
+ align-items: center;
95
+ }
96
+
97
+ .aboutBio {
98
+ display: flex;
99
+ flex-direction: row;
100
+ gap: 4rem;
101
+ width: 100%;
102
+ align-items: center;
103
+ }
104
+
105
+ .bioImageContainer {
106
+ flex: 1;
107
+ display: flex;
108
+ justify-content: center;
109
+ align-items: center;
110
+ padding-top: 0;
111
+ align-self: stretch;
112
+ margin-bottom: 1.3rem;
113
+ }
114
+
115
+ .imageWrapper {
116
+ position: relative;
117
+ border-radius: 12px;
118
+ overflow: hidden;
119
+ box-shadow: 0 10px 20px var(--ifm-shadow-color);
120
+ transform: none;
121
+ transition: transform 0.4s ease, box-shadow 0.4s ease;
122
+ max-width: 350px;
123
+ margin: auto 0;
124
+ }
125
+
126
+ .imageWrapper::before {
127
+ content: '';
128
+ position: absolute;
129
+ top: 0;
130
+ left: 0;
131
+ right: 0;
132
+ bottom: 0;
133
+ border: 2px solid var(--ifm-color-primary);
134
+ border-radius: 10px;
135
+ opacity: 0.2;
136
+ pointer-events: none;
137
+ z-index: 1;
138
+ }
139
+
140
+ .imageWrapper:hover {
141
+ transform: translateY(-8px);
142
+ box-shadow: 0 15px 30px var(--ifm-shadow-color);
143
+ }
144
+
145
+ .aboutImage {
146
+ display: block;
147
+ max-width: 100%;
148
+ height: auto;
149
+ border-radius: 8px;
150
+ object-fit: cover;
151
+ transition: filter 0.3s ease;
152
+ }
153
+
154
+ .bioTextContainer {
155
+ flex: 1.5;
156
+ display: flex;
157
+ flex-direction: column;
158
+ gap: 1.2rem;
159
+ align-self: flex-start;
160
+ }
161
+
162
+ .bioText {
163
+ display: flex;
164
+ flex-direction: column;
165
+ gap: 8px;
166
+ align-self: flex-start;
167
+ margin-top: -0.5rem;
168
+ }
169
+
170
+ .aboutParagraph {
171
+ margin-bottom: 0.2rem;
172
+ font-size: 1.05rem;
173
+ line-height: 1.8;
174
+ color: var(--ifm-font-color-base);
175
+ position: relative;
176
+ padding-left: 0.8rem;
177
+ opacity: 0;
178
+ animation: fadeSlideIn 0.5s ease-out forwards;
179
+ animation-delay: calc(0.3s + var(--paragraph-index, 0) * 0.15s);
180
+ }
181
+
182
+ .aboutParagraph:last-child {
183
+ margin-bottom: 0;
184
+ }
185
+
186
+ .aboutParagraph::before {
187
+ content: '';
188
+ position: absolute;
189
+ left: 0;
190
+ top: 0.5rem;
191
+ bottom: 0.5rem;
192
+ width: 3px;
193
+ background: linear-gradient(to bottom, var(--ifm-color-primary), transparent);
194
+ border-radius: 4px;
195
+ opacity: 0.7;
196
+ }
197
+
198
+ .resumeButtonWrapper {
199
+ margin-top: 1rem;
200
+ }
201
+
202
+ .resumeButton {
203
+ display: inline-block;
204
+ padding: 0.6rem 1.5rem;
205
+ font-size: 0.95rem;
206
+ font-weight: 500;
207
+ text-decoration: none;
208
+ color: var(--ifm-background-color);
209
+ background-color: var(--ifm-color-primary);
210
+ border-radius: 4px;
211
+ transition: all 0.3s ease, transform 0.2s ease;
212
+ border: 2px solid var(--ifm-color-primary);
213
+ position: relative;
214
+ overflow: hidden;
215
+ z-index: 1;
216
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
217
+ }
218
+
219
+ .resumeButton::before {
220
+ content: '';
221
+ position: absolute;
222
+ top: 0;
223
+ left: -100%;
224
+ width: 100%;
225
+ height: 100%;
226
+ background: linear-gradient(
227
+ 90deg,
228
+ transparent,
229
+ rgba(255, 255, 255, 0.2),
230
+ transparent
231
+ );
232
+ transition: left 0.7s ease;
233
+ z-index: -1;
234
+ }
235
+
236
+ .resumeButton:hover {
237
+ background-color: transparent;
238
+ color: var(--ifm-color-primary);
239
+ transform: translateY(-3px);
240
+ box-shadow: 0 6px 15px rgba(0, 0, 0, 0.2);
241
+ text-decoration: none;
242
+ }
243
+
244
+ .resumeButton:hover::before {
245
+ left: 100%;
246
+ }
247
+
248
+ .buttonText {
249
+ position: relative;
250
+ z-index: 2;
251
+ }
252
+
253
+ .skillsContainer {
254
+ width: 100%;
255
+ padding: 0.8rem 0 0.5rem;
256
+ position: relative;
257
+ overflow: hidden;
258
+ margin-top: 0;
259
+ }
260
+
261
+ .skillsTitle {
262
+ font-size: 1.4rem;
263
+ margin-bottom: 1.2rem;
264
+ color: var(--ifm-color-primary);
265
+ font-weight: 600;
266
+ padding-left: 0;
267
+ position: relative;
268
+ display: inline-block;
269
+ }
270
+
271
+ .skillsTitle::after {
272
+ content: '';
273
+ position: absolute;
274
+ width: 40%;
275
+ height: 2px;
276
+ bottom: -0.4rem;
277
+ left: 0;
278
+ background-color: var(--ifm-color-primary);
279
+ opacity: 0.5;
280
+ border-radius: 2px;
281
+ }
282
+
283
+ .skillsGrid {
284
+ display: flex;
285
+ flex-wrap: wrap;
286
+ gap: 0.9rem;
287
+ padding-left: 0;
288
+ padding-top: 0.4rem;
289
+ margin-bottom: 0.5rem;
290
+ }
291
+
292
+ .skillBadge {
293
+ background-color: rgba(var(--ctp-lavender-rgb), 0.08);
294
+ color: var(--ctp-lavender);
295
+ border-radius: 20px;
296
+ padding: 0.5rem 1rem;
297
+ font-size: 0.95rem;
298
+ font-weight: 500;
299
+ transition: all 0.3s ease;
300
+ border: 1px solid rgba(var(--ctp-lavender-rgb), 0.15);
301
+ display: flex;
302
+ align-items: center;
303
+ justify-content: center;
304
+ opacity: 0;
305
+ animation: skillAppear 0.4s ease-out forwards;
306
+ transform: translateY(10px);
307
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
308
+ }
309
+
310
+ .skillBadge:hover {
311
+ transform: translateY(-3px);
312
+ box-shadow: 0 5px 12px rgba(0, 0, 0, 0.1);
313
+ background-color: rgba(var(--ctp-lavender-rgb), 0.15);
314
+ border-color: rgba(var(--ctp-lavender-rgb), 0.3);
315
+ }
316
+
317
+ /* Responsive styles */
318
+ @media (max-width: 992px) {
319
+ .aboutBio {
320
+ gap: 3rem;
321
+ }
322
+ }
323
+
324
+ @media (max-width: 768px) {
325
+ .aboutSection {
326
+ scroll-margin-top: var(--ifm-scroll-margin-top-mobile);
327
+ padding: 1.5rem 0 4rem;
328
+ }
329
+
330
+ .aboutContainer {
331
+ padding: 0 1.5rem;
332
+ }
333
+
334
+ .aboutHeader {
335
+ margin-bottom: 2rem;
336
+ }
337
+
338
+ .aboutHeading {
339
+ font-size: 2.4rem;
340
+ }
341
+
342
+ .aboutBio {
343
+ flex-direction: column;
344
+ gap: 2rem;
345
+ }
346
+
347
+ .bioImageContainer {
348
+ width: 100%;
349
+ padding-top: 0;
350
+ padding-bottom: 0.8rem;
351
+ margin-bottom: 0.8rem;
352
+ }
353
+
354
+ .imageWrapper {
355
+ transform: none;
356
+ max-width: 300px;
357
+ margin: 0 auto;
358
+ }
359
+
360
+ .bioTextContainer {
361
+ width: 100%;
362
+ gap: 1rem;
363
+ }
364
+
365
+ .skillsContainer {
366
+ padding: 0.6rem 0 0.5rem;
367
+ margin-top: 0;
368
+ }
369
+
370
+ .skillsTitle {
371
+ margin-bottom: 1rem;
372
+ display: block;
373
+ text-align: center;
374
+ width: 100%;
375
+ }
376
+
377
+ .skillsTitle::after {
378
+ width: 40px;
379
+ left: 50%;
380
+ transform: translateX(-50%);
381
+ }
382
+
383
+ .skillsGrid {
384
+ justify-content: center;
385
+ }
386
+ }
387
+
388
+ @media (max-width: 480px) {
389
+ .aboutSection {
390
+ scroll-margin-top: 25px;
391
+ padding: 0.5rem 0 2.5rem;
392
+ min-height: auto;
393
+ }
394
+
395
+ .aboutContainer {
396
+ padding: 0 1rem;
397
+ }
398
+
399
+ .aboutHeader {
400
+ margin-bottom: 1.4rem;
401
+ }
402
+
403
+ .aboutHeading {
404
+ font-size: 1.8rem;
405
+ }
406
+
407
+ .aboutContent {
408
+ gap: 1.5rem;
409
+ }
410
+
411
+ .aboutBio {
412
+ gap: 1.6rem;
413
+ }
414
+
415
+ .bioImageContainer {
416
+ padding-top: 0;
417
+ padding-bottom: 0.3rem;
418
+ margin-bottom: 0;
419
+ }
420
+
421
+ .imageWrapper {
422
+ max-width: 200px;
423
+ margin: 0 auto 0.5rem;
424
+ }
425
+
426
+ .aboutParagraph {
427
+ font-size: 0.95rem;
428
+ line-height: 1.6;
429
+ padding-left: 0.6rem;
430
+ }
431
+
432
+ .aboutParagraph::before {
433
+ width: 2px;
434
+ }
435
+
436
+ .skillsTitle {
437
+ font-size: 1.1rem;
438
+ margin-bottom: 0.8rem;
439
+ text-align: center;
440
+ }
441
+
442
+ .skillsGrid {
443
+ gap: 0.6rem;
444
+ justify-content: center;
445
+ padding-top: 0.3rem;
446
+ }
447
+
448
+ .skillBadge {
449
+ font-size: 0.8rem;
450
+ padding: 0.35rem 0.8rem;
451
+ border-radius: 16px;
452
+ }
453
+
454
+ .bioTextContainer {
455
+ gap: 0.6rem;
456
+ }
457
+
458
+ .skillsContainer {
459
+ padding: 0.3rem 0 0.5rem;
460
+ }
461
+ }
462
+
463
+ @media (max-width: 350px) {
464
+ .aboutHeading {
465
+ font-size: 1.6rem;
466
+ }
467
+
468
+ .imageWrapper {
469
+ max-width: 180px;
470
+ }
471
+
472
+ .skillBadge {
473
+ font-size: 0.75rem;
474
+ padding: 0.3rem 0.7rem;
475
+ }
476
+
477
+ .aboutParagraph {
478
+ font-size: 0.9rem;
479
+ line-height: 1.5;
480
+ }
481
+ }
482
+
483
+ @media (prefers-reduced-motion: reduce) {
484
+ .aboutHeading, .aboutContent, .aboutImage,
485
+ .resumeButton, .skillBadge, .imageWrapper, .resumeButton::before,
486
+ .aboutParagraph {
487
+ animation: none !important;
488
+ transition: none !important;
489
+ opacity: 1;
490
+ transform: none !important;
491
+ }
492
+ }
@@ -0,0 +1,87 @@
1
+ import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
2
+ import { iconMap } from "@site/src/config/iconMappings";
3
+ import { FaQuestionCircle } from "react-icons/fa";
4
+ import styles from './styles.module.css';
5
+
6
+ const sortEmail = (links) => {
7
+ return [...links].sort((a, b) => {
8
+ const isEmailA = a.url?.startsWith('mailto:') ||
9
+ a.icon?.toLowerCase().includes('email') ||
10
+ a.name?.toLowerCase().includes('email');
11
+
12
+ const isEmailB = b.url?.startsWith('mailto:') ||
13
+ b.icon?.toLowerCase().includes('email') ||
14
+ b.name?.toLowerCase().includes('email');
15
+
16
+ if (isEmailA && !isEmailB) return -1;
17
+ if (!isEmailA && isEmailB) return 1;
18
+
19
+ return 0;
20
+ });
21
+ };
22
+
23
+ export default function ContactSection({ id, className, title, subtitle }) {
24
+ const { siteConfig } = useDocusaurusContext();
25
+ const { customFields } = siteConfig;
26
+ let socialLinks = customFields.socialLinks.links || [];
27
+
28
+ socialLinks = sortEmail(socialLinks);
29
+
30
+ return (
31
+ <div id={id} className={`${styles.contactSection} ${className || ''}`} role="region" aria-label="Contact section">
32
+ <div className={styles.contactContainer}>
33
+ <div className={styles.contactHeader}>
34
+ <h2 className={styles.contactTitle}>
35
+ {title || "Get In Touch"}
36
+ </h2>
37
+ <p className={styles.contactSubtitle}>
38
+ {subtitle || "Feel free to reach out for collaborations, questions, or just to say hello!"}
39
+ </p>
40
+ </div>
41
+
42
+ {/* SocialCard */}
43
+ <div className={styles.gridWrapper}>
44
+ <div className={styles.socialGrid} role="list" aria-label="Social media and contact links">
45
+ {socialLinks.map((social, index) => {
46
+ const iconData = iconMap[social.icon] || {};
47
+
48
+ const name = social.name || "?";
49
+ const Icon = iconData.icon || FaQuestionCircle;
50
+ const iconColor = iconData.color || "#3578e5";
51
+ const description = name === "?" ? "" : (social.desc || `Connect with me on ${name}`);
52
+ const url = social.url;
53
+
54
+ return (
55
+ <a
56
+ key={name}
57
+ href={url}
58
+ target="_blank"
59
+ rel="noopener noreferrer"
60
+ className={styles.socialCard}
61
+ style={{
62
+ "--card-index": index,
63
+ "--icon-hover-color": iconColor,
64
+ }}
65
+ aria-label={`Connect with me on ${name}: ${description}`}
66
+ role="listitem"
67
+ >
68
+ {Icon && (
69
+ <div className={styles.socialIcon}>
70
+ <Icon aria-hidden="true" />
71
+ </div>
72
+ )}
73
+ <h3 className={styles.socialTitle}>
74
+ {name}
75
+ </h3>
76
+ <p className={styles.socialDesc}>
77
+ {description}
78
+ </p>
79
+ </a>
80
+ );
81
+ })}
82
+ </div>
83
+ </div>
84
+ </div>
85
+ </div>
86
+ );
87
+ }