portosaurus 2.0.3 → 2.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.
Files changed (91) hide show
  1. package/bin/portosaurus.mjs +14 -327
  2. package/package.json +16 -11
  3. package/src/cli/build.mjs +43 -0
  4. package/src/cli/dev.mjs +31 -0
  5. package/src/cli/init.mjs +135 -0
  6. package/src/cli/serve.mjs +30 -0
  7. package/src/core/buildDocuConfig.mjs +664 -0
  8. package/src/core/{themePlugin.mjs → plugins/themePlugin.mjs} +1 -1
  9. package/src/template/.github/workflows/deploy.yml +52 -0
  10. package/src/template/.nojekyll +0 -0
  11. package/src/template/README.md +58 -0
  12. package/src/template/blog/authors.yml +1 -1
  13. package/src/template/blog/welcome.md +1 -1
  14. package/src/template/config.js +40 -23
  15. package/src/template/package.json +20 -0
  16. package/src/template/static/img/svg/icon-blog.svg +2 -0
  17. package/src/template/static/img/svg/icon-note.svg +2 -0
  18. package/src/{components → theme/components}/AboutSection/index.js +22 -13
  19. package/src/{components → theme/components}/AboutSection/styles.module.css +59 -48
  20. package/src/{components → theme/components}/ContactSection/index.js +31 -24
  21. package/src/{components → theme/components}/ContactSection/styles.module.css +31 -26
  22. package/src/{components → theme/components}/ExperienceSection/index.js +12 -7
  23. package/src/{components → theme/components}/ExperienceSection/styles.module.css +23 -20
  24. package/src/{components → theme/components}/HeroSection/index.js +9 -11
  25. package/src/{components → theme/components}/HeroSection/styles.module.css +44 -32
  26. package/src/{components → theme/components}/NoteIndex/index.js +10 -3
  27. package/src/{components → theme/components}/Preview/components/PreviewHeader.js +14 -8
  28. package/src/{components → theme/components}/Preview/components/Triggers/Pv.js +32 -7
  29. package/src/{components → theme/components}/Preview/components/Triggers/SrcPv.js +1 -5
  30. package/src/theme/components/Preview/index.js +3 -0
  31. package/src/{components → theme/components}/ProjectsSection/index.js +279 -224
  32. package/src/{components → theme/components}/ProjectsSection/styles.module.css +21 -17
  33. package/src/{components → theme/components}/ScrollToTop/index.js +18 -21
  34. package/src/{components → theme/components}/ScrollToTop/styles.module.css +10 -9
  35. package/src/theme/components/SocialLinks/index.js +125 -0
  36. package/src/{components → theme/components}/SocialLinks/styles.module.css +9 -7
  37. package/src/{components → theme/components}/Tooltip/index.js +4 -1
  38. package/src/theme/config/iconMappings.js +465 -0
  39. package/src/theme/config/metaTags.js +239 -0
  40. package/src/theme/config/prism.js +179 -0
  41. package/src/theme/config/sidebar.js +17 -0
  42. package/src/{css → theme/css}/bootstrap.css +0 -1
  43. package/src/theme/css/catppuccin.css +618 -0
  44. package/src/{css → theme/css}/custom.css +3 -9
  45. package/src/{css → theme/css}/tasks.css +43 -37
  46. package/src/theme/{MDXComponents.js → overrides/MDXComponents.js} +3 -3
  47. package/src/theme/{Root.js → overrides/Root.js} +2 -4
  48. package/src/{pages → theme/pages}/index.js +23 -39
  49. package/src/theme/pages/notes.js +83 -0
  50. package/src/{pages → theme/pages}/tasks.js +115 -56
  51. package/src/{core/client-utils → theme/utils}/HashNavigation.js +60 -49
  52. package/src/{core/client-utils → theme/utils}/updateTitle.js +21 -25
  53. package/src/{core/build-utils → utils/build}/cssUtils.mjs +5 -3
  54. package/src/{core/build-utils → utils/build}/generateFavicon.mjs +44 -12
  55. package/src/{core/build-utils → utils/build}/generateRobotsTxt.mjs +4 -3
  56. package/src/{core/build-utils → utils/build}/iconExtractor.mjs +7 -3
  57. package/src/utils/build/imageDownloader.mjs +159 -0
  58. package/src/{core/build-utils → utils/build}/imageProcessor.mjs +5 -6
  59. package/src/utils/helpers.mjs +153 -0
  60. package/src/utils/logger.mjs +53 -0
  61. package/src/utils/packageManager.mjs +88 -0
  62. package/src/components/Preview/index.js +0 -3
  63. package/src/components/SocialLinks/index.js +0 -130
  64. package/src/config/iconMappings.js +0 -329
  65. package/src/config/metaTags.js +0 -240
  66. package/src/config/prism.js +0 -179
  67. package/src/config/sidebar.js +0 -20
  68. package/src/core/build-utils/imageDownloader.mjs +0 -98
  69. package/src/core/createDocuConf.mjs +0 -472
  70. package/src/core/defaults.mjs +0 -67
  71. package/src/core/logger.mjs +0 -17
  72. package/src/core/packageManager.mjs +0 -72
  73. package/src/css/catppuccin.css +0 -632
  74. package/src/pages/notes.js +0 -87
  75. /package/src/template/notes/{welcome.md → welcome.mdx} +0 -0
  76. /package/src/{components → theme/components}/NoteIndex/styles.module.css +0 -0
  77. /package/src/{components → theme/components}/Preview/components/FeedbackStates.js +0 -0
  78. /package/src/{components → theme/components}/Preview/components/FileTabs.js +0 -0
  79. /package/src/{components → theme/components}/Preview/components/Triggers/index.js +0 -0
  80. /package/src/{components → theme/components}/Preview/components/ViewerWindow.js +0 -0
  81. /package/src/{components → theme/components}/Preview/hooks/useDeepLinkHash.js +0 -0
  82. /package/src/{components → theme/components}/Preview/hooks/useDockLayout.js +0 -0
  83. /package/src/{components → theme/components}/Preview/hooks/useFileFetch.js +0 -0
  84. /package/src/{components → theme/components}/Preview/renderers/CodeRenderer.js +0 -0
  85. /package/src/{components → theme/components}/Preview/renderers/ImageRenderer.js +0 -0
  86. /package/src/{components → theme/components}/Preview/renderers/PdfRenderer.js +0 -0
  87. /package/src/{components → theme/components}/Preview/renderers/WebRenderer.js +0 -0
  88. /package/src/{components → theme/components}/Preview/state/index.js +0 -0
  89. /package/src/{components → theme/components}/Preview/styles.module.css +0 -0
  90. /package/src/{components → theme/components}/Preview/utils/index.js +0 -0
  91. /package/src/{components → theme/components}/Tooltip/styles.module.css +0 -0
@@ -1,4 +1,3 @@
1
-
2
1
  /* Animations */
3
2
  @keyframes fadeIn {
4
3
  from {
@@ -95,7 +94,10 @@
95
94
  opacity: 0;
96
95
  animation: fadeIn 0.5s ease-out forwards;
97
96
  height: 100%;
98
- transition: transform 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease;
97
+ transition:
98
+ transform 0.3s ease,
99
+ box-shadow 0.3s ease,
100
+ border-color 0.3s ease;
99
101
  border: 1px solid var(--ifm-shadow-color);
100
102
  width: 100%;
101
103
  }
@@ -181,7 +183,7 @@
181
183
  }
182
184
 
183
185
  .projectStateLabel {
184
- font-size: 0.65rem;
186
+ font-size: 0.65rem;
185
187
  font-weight: 500;
186
188
  padding: 1px 4px;
187
189
  border-radius: var(--ifm-global-radius);
@@ -329,7 +331,9 @@
329
331
  justify-content: center;
330
332
  cursor: pointer;
331
333
  z-index: 5;
332
- transition: opacity 0.2s ease, background-color 0.2s ease;
334
+ transition:
335
+ opacity 0.2s ease,
336
+ background-color 0.2s ease;
333
337
  padding: 0;
334
338
  box-shadow: var(--ifm-global-shadow-md);
335
339
  }
@@ -408,12 +412,12 @@
408
412
  overflow-x: auto;
409
413
  overflow-y: hidden;
410
414
  -webkit-overflow-scrolling: touch;
411
- scrollbar-width: none;
412
- -ms-overflow-style: none;
415
+ scrollbar-width: none;
416
+ -ms-overflow-style: none;
413
417
  display: flex;
414
418
  justify-content: center;
415
419
  padding: 0.8rem 0;
416
- max-width: 60vw;
420
+ max-width: 60vw;
417
421
  scroll-padding: 0 20px;
418
422
  margin: 0 5px;
419
423
  position: relative;
@@ -459,7 +463,7 @@
459
463
  /* Center alignment for dots */
460
464
  .centerDots {
461
465
  display: flex !important;
462
- justify-content: center !important;
466
+ justify-content: center !important;
463
467
  text-align: center !important;
464
468
  margin: 0 auto;
465
469
  }
@@ -586,7 +590,7 @@
586
590
  display: flex;
587
591
  justify-content: center;
588
592
  }
589
-
593
+
590
594
  .mobileNavigationControls .centerDots {
591
595
  margin: 0 auto;
592
596
  }
@@ -598,7 +602,7 @@
598
602
  width: 40px;
599
603
  height: 40px;
600
604
  flex-shrink: 0;
601
- z-index: 10;
605
+ z-index: 10;
602
606
  }
603
607
 
604
608
  .mobileNavigationControls .carouselControl:hover {
@@ -628,25 +632,25 @@
628
632
  }
629
633
 
630
634
  .mobileNavigationControls .dotsScrollContainer {
631
- justify-content: flex-start;
635
+ justify-content: flex-start;
632
636
  padding-left: 10px;
633
- min-height: 40px;
637
+ min-height: 40px;
634
638
  align-items: center;
635
639
  }
636
-
640
+
637
641
  .mobileNavigationControls .centerDots {
638
642
  justify-content: center !important;
639
643
  padding-left: 0;
640
644
  }
641
-
645
+
642
646
  .mobileNavigationControls .navDot:first-child {
643
647
  margin-left: 2px;
644
648
  }
645
-
649
+
646
650
  .mobileNavigationControls .activeDot {
647
651
  transform: scale(1.6);
648
652
  opacity: 1;
649
- box-shadow: 0 0 0 2px rgba(var(--ifm-color-primary-rgb), 0.5);
653
+ box-shadow: 0 0 0 2px rgba(var(--ifm-color-primary-rgb), 0.5);
650
654
  }
651
655
  }
652
656
 
@@ -799,7 +803,7 @@
799
803
 
800
804
  .mobileNavigationControls .activeDot {
801
805
  box-shadow: 0 0 0 1.5px rgba(var(--ifm-color-primary-rgb), 0.4);
802
- transform: scale(1.5);
806
+ transform: scale(1.5);
803
807
  }
804
808
  }
805
809
 
@@ -1,6 +1,6 @@
1
- import { useState, useEffect, useRef } from 'react';
2
- import { IoIosArrowUp } from 'react-icons/io';
3
- import styles from './styles.module.css';
1
+ import { useState, useEffect, useRef } from "react";
2
+ import { IoIosArrowUp } from "react-icons/io";
3
+ import styles from "./styles.module.css";
4
4
 
5
5
  export default function ScrollToTop({ hideDelay = 1500 }) {
6
6
  const [isVisible, setIsVisible] = useState(false);
@@ -9,12 +9,11 @@ export default function ScrollToTop({ hideDelay = 1500 }) {
9
9
  const lastScrollTopRef = useRef(0);
10
10
 
11
11
  const startHideTimer = () => {
12
-
13
12
  // Clear any existing timeout
14
13
  if (timeoutRef.current) {
15
14
  clearTimeout(timeoutRef.current);
16
15
  }
17
-
16
+
18
17
  // Only start timer if not hovering
19
18
  if (!isHovering) {
20
19
  timeoutRef.current = setTimeout(() => {
@@ -24,23 +23,21 @@ export default function ScrollToTop({ hideDelay = 1500 }) {
24
23
  };
25
24
 
26
25
  useEffect(() => {
27
-
28
26
  const handleScroll = () => {
29
- const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
27
+ const scrollTop =
28
+ window.pageYOffset || document.documentElement.scrollTop;
30
29
  const isScrollingUp = scrollTop < lastScrollTopRef.current;
31
-
30
+
32
31
  // Save the current scroll position
33
32
  lastScrollTopRef.current = scrollTop;
34
-
33
+
35
34
  // Show button when scrolling up past threshold
36
35
  if (isScrollingUp && scrollTop > 300) {
37
-
38
36
  setIsVisible(true);
39
37
  startHideTimer();
40
38
  } else {
41
-
42
39
  setIsVisible(false);
43
-
40
+
44
41
  if (timeoutRef.current) {
45
42
  clearTimeout(timeoutRef.current);
46
43
  }
@@ -48,11 +45,11 @@ export default function ScrollToTop({ hideDelay = 1500 }) {
48
45
  };
49
46
 
50
47
  // Set up event listener
51
- window.addEventListener('scroll', handleScroll, { passive: true });
52
-
48
+ window.addEventListener("scroll", handleScroll, { passive: true });
49
+
53
50
  // Clean up
54
51
  return () => {
55
- window.removeEventListener('scroll', handleScroll);
52
+ window.removeEventListener("scroll", handleScroll);
56
53
  if (timeoutRef.current) {
57
54
  clearTimeout(timeoutRef.current);
58
55
  }
@@ -60,7 +57,6 @@ export default function ScrollToTop({ hideDelay = 1500 }) {
60
57
  }, [hideDelay, isHovering]);
61
58
 
62
59
  const handleMouseEnter = () => {
63
-
64
60
  setIsHovering(true);
65
61
 
66
62
  if (timeoutRef.current) {
@@ -69,23 +65,24 @@ export default function ScrollToTop({ hideDelay = 1500 }) {
69
65
  };
70
66
 
71
67
  const handleMouseLeave = () => {
72
-
73
68
  setIsHovering(false);
74
69
  startHideTimer();
75
70
  };
76
71
 
77
72
  const scrollToTop = () => {
78
- const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
79
-
73
+ const prefersReducedMotion = window.matchMedia(
74
+ "(prefers-reduced-motion: reduce)",
75
+ ).matches;
76
+
80
77
  window.scrollTo({
81
78
  top: 0,
82
- behavior: prefersReducedMotion ? 'auto' : 'smooth'
79
+ behavior: prefersReducedMotion ? "auto" : "smooth",
83
80
  });
84
81
  };
85
82
 
86
83
  return (
87
84
  <button
88
- className={`${styles.scrollToTop} ${isVisible ? styles.visible : ''}`}
85
+ className={`${styles.scrollToTop} ${isVisible ? styles.visible : ""}`}
89
86
  onClick={scrollToTop}
90
87
  onMouseEnter={handleMouseEnter}
91
88
  onMouseLeave={handleMouseLeave}
@@ -17,7 +17,10 @@
17
17
  opacity: 0;
18
18
  transform: translateY(20px) scale(0.9);
19
19
  pointer-events: none;
20
- transition: opacity 0.3s ease, transform 0.3s ease, background-color 0.3s ease;
20
+ transition:
21
+ opacity 0.3s ease,
22
+ transform 0.3s ease,
23
+ background-color 0.3s ease;
21
24
  }
22
25
 
23
26
  .scrollToTop.visible {
@@ -46,14 +49,13 @@
46
49
 
47
50
  /* Responsive adjustments */
48
51
  @media (max-width: 768px) {
49
-
50
52
  .scrollToTop {
51
53
  width: 45px;
52
54
  height: 45px;
53
55
  bottom: 25px;
54
56
  right: 25px;
55
57
  }
56
-
58
+
57
59
  .scrollToTop svg {
58
60
  width: 24px;
59
61
  height: 24px;
@@ -61,27 +63,26 @@
61
63
  }
62
64
 
63
65
  @media (max-width: 480px) {
64
-
65
66
  .scrollToTop {
66
- width: 40px;
67
+ width: 40px;
67
68
  height: 40px;
68
69
  bottom: 20px;
69
70
  right: 50%;
70
71
  transform: translateX(50%) translateY(20px) scale(0.9);
71
72
  }
72
-
73
+
73
74
  .scrollToTop.visible {
74
75
  transform: translateX(50%) scale(1);
75
76
  }
76
-
77
+
77
78
  .scrollToTop:hover {
78
79
  transform: translateX(50%) translateY(-3px) scale(1.05);
79
80
  }
80
-
81
+
81
82
  .scrollToTop:active {
82
83
  transform: translateX(50%) translateY(-1px) scale(1.02);
83
84
  }
84
-
85
+
85
86
  .scrollToTop svg {
86
87
  width: 22px;
87
88
  height: 22px;
@@ -0,0 +1,125 @@
1
+ import { useState, useEffect, useMemo, useCallback } from "react";
2
+ import styles from "./styles.module.css";
3
+ import { FaQuestionCircle } from "react-icons/fa";
4
+
5
+ import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
6
+ import useIsBrowser from "@docusaurus/useIsBrowser";
7
+
8
+ import Tooltip from "../Tooltip";
9
+ import { iconMap } from "../../config/iconMappings";
10
+
11
+ // Default icon & icon
12
+ const DEFAULT_ICON = FaQuestionCircle;
13
+ const DEFAULT_COLOR = "var(--ifm-color-primary)";
14
+
15
+ export default function SocialIcons({ showAll = false }) {
16
+ const { siteConfig } = useDocusaurusContext();
17
+ const { customFields } = siteConfig;
18
+ const isBrowser = useIsBrowser();
19
+
20
+ const [animationDelays, setAnimationDelays] = useState({});
21
+
22
+ const allSocialLinks = customFields.socialLinks.links || [];
23
+
24
+ // FIX: `to prevent unnecessary recalculations`
25
+ const socialLinks = useMemo(() => {
26
+ return showAll ? allSocialLinks : allSocialLinks.filter((link) => link.pin);
27
+ }, [allSocialLinks, showAll]);
28
+
29
+ // Calculate delays based on screen size
30
+ const calculateDelays = useCallback(() => {
31
+ if (!isBrowser) return {};
32
+
33
+ const isTablet = window.innerWidth <= 768;
34
+ const isMobile = window.innerWidth <= 480;
35
+ const delays = {};
36
+
37
+ const baseDelay = isMobile ? 0.7 : isTablet ? 0.9 : 1.3;
38
+ const incrementDelay = 0.1;
39
+
40
+ socialLinks.forEach((_, index) => {
41
+ delays[index] = `${baseDelay + index * incrementDelay}s`;
42
+ });
43
+
44
+ return delays;
45
+ }, [isBrowser, socialLinks]);
46
+
47
+ useEffect(() => {
48
+ if (!isBrowser) return;
49
+
50
+ // Set initial delays
51
+ setAnimationDelays(calculateDelays());
52
+
53
+ const handleResize = () => {
54
+ setAnimationDelays(calculateDelays());
55
+ };
56
+
57
+ window.addEventListener("resize", handleResize);
58
+ return () => window.removeEventListener("resize", handleResize);
59
+ }, [isBrowser, calculateDelays]);
60
+
61
+ // Get icon component and color
62
+ const getIconDetails = (iconName) => {
63
+ if (!iconName) {
64
+ return {
65
+ icon: DEFAULT_ICON,
66
+ color: DEFAULT_COLOR,
67
+ };
68
+ }
69
+
70
+ const formattedIconName = iconName.toLowerCase();
71
+ const iconDetails = iconMap[formattedIconName];
72
+
73
+ if (!iconDetails) {
74
+ return {
75
+ icon: DEFAULT_ICON,
76
+ color: DEFAULT_COLOR,
77
+ };
78
+ }
79
+
80
+ return {
81
+ icon: iconDetails.icon,
82
+ color: iconDetails.color || DEFAULT_COLOR,
83
+ };
84
+ };
85
+
86
+ if (socialLinks.length === 0) {
87
+ return null;
88
+ }
89
+
90
+ return (
91
+ <div className={styles.socialIcons}>
92
+ {socialLinks.map((social, index) => {
93
+ const { icon: IconComponent, color: iconColor } = getIconDetails(
94
+ social.icon,
95
+ );
96
+ const href = social.url || "#";
97
+ const displayColor = social.color || iconColor;
98
+
99
+ return (
100
+ <Tooltip
101
+ key={index}
102
+ msg={social.desc || social.icon || "Link"}
103
+ position="top"
104
+ color={displayColor}
105
+ underline={false}
106
+ >
107
+ <a
108
+ href={href}
109
+ target="_blank"
110
+ rel="noopener noreferrer"
111
+ className={styles.socialLink}
112
+ style={{
113
+ "--hover-color": displayColor,
114
+ animationDelay: animationDelays[index] || "0s",
115
+ }}
116
+ aria-label={social.icon || "social link"}
117
+ >
118
+ <IconComponent size={24} />
119
+ </a>
120
+ </Tooltip>
121
+ );
122
+ })}
123
+ </div>
124
+ );
125
+ }
@@ -1,11 +1,13 @@
1
-
2
1
  /* Animation */
3
2
  @keyframes fadeIn {
4
- from { opacity: 0; }
5
- to { opacity: 1; }
3
+ from {
4
+ opacity: 0;
5
+ }
6
+ to {
7
+ opacity: 1;
8
+ }
6
9
  }
7
10
 
8
-
9
11
  .socialIcons {
10
12
  display: flex;
11
13
  align-items: center;
@@ -18,7 +20,9 @@
18
20
  align-items: center;
19
21
  justify-content: center;
20
22
  color: var(--ifm-color-primary);
21
- transition: color 0.3s, transform 0.2s;
23
+ transition:
24
+ color 0.3s,
25
+ transform 0.2s;
22
26
  position: relative;
23
27
  animation: fadeIn 0.3s ease-out forwards;
24
28
  opacity: 0;
@@ -31,7 +35,6 @@
31
35
  color: var(--hover-color, var(--ifm-color-primary-dark));
32
36
  }
33
37
 
34
-
35
38
  /* Responsive */
36
39
  @media (max-width: 768px) {
37
40
  .socialIcons {
@@ -42,7 +45,6 @@
42
45
  .socialLink {
43
46
  margin: 0 9px;
44
47
  }
45
-
46
48
  }
47
49
 
48
50
  /* Accessibility */
@@ -14,7 +14,10 @@ export default function Tooltip({
14
14
  const containerRef = useRef(null);
15
15
 
16
16
  const tooltipStyle = color
17
- ? { "--tooltip-color": color, "--tooltip-text-color": "var(--ifm-font-color-base-inverse)" }
17
+ ? {
18
+ "--tooltip-color": color,
19
+ "--tooltip-text-color": "var(--ifm-font-color-base-inverse)",
20
+ }
18
21
  : {};
19
22
 
20
23
  const show = useCallback(() => {