mirror of
				https://github.com/imfing/hextra.git
				synced 2025-10-31 15:44:51 -04:00 
			
		
		
		
	Compare commits
	
		
			42 Commits
		
	
	
		
			v0.3.0
			...
			122-improv
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 9fc253dff5 | ||
|   | 0125822785 | ||
|   | 1e1d1c8716 | ||
|   | 1048ee47d7 | ||
|   | 5842f893a3 | ||
|   | 78ce7c2f2e | ||
|   | 0652772c15 | ||
|   | 13e4eb3414 | ||
|   | 529fcd8a62 | ||
|   | 21a13c49f9 | ||
|   | 98d0a3dc73 | ||
|   | 24f3178ea8 | ||
|   | 230cc438b7 | ||
|   | 214cb7994f | ||
|   | 792ad4b569 | ||
|   | 97e6945c04 | ||
|   | 93cb788e52 | ||
|   | 88b0f1b2ab | ||
|   | a31b46f5e3 | ||
|   | 6641d36b98 | ||
|   | e42d01898a | ||
|   | 6cd4c55613 | ||
|   | cb09b7ce1e | ||
|   | 96c6ff073f | ||
|   | 28a20e1e7e | ||
|   | 5f4c7423d0 | ||
|   | 2bc4ed19e3 | ||
|   | 8aa6439132 | ||
|   | b7558aca44 | ||
|   | 55ff819dae | ||
|   | 924d8508d0 | ||
|   | 1b932f260a | ||
|   | 5768ed4695 | ||
|   | f4cea168b1 | ||
|   | e2d00fdcd0 | ||
|   | 103faa24f3 | ||
|   | d1bed05843 | ||
|   | 2df3c563bf | ||
|   | ec02eb34fe | ||
|   | 46dea718e6 | ||
|   | adf5a113fc | ||
|   | 6a19ac31c0 | 
							
								
								
									
										40
									
								
								.github/ISSUE_TEMPLATE/bug_report.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								.github/ISSUE_TEMPLATE/bug_report.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | --- | ||||||
|  | name: Bug report | ||||||
|  | about: Create a report to help us improve | ||||||
|  | title: '' | ||||||
|  | labels: '' | ||||||
|  | assignees: '' | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | **Description** | ||||||
|  |  | ||||||
|  | <!-- Provide a clear and concise description of the bug --> | ||||||
|  |  | ||||||
|  | **Steps To Reproduce** | ||||||
|  |  | ||||||
|  | 1.  | ||||||
|  | 2.  | ||||||
|  | 3.  | ||||||
|  |  | ||||||
|  | **Expected Behavior** | ||||||
|  |  | ||||||
|  | <!-- What should have happened? --> | ||||||
|  |  | ||||||
|  | **Actual Behavior** | ||||||
|  |  | ||||||
|  | <!-- What happened instead? --> | ||||||
|  |  | ||||||
|  | **Screenshots** | ||||||
|  |  | ||||||
|  | <!-- If applicable, add screenshots to help explain your problem --> | ||||||
|  |  | ||||||
|  | **Environment** | ||||||
|  |  | ||||||
|  | - Hugo Version: [e.g., 0.85.0] | ||||||
|  | - Browser/OS: [e.g., Chrome, MacOS] | ||||||
|  | - Theme Version: [e.g., v2.0] | ||||||
|  |  | ||||||
|  | **Additional Context** | ||||||
|  |  | ||||||
|  | <!-- Add any other context about the problem here --> | ||||||
							
								
								
									
										24
									
								
								.github/ISSUE_TEMPLATE/feature_request.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								.github/ISSUE_TEMPLATE/feature_request.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | --- | ||||||
|  | name: Feature request | ||||||
|  | about: Suggest an idea for this project | ||||||
|  | title: '' | ||||||
|  | labels: '' | ||||||
|  | assignees: '' | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | **Feature Description** | ||||||
|  |  | ||||||
|  | <!-- Provide a clear and concise description of the feature --> | ||||||
|  |  | ||||||
|  | **Problem/Solution** | ||||||
|  |  | ||||||
|  | <!-- What problem will this feature solve? Or what new capability will it add? --> | ||||||
|  |  | ||||||
|  | **Alternatives Considered** | ||||||
|  |  | ||||||
|  | <!-- Have you considered any alternative solutions or workarounds? --> | ||||||
|  |  | ||||||
|  | **Additional Context** | ||||||
|  |  | ||||||
|  | <!-- Add any other context or screenshots about the feature request here --> | ||||||
| @@ -697,6 +697,12 @@ video { | |||||||
| .h-2 { | .h-2 { | ||||||
|   height: 0.5rem; |   height: 0.5rem; | ||||||
| } | } | ||||||
|  | .h-3 { | ||||||
|  |   height: 0.75rem; | ||||||
|  | } | ||||||
|  | .h-3\.5 { | ||||||
|  |   height: 0.875rem; | ||||||
|  | } | ||||||
| .h-4 { | .h-4 { | ||||||
|   height: 1rem; |   height: 1rem; | ||||||
| } | } | ||||||
| @@ -941,6 +947,10 @@ video { | |||||||
|   --tw-border-opacity: 1; |   --tw-border-opacity: 1; | ||||||
|   border-color: rgb(229 231 235 / var(--tw-border-opacity)); |   border-color: rgb(229 231 235 / var(--tw-border-opacity)); | ||||||
| } | } | ||||||
|  | .border-gray-500 { | ||||||
|  |   --tw-border-opacity: 1; | ||||||
|  |   border-color: rgb(107 114 128 / var(--tw-border-opacity)); | ||||||
|  | } | ||||||
| .border-orange-100 { | .border-orange-100 { | ||||||
|   --tw-border-opacity: 1; |   --tw-border-opacity: 1; | ||||||
|   border-color: rgb(255 237 213 / var(--tw-border-opacity)); |   border-color: rgb(255 237 213 / var(--tw-border-opacity)); | ||||||
| @@ -977,18 +987,18 @@ video { | |||||||
| } | } | ||||||
| .bg-primary-100 { | .bg-primary-100 { | ||||||
|   --tw-bg-opacity: 1; |   --tw-bg-opacity: 1; | ||||||
|   background-color: hsl(var(--primary-hue) 100% 94% / var(--tw-bg-opacity)); |   background-color: hsl(var(--primary-hue) var(--primary-saturation) 94% / var(--tw-bg-opacity)); | ||||||
| } | } | ||||||
| .bg-primary-400 { | .bg-primary-400 { | ||||||
|   --tw-bg-opacity: 1; |   --tw-bg-opacity: 1; | ||||||
|   background-color: hsl(var(--primary-hue) 100% 66% / var(--tw-bg-opacity)); |   background-color: hsl(var(--primary-hue) var(--primary-saturation) 66% / var(--tw-bg-opacity)); | ||||||
| } | } | ||||||
| .bg-primary-600 { | .bg-primary-600 { | ||||||
|   --tw-bg-opacity: 1; |   --tw-bg-opacity: 1; | ||||||
|   background-color: hsl(var(--primary-hue) 100% 45% / var(--tw-bg-opacity)); |   background-color: hsl(var(--primary-hue) var(--primary-saturation) 45% / var(--tw-bg-opacity)); | ||||||
| } | } | ||||||
| .bg-primary-700\/5 { | .bg-primary-700\/5 { | ||||||
|   background-color: hsl(var(--primary-hue) 100% 39% / 0.05); |   background-color: hsl(var(--primary-hue) var(--primary-saturation) 39% / 0.05); | ||||||
| } | } | ||||||
| .bg-red-100 { | .bg-red-100 { | ||||||
|   --tw-bg-opacity: 1; |   --tw-bg-opacity: 1; | ||||||
| @@ -1251,7 +1261,7 @@ video { | |||||||
| } | } | ||||||
| .text-primary-800 { | .text-primary-800 { | ||||||
|   --tw-text-opacity: 1; |   --tw-text-opacity: 1; | ||||||
|   color: hsl(var(--primary-hue) 100% 32% / var(--tw-text-opacity)); |   color: hsl(var(--primary-hue) var(--primary-saturation) 32% / var(--tw-text-opacity)); | ||||||
| } | } | ||||||
| .text-red-900 { | .text-red-900 { | ||||||
|   --tw-text-opacity: 1; |   --tw-text-opacity: 1; | ||||||
| @@ -1370,6 +1380,9 @@ video { | |||||||
| .duration-200 { | .duration-200 { | ||||||
|   transition-duration: 200ms; |   transition-duration: 200ms; | ||||||
| } | } | ||||||
|  | .duration-75 { | ||||||
|  |   transition-duration: 75ms; | ||||||
|  | } | ||||||
| .ease-in { | .ease-in { | ||||||
|   transition-timing-function: cubic-bezier(0.4, 0, 1, 1); |   transition-timing-function: cubic-bezier(0.4, 0, 1, 1); | ||||||
| } | } | ||||||
| @@ -1426,7 +1439,7 @@ video { | |||||||
|   } |   } | ||||||
| } | } | ||||||
| :is(html[class~="dark"] .content h2) { | :is(html[class~="dark"] .content h2) { | ||||||
|   border-color: hsl(var(--primary-hue) 100% 94% / 0.1); |   border-color: hsl(var(--primary-hue) var(--primary-saturation) 94% / 0.1); | ||||||
|   --tw-text-opacity: 1; |   --tw-text-opacity: 1; | ||||||
|   color: rgb(241 245 249 / var(--tw-text-opacity)); |   color: rgb(241 245 249 / var(--tw-text-opacity)); | ||||||
| } | } | ||||||
| @@ -1492,9 +1505,13 @@ video { | |||||||
| .content p:first-child { | .content p:first-child { | ||||||
|   margin-top: 0px; |   margin-top: 0px; | ||||||
| } | } | ||||||
|  | .content .not-prose p { | ||||||
|  |   margin-top: 0px; | ||||||
|  |   line-height: 1.5; | ||||||
|  | } | ||||||
| .content a { | .content a { | ||||||
|   --tw-text-opacity: 1; |   --tw-text-opacity: 1; | ||||||
|   color: hsl(var(--primary-hue) 100% 45% / var(--tw-text-opacity)); |   color: hsl(var(--primary-hue) var(--primary-saturation) 45% / var(--tw-text-opacity)); | ||||||
|   text-decoration-line: underline; |   text-decoration-line: underline; | ||||||
|   text-decoration-thickness: from-font; |   text-decoration-thickness: from-font; | ||||||
|   text-underline-position: from-font; |   text-underline-position: from-font; | ||||||
| @@ -1532,7 +1549,7 @@ video { | |||||||
|   margin-bottom: 1rem; |   margin-bottom: 1rem; | ||||||
|   overflow-x: auto; |   overflow-x: auto; | ||||||
|   border-radius: 0.75rem; |   border-radius: 0.75rem; | ||||||
|   background-color: hsl(var(--primary-hue) 100% 39% / 0.05); |   background-color: hsl(var(--primary-hue) var(--primary-saturation) 39% / 0.05); | ||||||
|   padding-top: 1rem; |   padding-top: 1rem; | ||||||
|   padding-bottom: 1rem; |   padding-bottom: 1rem; | ||||||
|   font-size: .9em; |   font-size: .9em; | ||||||
| @@ -1544,18 +1561,18 @@ video { | |||||||
|  |  | ||||||
|   .content pre:not(.code-block pre) { |   .content pre:not(.code-block pre) { | ||||||
|     border-width: 1px; |     border-width: 1px; | ||||||
|     border-color: hsl(var(--primary-hue) 100% 24% / 0.2); |     border-color: hsl(var(--primary-hue) var(--primary-saturation) 24% / 0.2); | ||||||
|     --tw-contrast: contrast(1.5); |     --tw-contrast: contrast(1.5); | ||||||
|     filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); |     filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| :is(html[class~="dark"] .content pre:not(.code-block pre)) { | :is(html[class~="dark"] .content pre:not(.code-block pre)) { | ||||||
|   background-color: hsl(var(--primary-hue) 100% 77% / 0.1); |   background-color: hsl(var(--primary-hue) var(--primary-saturation) 77% / 0.1); | ||||||
| } | } | ||||||
| @media (prefers-contrast: more) { | @media (prefers-contrast: more) { | ||||||
|  |  | ||||||
|   :is(html[class~="dark"] .content pre:not(.code-block pre)) { |   :is(html[class~="dark"] .content pre:not(.code-block pre)) { | ||||||
|     border-color: hsl(var(--primary-hue) 100% 94% / 0.4); |     border-color: hsl(var(--primary-hue) var(--primary-saturation) 94% / 0.4); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| .content code:not(.code-block code) { | .content code:not(.code-block code) { | ||||||
| @@ -2151,7 +2168,7 @@ article details > summary::before { | |||||||
| } | } | ||||||
| .code-block pre { | .code-block pre { | ||||||
|   overflow-x: auto; |   overflow-x: auto; | ||||||
|   background-color: hsl(var(--primary-hue) 100% 39% / 0.05); |   background-color: hsl(var(--primary-hue) var(--primary-saturation) 39% / 0.05); | ||||||
|   font-size: .9em; |   font-size: .9em; | ||||||
|   font-weight: 500; |   font-weight: 500; | ||||||
|   -webkit-font-smoothing: auto; |   -webkit-font-smoothing: auto; | ||||||
| @@ -2161,18 +2178,18 @@ article details > summary::before { | |||||||
|  |  | ||||||
|   .code-block pre { |   .code-block pre { | ||||||
|     border-width: 1px; |     border-width: 1px; | ||||||
|     border-color: hsl(var(--primary-hue) 100% 24% / 0.2); |     border-color: hsl(var(--primary-hue) var(--primary-saturation) 24% / 0.2); | ||||||
|     --tw-contrast: contrast(1.5); |     --tw-contrast: contrast(1.5); | ||||||
|     filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); |     filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| :is(html[class~="dark"] .code-block pre) { | :is(html[class~="dark"] .code-block pre) { | ||||||
|   background-color: hsl(var(--primary-hue) 100% 77% / 0.1); |   background-color: hsl(var(--primary-hue) var(--primary-saturation) 77% / 0.1); | ||||||
| } | } | ||||||
| @media (prefers-contrast: more) { | @media (prefers-contrast: more) { | ||||||
|  |  | ||||||
|   :is(html[class~="dark"] .code-block pre) { |   :is(html[class~="dark"] .code-block pre) { | ||||||
|     border-color: hsl(var(--primary-hue) 100% 94% / 0.4); |     border-color: hsl(var(--primary-hue) var(--primary-saturation) 94% / 0.4); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| .code-block .filename { | .code-block .filename { | ||||||
| @@ -2185,7 +2202,7 @@ article details > summary::before { | |||||||
|   white-space: nowrap; |   white-space: nowrap; | ||||||
|   border-top-left-radius: 0.75rem; |   border-top-left-radius: 0.75rem; | ||||||
|   border-top-right-radius: 0.75rem; |   border-top-right-radius: 0.75rem; | ||||||
|   background-color: hsl(var(--primary-hue) 100% 39% / 0.05); |   background-color: hsl(var(--primary-hue) var(--primary-saturation) 39% / 0.05); | ||||||
|   padding-top: 0.5rem; |   padding-top: 0.5rem; | ||||||
|   padding-bottom: 0.5rem; |   padding-bottom: 0.5rem; | ||||||
|   padding-left: 1rem; |   padding-left: 1rem; | ||||||
| @@ -2195,7 +2212,7 @@ article details > summary::before { | |||||||
|   color: rgb(55 65 81 / var(--tw-text-opacity)); |   color: rgb(55 65 81 / var(--tw-text-opacity)); | ||||||
| } | } | ||||||
| :is(html[class~="dark"] .code-block .filename) { | :is(html[class~="dark"] .code-block .filename) { | ||||||
|   background-color: hsl(var(--primary-hue) 100% 77% / 0.1); |   background-color: hsl(var(--primary-hue) var(--primary-saturation) 77% / 0.1); | ||||||
|   --tw-text-opacity: 1; |   --tw-text-opacity: 1; | ||||||
|   color: rgb(229 231 235 / var(--tw-text-opacity)); |   color: rgb(229 231 235 / var(--tw-text-opacity)); | ||||||
| } | } | ||||||
| @@ -2248,7 +2265,7 @@ article details > summary::before { | |||||||
| .chroma .hl { | .chroma .hl { | ||||||
|   display: block; |   display: block; | ||||||
|   width: 100%; |   width: 100%; | ||||||
|   background-color: hsl(var(--primary-hue) 100% 32% / 0.1); |   background-color: hsl(var(--primary-hue) var(--primary-saturation) 32% / 0.1); | ||||||
| } | } | ||||||
| .hextra-cards { | .hextra-cards { | ||||||
|   grid-template-columns: repeat(auto-fill, minmax(max(250px, calc((100% - 1rem * 2) / var(--rows))), 1fr)); |   grid-template-columns: repeat(auto-fill, minmax(max(250px, calc((100% - 1rem * 2) / var(--rows))), 1fr)); | ||||||
| @@ -2340,13 +2357,13 @@ article details > summary::before { | |||||||
| } | } | ||||||
| .search-wrapper li .active { | .search-wrapper li .active { | ||||||
|   border-radius: 0.375rem; |   border-radius: 0.375rem; | ||||||
|   background-color: hsl(var(--primary-hue) 100% 50% / 0.1); |   background-color: hsl(var(--primary-hue) var(--primary-saturation) 50% / 0.1); | ||||||
| } | } | ||||||
| @media (prefers-contrast: more) { | @media (prefers-contrast: more) { | ||||||
|  |  | ||||||
|   .search-wrapper li .active { |   .search-wrapper li .active { | ||||||
|     --tw-border-opacity: 1; |     --tw-border-opacity: 1; | ||||||
|     border-color: hsl(var(--primary-hue) 100% 50% / var(--tw-border-opacity)); |     border-color: hsl(var(--primary-hue) var(--primary-saturation) 50% / var(--tw-border-opacity)); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| .search-wrapper .no-result { | .search-wrapper .no-result { | ||||||
| @@ -2433,7 +2450,7 @@ article details > summary::before { | |||||||
|   } |   } | ||||||
| .search-wrapper .match { | .search-wrapper .match { | ||||||
|   --tw-text-opacity: 1; |   --tw-text-opacity: 1; | ||||||
|   color: hsl(var(--primary-hue) 100% 45% / var(--tw-text-opacity)); |   color: hsl(var(--primary-hue) var(--primary-saturation) 45% / var(--tw-text-opacity)); | ||||||
| } | } | ||||||
| @media (max-width: 767px) { | @media (max-width: 767px) { | ||||||
|   .sidebar-container { |   .sidebar-container { | ||||||
| @@ -2572,11 +2589,13 @@ body { | |||||||
| } | } | ||||||
| :root { | :root { | ||||||
|   --primary-hue: 212deg; |   --primary-hue: 212deg; | ||||||
|  |   --primary-saturation: 100%; | ||||||
|   --navbar-height: 4rem; |   --navbar-height: 4rem; | ||||||
|   --menu-height: 3.75rem; |   --menu-height: 3.75rem; | ||||||
| } | } | ||||||
| .dark { | .dark { | ||||||
|   --primary-hue: 204deg; |   --primary-hue: 204deg; | ||||||
|  |   --primary-saturation: 100%; | ||||||
| } | } | ||||||
| .placeholder\:text-gray-500::-moz-placeholder { | .placeholder\:text-gray-500::-moz-placeholder { | ||||||
|   --tw-text-opacity: 1; |   --tw-text-opacity: 1; | ||||||
| @@ -2660,6 +2679,10 @@ body { | |||||||
|   --tw-border-opacity: 1; |   --tw-border-opacity: 1; | ||||||
|   border-color: rgb(156 163 175 / var(--tw-border-opacity)); |   border-color: rgb(156 163 175 / var(--tw-border-opacity)); | ||||||
| } | } | ||||||
|  | .hover\:border-gray-900:hover { | ||||||
|  |   --tw-border-opacity: 1; | ||||||
|  |   border-color: rgb(17 24 39 / var(--tw-border-opacity)); | ||||||
|  | } | ||||||
| .hover\:bg-gray-100:hover { | .hover\:bg-gray-100:hover { | ||||||
|   --tw-bg-opacity: 1; |   --tw-bg-opacity: 1; | ||||||
|   background-color: rgb(243 244 246 / var(--tw-bg-opacity)); |   background-color: rgb(243 244 246 / var(--tw-bg-opacity)); | ||||||
| @@ -2669,11 +2692,11 @@ body { | |||||||
| } | } | ||||||
| .hover\:bg-primary-50:hover { | .hover\:bg-primary-50:hover { | ||||||
|   --tw-bg-opacity: 1; |   --tw-bg-opacity: 1; | ||||||
|   background-color: hsl(var(--primary-hue) 100% 97% / var(--tw-bg-opacity)); |   background-color: hsl(var(--primary-hue) var(--primary-saturation) 97% / var(--tw-bg-opacity)); | ||||||
| } | } | ||||||
| .hover\:bg-primary-700:hover { | .hover\:bg-primary-700:hover { | ||||||
|   --tw-bg-opacity: 1; |   --tw-bg-opacity: 1; | ||||||
|   background-color: hsl(var(--primary-hue) 100% 39% / var(--tw-bg-opacity)); |   background-color: hsl(var(--primary-hue) var(--primary-saturation) 39% / var(--tw-bg-opacity)); | ||||||
| } | } | ||||||
| .hover\:bg-slate-50:hover { | .hover\:bg-slate-50:hover { | ||||||
|   --tw-bg-opacity: 1; |   --tw-bg-opacity: 1; | ||||||
| @@ -2693,7 +2716,7 @@ body { | |||||||
| } | } | ||||||
| .hover\:text-primary-600:hover { | .hover\:text-primary-600:hover { | ||||||
|   --tw-text-opacity: 1; |   --tw-text-opacity: 1; | ||||||
|   color: hsl(var(--primary-hue) 100% 45% / var(--tw-text-opacity)); |   color: hsl(var(--primary-hue) var(--primary-saturation) 45% / var(--tw-text-opacity)); | ||||||
| } | } | ||||||
| .hover\:opacity-60:hover { | .hover\:opacity-60:hover { | ||||||
|   opacity: 0.6; |   opacity: 0.6; | ||||||
| @@ -2730,7 +2753,7 @@ body { | |||||||
| } | } | ||||||
| .focus\:ring-primary-300:focus { | .focus\:ring-primary-300:focus { | ||||||
|   --tw-ring-opacity: 1; |   --tw-ring-opacity: 1; | ||||||
|   --tw-ring-color: hsl(var(--primary-hue) 100% 77% / var(--tw-ring-opacity)); |   --tw-ring-color: hsl(var(--primary-hue) var(--primary-saturation) 77% / var(--tw-ring-opacity)); | ||||||
| } | } | ||||||
| .active\:bg-gray-400\/20:active { | .active\:bg-gray-400\/20:active { | ||||||
|   background-color: rgb(156 163 175 / 0.2); |   background-color: rgb(156 163 175 / 0.2); | ||||||
| @@ -2772,11 +2795,11 @@ body { | |||||||
| } | } | ||||||
| .data-\[state\=selected\]\:border-primary-500[data-state=selected] { | .data-\[state\=selected\]\:border-primary-500[data-state=selected] { | ||||||
|   --tw-border-opacity: 1; |   --tw-border-opacity: 1; | ||||||
|   border-color: hsl(var(--primary-hue) 100% 50% / var(--tw-border-opacity)); |   border-color: hsl(var(--primary-hue) var(--primary-saturation) 50% / var(--tw-border-opacity)); | ||||||
| } | } | ||||||
| .data-\[state\=selected\]\:text-primary-600[data-state=selected] { | .data-\[state\=selected\]\:text-primary-600[data-state=selected] { | ||||||
|   --tw-text-opacity: 1; |   --tw-text-opacity: 1; | ||||||
|   color: hsl(var(--primary-hue) 100% 45% / var(--tw-text-opacity)); |   color: hsl(var(--primary-hue) var(--primary-saturation) 45% / var(--tw-text-opacity)); | ||||||
| } | } | ||||||
| .group[data-theme=dark] .group-data-\[theme\=dark\]\:hidden { | .group[data-theme=dark] .group-data-\[theme\=dark\]\:hidden { | ||||||
|   display: none; |   display: none; | ||||||
| @@ -2918,6 +2941,11 @@ body { | |||||||
|     border-color: currentColor; |     border-color: currentColor; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   .contrast-more\:border-gray-800 { | ||||||
|  |     --tw-border-opacity: 1; | ||||||
|  |     border-color: rgb(31 41 55 / var(--tw-border-opacity)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   .contrast-more\:border-gray-900 { |   .contrast-more\:border-gray-900 { | ||||||
|     --tw-border-opacity: 1; |     --tw-border-opacity: 1; | ||||||
|     border-color: rgb(17 24 39 / var(--tw-border-opacity)); |     border-color: rgb(17 24 39 / var(--tw-border-opacity)); | ||||||
| @@ -2930,7 +2958,7 @@ body { | |||||||
|  |  | ||||||
|   .contrast-more\:border-primary-500 { |   .contrast-more\:border-primary-500 { | ||||||
|     --tw-border-opacity: 1; |     --tw-border-opacity: 1; | ||||||
|     border-color: hsl(var(--primary-hue) 100% 50% / var(--tw-border-opacity)); |     border-color: hsl(var(--primary-hue) var(--primary-saturation) 50% / var(--tw-border-opacity)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   .contrast-more\:border-transparent { |   .contrast-more\:border-transparent { | ||||||
| @@ -2993,6 +3021,10 @@ body { | |||||||
| :is(html[class~="dark"] .dark\:border-gray-100\/20) { | :is(html[class~="dark"] .dark\:border-gray-100\/20) { | ||||||
|   border-color: rgb(243 244 246 / 0.2); |   border-color: rgb(243 244 246 / 0.2); | ||||||
| } | } | ||||||
|  | :is(html[class~="dark"] .dark\:border-gray-400) { | ||||||
|  |   --tw-border-opacity: 1; | ||||||
|  |   border-color: rgb(156 163 175 / var(--tw-border-opacity)); | ||||||
|  | } | ||||||
| :is(html[class~="dark"] .dark\:border-neutral-700) { | :is(html[class~="dark"] .dark\:border-neutral-700) { | ||||||
|   --tw-border-opacity: 1; |   --tw-border-opacity: 1; | ||||||
|   border-color: rgb(64 64 64 / var(--tw-border-opacity)); |   border-color: rgb(64 64 64 / var(--tw-border-opacity)); | ||||||
| @@ -3038,14 +3070,14 @@ body { | |||||||
|   background-color: rgb(251 146 60 / 0.2); |   background-color: rgb(251 146 60 / 0.2); | ||||||
| } | } | ||||||
| :is(html[class~="dark"] .dark\:bg-primary-300\/10) { | :is(html[class~="dark"] .dark\:bg-primary-300\/10) { | ||||||
|   background-color: hsl(var(--primary-hue) 100% 77% / 0.1); |   background-color: hsl(var(--primary-hue) var(--primary-saturation) 77% / 0.1); | ||||||
| } | } | ||||||
| :is(html[class~="dark"] .dark\:bg-primary-400\/10) { | :is(html[class~="dark"] .dark\:bg-primary-400\/10) { | ||||||
|   background-color: hsl(var(--primary-hue) 100% 66% / 0.1); |   background-color: hsl(var(--primary-hue) var(--primary-saturation) 66% / 0.1); | ||||||
| } | } | ||||||
| :is(html[class~="dark"] .dark\:bg-primary-600) { | :is(html[class~="dark"] .dark\:bg-primary-600) { | ||||||
|   --tw-bg-opacity: 1; |   --tw-bg-opacity: 1; | ||||||
|   background-color: hsl(var(--primary-hue) 100% 45% / var(--tw-bg-opacity)); |   background-color: hsl(var(--primary-hue) var(--primary-saturation) 45% / var(--tw-bg-opacity)); | ||||||
| } | } | ||||||
| :is(html[class~="dark"] .dark\:bg-red-900\/30) { | :is(html[class~="dark"] .dark\:bg-red-900\/30) { | ||||||
|   background-color: rgb(127 29 29 / 0.3); |   background-color: rgb(127 29 29 / 0.3); | ||||||
| @@ -3099,7 +3131,7 @@ body { | |||||||
| } | } | ||||||
| :is(html[class~="dark"] .dark\:text-primary-600) { | :is(html[class~="dark"] .dark\:text-primary-600) { | ||||||
|   --tw-text-opacity: 1; |   --tw-text-opacity: 1; | ||||||
|   color: hsl(var(--primary-hue) 100% 45% / var(--tw-text-opacity)); |   color: hsl(var(--primary-hue) var(--primary-saturation) 45% / var(--tw-text-opacity)); | ||||||
| } | } | ||||||
| :is(html[class~="dark"] .dark\:text-red-200) { | :is(html[class~="dark"] .dark\:text-red-200) { | ||||||
|   --tw-text-opacity: 1; |   --tw-text-opacity: 1; | ||||||
| @@ -3152,6 +3184,10 @@ body { | |||||||
|   --tw-invert: invert(100%); |   --tw-invert: invert(100%); | ||||||
|   filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); |   filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); | ||||||
| } | } | ||||||
|  | :is(html[class~="dark"] .dark\:hover\:border-gray-100:hover) { | ||||||
|  |   --tw-border-opacity: 1; | ||||||
|  |   border-color: rgb(243 244 246 / var(--tw-border-opacity)); | ||||||
|  | } | ||||||
| :is(html[class~="dark"] .dark\:hover\:border-gray-600:hover) { | :is(html[class~="dark"] .dark\:hover\:border-gray-600:hover) { | ||||||
|   --tw-border-opacity: 1; |   --tw-border-opacity: 1; | ||||||
|   border-color: rgb(75 85 99 / var(--tw-border-opacity)); |   border-color: rgb(75 85 99 / var(--tw-border-opacity)); | ||||||
| @@ -3184,14 +3220,14 @@ body { | |||||||
|   background-color: rgb(23 23 23 / var(--tw-bg-opacity)); |   background-color: rgb(23 23 23 / var(--tw-bg-opacity)); | ||||||
| } | } | ||||||
| :is(html[class~="dark"] .dark\:hover\:bg-primary-100\/5:hover) { | :is(html[class~="dark"] .dark\:hover\:bg-primary-100\/5:hover) { | ||||||
|   background-color: hsl(var(--primary-hue) 100% 94% / 0.05); |   background-color: hsl(var(--primary-hue) var(--primary-saturation) 94% / 0.05); | ||||||
| } | } | ||||||
| :is(html[class~="dark"] .dark\:hover\:bg-primary-700:hover) { | :is(html[class~="dark"] .dark\:hover\:bg-primary-700:hover) { | ||||||
|   --tw-bg-opacity: 1; |   --tw-bg-opacity: 1; | ||||||
|   background-color: hsl(var(--primary-hue) 100% 39% / var(--tw-bg-opacity)); |   background-color: hsl(var(--primary-hue) var(--primary-saturation) 39% / var(--tw-bg-opacity)); | ||||||
| } | } | ||||||
| :is(html[class~="dark"] .hover\:dark\:bg-primary-500\/10):hover { | :is(html[class~="dark"] .hover\:dark\:bg-primary-500\/10):hover { | ||||||
|   background-color: hsl(var(--primary-hue) 100% 50% / 0.1); |   background-color: hsl(var(--primary-hue) var(--primary-saturation) 50% / 0.1); | ||||||
| } | } | ||||||
| :is(html[class~="dark"] .dark\:hover\:text-gray-100:hover) { | :is(html[class~="dark"] .dark\:hover\:text-gray-100:hover) { | ||||||
|   --tw-text-opacity: 1; |   --tw-text-opacity: 1; | ||||||
| @@ -3219,7 +3255,7 @@ body { | |||||||
| } | } | ||||||
| :is(html[class~="dark"] .hover\:dark\:text-primary-600):hover { | :is(html[class~="dark"] .hover\:dark\:text-primary-600):hover { | ||||||
|   --tw-text-opacity: 1; |   --tw-text-opacity: 1; | ||||||
|   color: hsl(var(--primary-hue) 100% 45% / var(--tw-text-opacity)); |   color: hsl(var(--primary-hue) var(--primary-saturation) 45% / var(--tw-text-opacity)); | ||||||
| } | } | ||||||
| :is(html[class~="dark"] .dark\:hover\:shadow-none:hover) { | :is(html[class~="dark"] .dark\:hover\:shadow-none:hover) { | ||||||
|   --tw-shadow: 0 0 #0000; |   --tw-shadow: 0 0 #0000; | ||||||
| @@ -3232,7 +3268,7 @@ body { | |||||||
| } | } | ||||||
| :is(html[class~="dark"] .dark\:focus\:ring-primary-800:focus) { | :is(html[class~="dark"] .dark\:focus\:ring-primary-800:focus) { | ||||||
|   --tw-ring-opacity: 1; |   --tw-ring-opacity: 1; | ||||||
|   --tw-ring-color: hsl(var(--primary-hue) 100% 32% / var(--tw-ring-opacity)); |   --tw-ring-color: hsl(var(--primary-hue) var(--primary-saturation) 32% / var(--tw-ring-opacity)); | ||||||
| } | } | ||||||
| @media (prefers-contrast: more) { | @media (prefers-contrast: more) { | ||||||
|  |  | ||||||
| @@ -3252,7 +3288,7 @@ body { | |||||||
|  |  | ||||||
|   :is(html[class~="dark"] .contrast-more\:dark\:border-primary-500) { |   :is(html[class~="dark"] .contrast-more\:dark\:border-primary-500) { | ||||||
|     --tw-border-opacity: 1; |     --tw-border-opacity: 1; | ||||||
|     border-color: hsl(var(--primary-hue) 100% 50% / var(--tw-border-opacity)); |     border-color: hsl(var(--primary-hue) var(--primary-saturation) 50% / var(--tw-border-opacity)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   :is(html[class~="dark"] .dark\:contrast-more\:border-neutral-400) { |   :is(html[class~="dark"] .dark\:contrast-more\:border-neutral-400) { | ||||||
|   | |||||||
| @@ -21,10 +21,12 @@ body { | |||||||
|  |  | ||||||
| :root { | :root { | ||||||
|   --primary-hue: 212deg; |   --primary-hue: 212deg; | ||||||
|  |   --primary-saturation: 100%; | ||||||
|   --navbar-height: 4rem; |   --navbar-height: 4rem; | ||||||
|   --menu-height: 3.75rem; |   --menu-height: 3.75rem; | ||||||
| } | } | ||||||
|  |  | ||||||
| .dark { | .dark { | ||||||
|   --primary-hue: 204deg; |   --primary-hue: 204deg; | ||||||
|  |   --primary-saturation: 100%; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -20,6 +20,9 @@ | |||||||
|   p { |   p { | ||||||
|     @apply mt-6 leading-7 first:mt-0; |     @apply mt-6 leading-7 first:mt-0; | ||||||
|   } |   } | ||||||
|  |   .not-prose p { | ||||||
|  |     @apply mt-0 leading-normal; | ||||||
|  |   } | ||||||
|   a { |   a { | ||||||
|     @apply text-primary-600 underline decoration-from-font [text-underline-position:from-font]; |     @apply text-primary-600 underline decoration-from-font [text-underline-position:from-font]; | ||||||
|   } |   } | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								assets/js/back-to-top.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								assets/js/back-to-top.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | // Back to top button | ||||||
|  |  | ||||||
|  | document.addEventListener("DOMContentLoaded", function () { | ||||||
|  |   const backToTop = document.querySelector("#backToTop"); | ||||||
|  |   if (backToTop) { | ||||||
|  |     document.addEventListener("scroll", (e) => { | ||||||
|  |       if (window.scrollY > 300) { | ||||||
|  |         backToTop.classList.remove("opacity-0"); | ||||||
|  |       } else { | ||||||
|  |         backToTop.classList.add("opacity-0"); | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | function scrollUp() { | ||||||
|  |   window.scroll({ | ||||||
|  |     top: 0, | ||||||
|  |     left: 0, | ||||||
|  |     behavior: "smooth", | ||||||
|  |   }); | ||||||
|  | } | ||||||
| @@ -1,30 +1,63 @@ | |||||||
| document.querySelectorAll('.code-copy-btn').forEach(function (button) { | // Copy button for code blocks | ||||||
|   button.addEventListener('click', function (e) { |  | ||||||
|     e.preventDefault(); | document.addEventListener('DOMContentLoaded', function () { | ||||||
|     const targetId = button.getAttribute('data-clipboard-target'); |   const getCopyIcon = () => { | ||||||
|     const target = document.querySelector(targetId); |     const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); | ||||||
|     let codeElement; |     svg.innerHTML = ` | ||||||
|     if (target.tagName === 'CODE') { |       <path stroke-linecap="round" stroke-linejoin="round" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" /> | ||||||
|       codeElement = target; |     `; | ||||||
|     } else { |     svg.setAttribute('fill', 'none'); | ||||||
|       // Select the last code element in case line numbers are present |     svg.setAttribute('viewBox', '0 0 24 24'); | ||||||
|       const codeElements = target.querySelectorAll('code'); |     svg.setAttribute('stroke', 'currentColor'); | ||||||
|       codeElement = codeElements[codeElements.length - 1]; |     svg.setAttribute('stroke-width', '2'); | ||||||
|     } |     return svg; | ||||||
|     if (codeElement) { |   } | ||||||
|       // Replace double newlines with single newlines in the innerText |  | ||||||
|       // as each line inside <span> has trailing newline '\n' |   const getSuccessIcon = () => { | ||||||
|       const code = codeElement.innerText.replace(/\n\n/g, '\n'); |     const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); | ||||||
|       navigator.clipboard.writeText(code).then(function () { |     svg.innerHTML = ` | ||||||
|         button.classList.add('copied'); |       <path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" /> | ||||||
|         setTimeout(function () { |     `; | ||||||
|           button.classList.remove('copied'); |     svg.setAttribute('fill', 'none'); | ||||||
|         }, 500); |     svg.setAttribute('viewBox', '0 0 24 24'); | ||||||
|       }).catch(function (err) { |     svg.setAttribute('stroke', 'currentColor'); | ||||||
|         console.error('Failed to copy text: ', err); |     svg.setAttribute('stroke-width', '2'); | ||||||
|       }); |     return svg; | ||||||
|     } else { |   } | ||||||
|       console.error('Target element not found'); |  | ||||||
|     } |   document.querySelectorAll('.code-copy-btn').forEach(function (button) { | ||||||
|  |     // Add copy and success icons | ||||||
|  |     button.querySelector('.copy-icon')?.appendChild(getCopyIcon()); | ||||||
|  |     button.querySelector('.success-icon')?.appendChild(getSuccessIcon()); | ||||||
|  |  | ||||||
|  |     // Add click event listener for copy button | ||||||
|  |     button.addEventListener('click', function (e) { | ||||||
|  |       e.preventDefault(); | ||||||
|  |       const targetId = button.getAttribute('data-clipboard-target'); | ||||||
|  |       const target = document.querySelector(targetId); | ||||||
|  |       let codeElement; | ||||||
|  |       if (target.tagName === 'CODE') { | ||||||
|  |         codeElement = target; | ||||||
|  |       } else { | ||||||
|  |         // Select the last code element in case line numbers are present | ||||||
|  |         const codeElements = target.querySelectorAll('code'); | ||||||
|  |         codeElement = codeElements[codeElements.length - 1]; | ||||||
|  |       } | ||||||
|  |       if (codeElement) { | ||||||
|  |         // Replace double newlines with single newlines in the innerText | ||||||
|  |         // as each line inside <span> has trailing newline '\n' | ||||||
|  |         const code = codeElement.innerText.replace(/\n\n/g, '\n'); | ||||||
|  |         navigator.clipboard.writeText(code).then(function () { | ||||||
|  |           button.classList.add('copied'); | ||||||
|  |           setTimeout(function () { | ||||||
|  |             button.classList.remove('copied'); | ||||||
|  |           }, 500); | ||||||
|  |         }).catch(function (err) { | ||||||
|  |           console.error('Failed to copy text: ', err); | ||||||
|  |         }); | ||||||
|  |       } else { | ||||||
|  |         console.error('Target element not found'); | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -1,5 +1,16 @@ | |||||||
| // Search functionality using FlexSearch. | // Search functionality using FlexSearch. | ||||||
|  |  | ||||||
|  | // Change shortcut key to cmd+k on Mac, iPad or iPhone. | ||||||
|  | document.addEventListener("DOMContentLoaded", function () { | ||||||
|  |   if (/iPad|iPhone|Macintosh/.test(navigator.userAgent)) { | ||||||
|  |     // select the kbd element under the .search-wrapper class | ||||||
|  |     const keys = document.querySelectorAll(".search-wrapper kbd"); | ||||||
|  |     keys.forEach(key => { | ||||||
|  |       key.innerHTML = '<span class="text-xs">⌘</span>K'; | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | }); | ||||||
|  |  | ||||||
| // Render the search data as JSON. | // Render the search data as JSON. | ||||||
| // {{ $searchDataFile := printf "%s.search-data.json" .Language.Lang }} | // {{ $searchDataFile := printf "%s.search-data.json" .Language.Lang }} | ||||||
| // {{ $searchData := resources.Get "json/search-data.json" | resources.ExecuteAsTemplate $searchDataFile . }} | // {{ $searchData := resources.Get "json/search-data.json" | resources.ExecuteAsTemplate $searchDataFile . }} | ||||||
|   | |||||||
| @@ -1,40 +1,51 @@ | |||||||
| // Dark theme toggle | // Light / Dark theme toggle | ||||||
|  | (function () { | ||||||
|  |   const defaultTheme = '{{ site.Params.theme.default | default `system`}}' | ||||||
|  |  | ||||||
| const themeToggleButtons = document.querySelectorAll(".theme-toggle"); |   const themeToggleButtons = document.querySelectorAll(".theme-toggle"); | ||||||
|  |  | ||||||
| // Change the icons inside the button based on previous settings |   // Change the icons of the buttons based on previous settings or system theme | ||||||
| if ( |   if ( | ||||||
|   localStorage.getItem("color-theme") === "dark" || |     localStorage.getItem("color-theme") === "dark" || | ||||||
|   (!("color-theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches) |     (!("color-theme" in localStorage) && | ||||||
| ) { |       ((window.matchMedia("(prefers-color-scheme: dark)").matches && defaultTheme === "system") || defaultTheme === "dark")) | ||||||
|   themeToggleButtons.forEach((el) => el.dataset.theme = "dark"); |   ) { | ||||||
| } else { |     themeToggleButtons.forEach((el) => el.dataset.theme = "dark"); | ||||||
|   themeToggleButtons.forEach((el) => el.dataset.theme = "light"); |   } else { | ||||||
| } |     themeToggleButtons.forEach((el) => el.dataset.theme = "light"); | ||||||
|  |   } | ||||||
|  |  | ||||||
| themeToggleButtons.forEach((el) => { |   // Add click event handler to the buttons | ||||||
|   el.addEventListener("click", function () { |   themeToggleButtons.forEach((el) => { | ||||||
|     if (localStorage.getItem("color-theme")) { |     el.addEventListener("click", function () { | ||||||
|       if (localStorage.getItem("color-theme") === "light") { |       if (localStorage.getItem("color-theme")) { | ||||||
|         document.documentElement.classList.add("dark"); |         if (localStorage.getItem("color-theme") === "light") { | ||||||
|         document.documentElement.style.colorScheme = "dark"; |           setDarkTheme(); | ||||||
|         localStorage.setItem("color-theme", "dark"); |           localStorage.setItem("color-theme", "dark"); | ||||||
|  |         } else { | ||||||
|  |           setLightTheme(); | ||||||
|  |           localStorage.setItem("color-theme", "light"); | ||||||
|  |         } | ||||||
|       } else { |       } else { | ||||||
|         document.documentElement.classList.remove("dark"); |         if (document.documentElement.classList.contains("dark")) { | ||||||
|         document.documentElement.style.colorScheme = "light"; |           setLightTheme(); | ||||||
|         localStorage.setItem("color-theme", "light"); |           localStorage.setItem("color-theme", "light"); | ||||||
|  |         } else { | ||||||
|  |           setDarkTheme(); | ||||||
|  |           localStorage.setItem("color-theme", "dark"); | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|     } else { |       el.dataset.theme = document.documentElement.classList.contains("dark") ? "dark" : "light"; | ||||||
|       if (document.documentElement.classList.contains("dark")) { |     }); | ||||||
|         document.documentElement.classList.remove("dark"); |  | ||||||
|         document.documentElement.style.colorScheme = "light"; |  | ||||||
|         localStorage.setItem("color-theme", "light"); |  | ||||||
|       } else { |  | ||||||
|         document.documentElement.classList.add("dark"); |  | ||||||
|         document.documentElement.style.colorScheme = "dark"; |  | ||||||
|         localStorage.setItem("color-theme", "dark"); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     el.dataset.theme = document.documentElement.classList.contains("dark") ? "dark" : "light"; |  | ||||||
|   }); |   }); | ||||||
| }); |  | ||||||
|  |   // Listen for system theme changes | ||||||
|  |   window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (e) => { | ||||||
|  |     if (defaultTheme === "system" && !("color-theme" in localStorage)) { | ||||||
|  |       e.matches ? setDarkTheme() : setLightTheme(); | ||||||
|  |       themeToggleButtons.forEach((el) => | ||||||
|  |         el.dataset.theme = document.documentElement.classList.contains("dark") ? "dark" : "light" | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | })(); | ||||||
|   | |||||||
| @@ -1,3 +1,10 @@ | |||||||
|  | {{/* FlexSearch Index Data */}} | ||||||
|  | {{- $indexType := site.Params.search.flexsearch.index | default "content" -}} | ||||||
|  |  | ||||||
|  | {{- if not (in (slice "content" "summary" "heading" "title" ) $indexType) -}} | ||||||
|  |   {{- errorf "unknown flexsearch index type: %s" $indexType -}} | ||||||
|  | {{- end -}} | ||||||
|  |  | ||||||
| {{- $pages := where .Site.Pages "Kind" "in" (slice "page" "section") -}} | {{- $pages := where .Site.Pages "Kind" "in" (slice "page" "section") -}} | ||||||
| {{- $pages = where $pages "Params.excludeSearch" "!=" true -}} | {{- $pages = where $pages "Params.excludeSearch" "!=" true -}} | ||||||
| {{- $pages = where $pages "Content" "!=" "" -}} | {{- $pages = where $pages "Content" "!=" "" -}} | ||||||
| @@ -7,7 +14,7 @@ | |||||||
| {{- range $index, $page := $pages -}} | {{- range $index, $page := $pages -}} | ||||||
|   {{- $pageTitle := $page.LinkTitle | default $page.File.BaseFileName -}} |   {{- $pageTitle := $page.LinkTitle | default $page.File.BaseFileName -}} | ||||||
|   {{- $pageLink := $page.RelPermalink -}} |   {{- $pageLink := $page.RelPermalink -}} | ||||||
|   {{- $data := partial "utils/fragments" $page -}} |   {{- $data := partial "utils/fragments" (dict "context" $page "type" $indexType) -}} | ||||||
|   {{- $output = $output | merge (dict $pageLink (dict "title" $pageTitle "data" $data)) -}} |   {{- $output = $output | merge (dict $pageLink (dict "title" $pageTitle "data" $data)) -}} | ||||||
| {{- end -}} | {{- end -}} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,4 +12,5 @@ This section covers some advanced topics of the theme. | |||||||
| {{< cards >}} | {{< cards >}} | ||||||
|   {{< card link="multi-language" title="Multi-language" icon="translate" >}} |   {{< card link="multi-language" title="Multi-language" icon="translate" >}} | ||||||
|   {{< card link="customization" title="Customization" icon="pencil" >}} |   {{< card link="customization" title="Customization" icon="pencil" >}} | ||||||
|  |   {{< card link="comments" title="Comments System" icon="chat-alt" >}} | ||||||
| {{< /cards >}} | {{< /cards >}} | ||||||
|   | |||||||
							
								
								
									
										39
									
								
								exampleSite/content/docs/advanced/comments.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								exampleSite/content/docs/advanced/comments.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | --- | ||||||
|  | title: Comments System | ||||||
|  | linkTitle: Comments | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | Hextra supports adding comments system to your site. | ||||||
|  | Currently [giscus](https://giscus.app/) is supported. | ||||||
|  |  | ||||||
|  | <!--more--> | ||||||
|  |  | ||||||
|  | ## giscus | ||||||
|  |  | ||||||
|  | [giscus](https://giscus.app/) is a comments system powered by [GitHub Discussions](https://docs.github.com/en/discussions). It is free and open source. | ||||||
|  |  | ||||||
|  | To enable giscus, you need to add the following to the site configuration file: | ||||||
|  |  | ||||||
|  | ```yaml {filename="hugo.yaml"} | ||||||
|  | params: | ||||||
|  |   comments: | ||||||
|  |     enable: false | ||||||
|  |     type: giscus | ||||||
|  |  | ||||||
|  |     giscus: | ||||||
|  |       repo: <repository> | ||||||
|  |       repoId: <repository ID> | ||||||
|  |       category: <category> | ||||||
|  |       categoryId: <category ID> | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | The giscus configurations can be constructed from the [giscus.app](https://giscus.app/) website. More details can also be found there. | ||||||
|  |  | ||||||
|  | Comments can be enabled or disabled for a specific page in the page front matter: | ||||||
|  |  | ||||||
|  | ```yaml {filename="content/docs/about.md"} | ||||||
|  | --- | ||||||
|  | title: About | ||||||
|  | comments: true | ||||||
|  | --- | ||||||
|  | ``` | ||||||
| @@ -34,11 +34,12 @@ The color of text mixed with `other text` can customized with: | |||||||
|  |  | ||||||
| ### Primary Color | ### Primary Color | ||||||
|  |  | ||||||
| The primary color of the theme can be customized by setting the `--primary-hue` variable: | The primary color of the theme can be customized by setting the `--primary-hue` and `--primary-saturation` variables: | ||||||
|  |  | ||||||
| ```css {filename="assets/css/custom.css"} | ```css {filename="assets/css/custom.css"} | ||||||
| :root { | :root { | ||||||
|   --primary-hue: 100deg; |   --primary-hue: 100deg; | ||||||
|  |   --primary-saturation: 90%; | ||||||
| } | } | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
|   | |||||||
| @@ -19,18 +19,29 @@ We have provided a [GitHub Actions workflow](https://docs.github.com/en/pages/ge | |||||||
|  |  | ||||||
| ## Start as New Project | ## Start as New Project | ||||||
|  |  | ||||||
| ### Prerequisites | There are two main ways to add the Hextra theme to your Hugo project. | ||||||
|  |  | ||||||
| Before we start, make sure we have [Hugo](https://gohugo.io/) installed. | 1. **Hugo Modules (Recommended)**: The simplest and recommended method. [Hugo modules](https://gohugo.io/hugo-modules/) let you pull in the theme directly from its online source. Theme is downloaded automatically and managed by Hugo. | ||||||
| Please refer to Hugo's [official installation guide](https://gohugo.io/installation/) for more details. |  | ||||||
|  |  | ||||||
| [Hugo modules](https://gohugo.io/hugo-modules/) are the recommended way to manage Hugo themes. To use Hugo modules, we need to install [Git](https://git-scm.com/) and [Go](https://go.dev/). | 2. **Git Submodule**: Alternatively, add Hextra as a [Git Submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules). The theme will be downloaded by Git and stored in your project's `themes` folder. | ||||||
|  |  | ||||||
|  | ### Setup Hextra as Hugo module | ||||||
|  |  | ||||||
|  | #### Prerequisites | ||||||
|  |  | ||||||
|  | Before starting, you need to have the following softwares installed: | ||||||
|  |  | ||||||
|  | - [Hugo (extended version)](https://gohugo.io/installation/) | ||||||
|  | - [Git](https://git-scm.com/) | ||||||
|  | - [Go](https://go.dev/) | ||||||
|  |  | ||||||
|  | #### Steps | ||||||
|  |  | ||||||
| {{% steps %}} | {{% steps %}} | ||||||
|  |  | ||||||
| ### Initialize a new Hugo site | ### Initialize a new Hugo site | ||||||
|  |  | ||||||
| ```bash | ```shell | ||||||
| $ hugo new site my-site --format=yaml | $ hugo new site my-site --format=yaml | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| @@ -45,7 +56,7 @@ $ hugo mod init github.com/username/my-site | |||||||
| $ hugo mod get github.com/imfing/hextra | $ hugo mod get github.com/imfing/hextra | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| Edit `hugo.yaml` to enable Hextra theme: | Configure `hugo.yaml` to use Hextra theme by adding the following: | ||||||
|  |  | ||||||
| ```yaml | ```yaml | ||||||
| module: | module: | ||||||
| @@ -55,7 +66,7 @@ module: | |||||||
|  |  | ||||||
| ### Create your first content pages | ### Create your first content pages | ||||||
|  |  | ||||||
| Let's create a new content page for the home page and the documentation page: | Let's create new content page for the home page and the documentation page: | ||||||
|  |  | ||||||
| ```shell | ```shell | ||||||
| $ hugo new content/_index.md | $ hugo new content/_index.md | ||||||
| @@ -73,20 +84,101 @@ Voila! You can see your new site at `http://localhost:1313/`. | |||||||
| {{% /steps %}} | {{% /steps %}} | ||||||
|  |  | ||||||
|  |  | ||||||
| ## Update Theme |  | ||||||
|  |  | ||||||
| {{% details title="How to update theme?" %}} | {{% details title="How to update theme?" %}} | ||||||
|  |  | ||||||
| To update the theme to the [latest released version](https://github.com/imfing/hextra/releases), run the following command: | To update all Hugo modules in your project to their latest versions, run the following command: | ||||||
|  |  | ||||||
| ```shell | ```shell | ||||||
| $ hugo mod get -u | $ hugo mod get -u | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
|  | To update only Hextra to the [latest released version](https://github.com/imfing/hextra/releases), run the following command: | ||||||
|  |  | ||||||
|  | ```shell | ||||||
|  | hugo mod get -u github.com/imfing/hextra | ||||||
|  | ``` | ||||||
|  |  | ||||||
| See [Hugo Modules](https://gohugo.io/hugo-modules/use-modules/#update-all-modules) for more details. | See [Hugo Modules](https://gohugo.io/hugo-modules/use-modules/#update-all-modules) for more details. | ||||||
|  |  | ||||||
| {{% /details %}} | {{% /details %}} | ||||||
|  |  | ||||||
|  | ### Setup Hextra as Git submodule | ||||||
|  |  | ||||||
|  | #### Prerequisites | ||||||
|  |  | ||||||
|  | Before starting, you need to have the following softwares installed: | ||||||
|  |  | ||||||
|  | - [Hugo (extended version)](https://gohugo.io/installation/) | ||||||
|  | - [Git](https://git-scm.com/) | ||||||
|  |  | ||||||
|  | #### Steps | ||||||
|  |  | ||||||
|  | {{% steps %}} | ||||||
|  |  | ||||||
|  | ### Initialize a new Hugo site | ||||||
|  |  | ||||||
|  | ```shell | ||||||
|  | $ hugo new site my-site --format=yaml | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ### Add Hextra theme as a Git submodule | ||||||
|  |  | ||||||
|  | ```shell | ||||||
|  | git submodule add https://github.com/imfing/hextra.git themes/hextra | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Configure `hugo.yaml` to use Hextra theme by adding the following: | ||||||
|  |  | ||||||
|  | ```yaml | ||||||
|  | theme: hextra | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ### Create your first content pages | ||||||
|  |  | ||||||
|  | Let's create new content page for the home page and the documentation page: | ||||||
|  |  | ||||||
|  | ```shell | ||||||
|  | $ hugo new content/_index.md | ||||||
|  | $ hugo new content/docs/_index.md | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ### Preview the site locally | ||||||
|  |  | ||||||
|  | ```shell | ||||||
|  | $ hugo server --buildDrafts --disableFastRender | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Voila! You can see your new site at `http://localhost:1313/`. | ||||||
|  |  | ||||||
|  | {{% /steps %}} | ||||||
|  |  | ||||||
|  |  | ||||||
|  | When using [CI/CD](https://en.wikipedia.org/wiki/CI/CD) for Hugo website deployment, it's essential to ensure that the following command is executed before running the `hugo` command. | ||||||
|  |  | ||||||
|  | ```shell | ||||||
|  | git submodule update --init | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Failure to run this command will result in the theme folder not being populated with Hextra theme files, leading to a build failure. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | {{% details title="How to update theme?" %}} | ||||||
|  |  | ||||||
|  | To update all submodules in your repository to their latest commits, run the following command: | ||||||
|  |  | ||||||
|  | ```shell | ||||||
|  | $ git submodule update --remote | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | To update only Hextra to the latest commit, run the following command: | ||||||
|  |  | ||||||
|  | ```shell | ||||||
|  | git submodule update --remote themes/hextra | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | See [Git submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules) for more details. | ||||||
|  |  | ||||||
|  | {{% /details %}} | ||||||
|  |  | ||||||
| ## Next | ## Next | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ weight: 2 | |||||||
|  |  | ||||||
| Hugo reads its configuration from `hugo.yaml` in the root of your Hugo site. | Hugo reads its configuration from `hugo.yaml` in the root of your Hugo site. | ||||||
| The config file is where you can configure all aspects of your site. | The config file is where you can configure all aspects of your site. | ||||||
| You can find the config file for this site in `exampleSite/hugo.yaml` as a good starting point. | Check out the config file for this site [`exampleSite/hugo.yaml`](https://github.com/imfing/hextra/blob/main/exampleSite/hugo.yaml) on GitHub to get a comprehensive idea of available settings and best practices. | ||||||
|  |  | ||||||
| <!--more--> | <!--more--> | ||||||
|  |  | ||||||
| @@ -181,6 +181,26 @@ Include both `favicon.ico` and `favicon.svg` files in your project to ensure you | |||||||
| While `favicon.ico` is generally for older browsers, `favicon.svg` is supported by modern ones. The optional `favicon-dark.svg` can be included for a tailored experience in dark mode. | While `favicon.ico` is generally for older browsers, `favicon.svg` is supported by modern ones. The optional `favicon-dark.svg` can be included for a tailored experience in dark mode. | ||||||
| Feel free to use tools like [favicon.io](https://favicon.io/) or [favycon](https://github.com/ruisaraiva19/favycon) to generate these icons. | Feel free to use tools like [favicon.io](https://favicon.io/) or [favycon](https://github.com/ruisaraiva19/favycon) to generate these icons. | ||||||
|  |  | ||||||
|  | ### Theme Configuration | ||||||
|  |  | ||||||
|  | Use the `theme` setting to configure the default theme mode and toggle button, allowing visitors to switch between light or dark mode. | ||||||
|  |  | ||||||
|  | ```yaml {filename="hugo.yaml"} | ||||||
|  | params: | ||||||
|  |   theme: | ||||||
|  |     # light | dark | system | ||||||
|  |     default: system | ||||||
|  |     displayToggle: true | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Options for `theme.default`: | ||||||
|  |  | ||||||
|  | - `light` - always use light mode | ||||||
|  | - `dark` - always use dark mode | ||||||
|  | - `system` - sync with the operating system setting (default) | ||||||
|  |  | ||||||
|  | The `theme.displayToggle` parameter allows you to display a toggle button for changing themes. | ||||||
|  | When set to `true`, visitors can switch between light or dark mode, overriding the default setting. | ||||||
|  |  | ||||||
| ### Page Width | ### Page Width | ||||||
|  |  | ||||||
| @@ -193,11 +213,42 @@ params: | |||||||
|     width: wide |     width: wide | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| There are three available options: `full`, `wide`, and `normal`. | There are three available options: `full`, `wide`, and `normal`. By default, the page width is set to `normal`. | ||||||
| By default, the page width is set to `normal`. |  | ||||||
|  |  | ||||||
| Similarly, the width of the navbar and footer can be customized by the `params.navbar.width` and `params.footer.width` parameters. | Similarly, the width of the navbar and footer can be customized by the `params.navbar.width` and `params.footer.width` parameters. | ||||||
|  |  | ||||||
|  | ### Search Index | ||||||
|  |  | ||||||
|  | Full-text search powered by [FlexSearch](https://github.com/nextapps-de/flexsearch) is enabled by default. | ||||||
|  | To customize the search index, set the `params.search.flexsearch.index` parameter in the config file: | ||||||
|  |  | ||||||
|  | ```yaml {filename="hugo.yaml"} | ||||||
|  | params: | ||||||
|  |   # Search | ||||||
|  |   search: | ||||||
|  |     enable: true | ||||||
|  |     type: flexsearch | ||||||
|  |  | ||||||
|  |     flexsearch: | ||||||
|  |       # index page by: content | summary | heading | title | ||||||
|  |       index: content | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Options for `flexsearch.index`: | ||||||
|  |  | ||||||
|  | - `content` - full content of the page (default) | ||||||
|  | - `summary` - summary of the page, see [Hugo Content Summaries](https://gohugo.io/content-management/summaries/) for more details | ||||||
|  | - `heading` - level 1 and level 2 headings | ||||||
|  | - `title` - only include the page title | ||||||
|  |  | ||||||
|  | To exclude a page from the search index, set the `excludeSearch: true` in the front matter of the page: | ||||||
|  |  | ||||||
|  | ```yaml {filename="content/docs/guide/configuration.md"} | ||||||
|  | --- | ||||||
|  | title: Configuration | ||||||
|  | excludeSearch: true | ||||||
|  | --- | ||||||
|  | ``` | ||||||
|  |  | ||||||
| ### Google Analytics | ### Google Analytics | ||||||
|  |  | ||||||
|   | |||||||
| @@ -26,6 +26,7 @@ languages: | |||||||
|     title: "Hextra テーマ" |     title: "Hextra テーマ" | ||||||
|   zh-cn: |   zh-cn: | ||||||
|     languageName: 简体中文 |     languageName: 简体中文 | ||||||
|  |     languageCode: zh-CN | ||||||
|     weight: 3 |     weight: 3 | ||||||
|     title: Hextra |     title: Hextra | ||||||
|  |  | ||||||
| @@ -108,6 +109,11 @@ params: | |||||||
|     # full (100%), wide (90rem), normal (1280px) |     # full (100%), wide (90rem), normal (1280px) | ||||||
|     width: normal |     width: normal | ||||||
|  |  | ||||||
|  |   theme: | ||||||
|  |     # light | dark | system | ||||||
|  |     default: system | ||||||
|  |     displayToggle: true | ||||||
|  |  | ||||||
|   footer: |   footer: | ||||||
|     displayCopyright: true |     displayCopyright: true | ||||||
|     displayPoweredBy: true |     displayPoweredBy: true | ||||||
| @@ -116,9 +122,33 @@ params: | |||||||
|   displayUpdatedDate: true |   displayUpdatedDate: true | ||||||
|   dateFormat: "January 2, 2006" |   dateFormat: "January 2, 2006" | ||||||
|  |  | ||||||
|  |   # Search | ||||||
|  |   # flexsearch is enabled by default | ||||||
|   search: |   search: | ||||||
|     enable: true |     enable: true | ||||||
|  |     type: flexsearch | ||||||
|  |  | ||||||
|  |     flexsearch: | ||||||
|  |       # index page by: content | summary | heading | title | ||||||
|  |       index: content | ||||||
|  |  | ||||||
|   editURL: |   editURL: | ||||||
|     enable: true |     enable: true | ||||||
|     base: "https://github.com/imfing/hextra/edit/main/exampleSite/content" |     base: "https://github.com/imfing/hextra/edit/main/exampleSite/content" | ||||||
|  |  | ||||||
|  |   comments: | ||||||
|  |     enable: false | ||||||
|  |     type: giscus | ||||||
|  |  | ||||||
|  |     # https://giscus.app/ | ||||||
|  |     giscus: | ||||||
|  |       repo: imfing/hextra | ||||||
|  |       repoId: R_kgDOJ9fJag | ||||||
|  |       category: General | ||||||
|  |       categoryId: DIC_kwDOJ9fJas4CY7gW | ||||||
|  |       # mapping: pathname | ||||||
|  |       # strict: 0 | ||||||
|  |       # reactionsEnabled: 1 | ||||||
|  |       # emitMetadata: 0 | ||||||
|  |       # inputPosition: top | ||||||
|  |       # lang: en | ||||||
|   | |||||||
| @@ -112,6 +112,7 @@ | |||||||
|       "border-black/5", |       "border-black/5", | ||||||
|       "border-blue-200", |       "border-blue-200", | ||||||
|       "border-gray-200", |       "border-gray-200", | ||||||
|  |       "border-gray-500", | ||||||
|       "border-l", |       "border-l", | ||||||
|       "border-orange-100", |       "border-orange-100", | ||||||
|       "border-red-200", |       "border-red-200", | ||||||
| @@ -127,6 +128,7 @@ | |||||||
|       "content", |       "content", | ||||||
|       "contrast-more:border", |       "contrast-more:border", | ||||||
|       "contrast-more:border-current", |       "contrast-more:border-current", | ||||||
|  |       "contrast-more:border-gray-800", | ||||||
|       "contrast-more:border-gray-900", |       "contrast-more:border-gray-900", | ||||||
|       "contrast-more:border-neutral-400", |       "contrast-more:border-neutral-400", | ||||||
|       "contrast-more:border-primary-500", |       "contrast-more:border-primary-500", | ||||||
| @@ -152,6 +154,7 @@ | |||||||
|       "contrast-more:text-gray-800", |       "contrast-more:text-gray-800", | ||||||
|       "contrast-more:text-gray-900", |       "contrast-more:text-gray-900", | ||||||
|       "contrast-more:underline", |       "contrast-more:underline", | ||||||
|  |       "copy-icon", | ||||||
|       "cursor-default", |       "cursor-default", | ||||||
|       "cursor-pointer", |       "cursor-pointer", | ||||||
|       "dark:before:bg-neutral-800", |       "dark:before:bg-neutral-800", | ||||||
| @@ -171,6 +174,7 @@ | |||||||
|       "dark:block", |       "dark:block", | ||||||
|       "dark:border-blue-200/30", |       "dark:border-blue-200/30", | ||||||
|       "dark:border-gray-100/20", |       "dark:border-gray-100/20", | ||||||
|  |       "dark:border-gray-400", | ||||||
|       "dark:border-neutral-700", |       "dark:border-neutral-700", | ||||||
|       "dark:border-neutral-800", |       "dark:border-neutral-800", | ||||||
|       "dark:border-orange-400/30", |       "dark:border-orange-400/30", | ||||||
| @@ -188,6 +192,7 @@ | |||||||
|       "dark:hover:bg-neutral-900", |       "dark:hover:bg-neutral-900", | ||||||
|       "dark:hover:bg-primary-100/5", |       "dark:hover:bg-primary-100/5", | ||||||
|       "dark:hover:bg-primary-700", |       "dark:hover:bg-primary-700", | ||||||
|  |       "dark:hover:border-gray-100", | ||||||
|       "dark:hover:border-gray-600", |       "dark:hover:border-gray-600", | ||||||
|       "dark:hover:border-neutral-500", |       "dark:hover:border-neutral-500", | ||||||
|       "dark:hover:border-neutral-700", |       "dark:hover:border-neutral-700", | ||||||
| @@ -226,6 +231,7 @@ | |||||||
|       "data-[state=selected]:text-primary-600", |       "data-[state=selected]:text-primary-600", | ||||||
|       "decoration-from-font", |       "decoration-from-font", | ||||||
|       "duration-200", |       "duration-200", | ||||||
|  |       "duration-75", | ||||||
|       "ease-in", |       "ease-in", | ||||||
|       "ease-in-out", |       "ease-in-out", | ||||||
|       "filename", |       "filename", | ||||||
| @@ -264,6 +270,7 @@ | |||||||
|       "h-0", |       "h-0", | ||||||
|       "h-16", |       "h-16", | ||||||
|       "h-2", |       "h-2", | ||||||
|  |       "h-3.5", | ||||||
|       "h-4", |       "h-4", | ||||||
|       "h-5", |       "h-5", | ||||||
|       "h-7", |       "h-7", | ||||||
| @@ -289,6 +296,7 @@ | |||||||
|       "hover:border-gray-200", |       "hover:border-gray-200", | ||||||
|       "hover:border-gray-300", |       "hover:border-gray-300", | ||||||
|       "hover:border-gray-400", |       "hover:border-gray-400", | ||||||
|  |       "hover:border-gray-900", | ||||||
|       "hover:dark:bg-primary-500/10", |       "hover:dark:bg-primary-500/10", | ||||||
|       "hover:dark:text-primary-600", |       "hover:dark:text-primary-600", | ||||||
|       "hover:opacity-60", |       "hover:opacity-60", | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								i18n/en.yaml
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								i18n/en.yaml
									
									
									
									
									
								
							| @@ -1,5 +1,9 @@ | |||||||
| onThisPage: "On this page" | backToTop: "Scroll to top" | ||||||
|  | changeLanguage: "Change language" | ||||||
|  | changeTheme: "Change theme" | ||||||
|  | copyright: "© 2023 Hextra Project." | ||||||
| editThisPage: "Edit this page on GitHub →" | editThisPage: "Edit this page on GitHub →" | ||||||
| lastUpdated: "Last updated on" | lastUpdated: "Last updated on" | ||||||
|  | onThisPage: "On this page" | ||||||
| copyright: "© 2023 Hextra Project." | readMore: "Read more →" | ||||||
|  | searchPlaceholder: "Search..." | ||||||
|   | |||||||
							
								
								
									
										7
									
								
								i18n/es.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								i18n/es.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | onThisPage: "En esta página" | ||||||
|  | editThisPage: "Edita esta página en GitHub →" | ||||||
|  | lastUpdated: "Última actualización" | ||||||
|  |  | ||||||
|  | backToTop: "Subir al inicio" | ||||||
|  |  | ||||||
|  | copyright: "© 2023 Hextra Project." | ||||||
							
								
								
									
										9
									
								
								i18n/ko.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								i18n/ko.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | backToTop: "맨위로 스크롤" | ||||||
|  | changeLanguage: "언어변경" | ||||||
|  | changeTheme: "테마변경" | ||||||
|  | copyright: "© 2023 Hextra Project." | ||||||
|  | editThisPage: "Github에서 편집하기 →" | ||||||
|  | lastUpdated: "마지막 수정일자" | ||||||
|  | onThisPage: "페이지 목차" | ||||||
|  | readMore: "더보기 →" | ||||||
|  | searchPlaceholder: "검색..." | ||||||
							
								
								
									
										7
									
								
								i18n/pt.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								i18n/pt.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | onThisPage: "Nesta página" | ||||||
|  | editThisPage: "Edita esta página no GitHub →" | ||||||
|  | lastUpdated: "Última actualização" | ||||||
|  |  | ||||||
|  | backToTop: "Voltar ao topo" | ||||||
|  |  | ||||||
|  | copyright: "© 2023 Projecto Hextra." | ||||||
							
								
								
									
										5
									
								
								i18n/sw.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								i18n/sw.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | onThisPage: "Kwenye ukurasa huu" | ||||||
|  | editThisPage: "Hariri ukurasa huu kwenye GitHub →" | ||||||
|  | lastUpdated: "Ilisasishwa mwisho" | ||||||
|  | backToTop: "Tembeza hadi juu" | ||||||
|  | copyright: "© 2023 Hextra Project." | ||||||
							
								
								
									
										7
									
								
								i18n/vi.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								i18n/vi.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | onThisPage: "Ở trang này" | ||||||
|  | editThisPage: "Sửa trang này trên GitHub →" | ||||||
|  | lastUpdated: "Lần cuối cập nhật lúc" | ||||||
|  |  | ||||||
|  | backToTop: "Lướt lên đầu trang" | ||||||
|  |  | ||||||
|  | copyright: "© 2023 Hextra Project." | ||||||
| @@ -12,4 +12,6 @@ onThisPage: "此页上" | |||||||
| editThisPage: "在 GitHub 上编辑此页 →" | editThisPage: "在 GitHub 上编辑此页 →" | ||||||
| lastUpdated: "最后更新于" | lastUpdated: "最后更新于" | ||||||
|  |  | ||||||
|  | backToTop: "返回顶部" | ||||||
|  |  | ||||||
| copyright: "© 2023 Hextra Project." | copyright: "© 2023 Hextra Project." | ||||||
|   | |||||||
| @@ -15,9 +15,13 @@ | |||||||
|     <pre><code id="code-block-{{ .Ordinal }}">{{ .Inner }}</code></pre> |     <pre><code id="code-block-{{ .Ordinal }}">{{ .Inner }}</code></pre> | ||||||
|   {{- end -}} |   {{- end -}} | ||||||
|   <div class="opacity-0 transition group-hover/code:opacity-100 flex gap-1 absolute m-[11px] right-0 {{ if $filename }}top-8{{ else }}top-0{{ end }}"> |   <div class="opacity-0 transition group-hover/code:opacity-100 flex gap-1 absolute m-[11px] right-0 {{ if $filename }}top-8{{ else }}top-0{{ end }}"> | ||||||
|     <button class="code-copy-btn group/copybtn transition-all active:opacity-50 bg-primary-700/5 border border-black/5 text-gray-600 hover:text-gray-900 rounded-md p-1.5 dark:bg-primary-300/10 dark:border-white/10 dark:text-gray-400 dark:hover:text-gray-50" title="Copy code" data-clipboard-target="#code-block-{{ .Ordinal }}"> |     <button | ||||||
|       {{ partial "utils/icon.html" (dict "name" "copy" "attributes" "class=\"group-[.copied]/copybtn:hidden pointer-events-none h-4 w-4\"") }} |       class="code-copy-btn group/copybtn transition-all active:opacity-50 bg-primary-700/5 border border-black/5 text-gray-600 hover:text-gray-900 rounded-md p-1.5 dark:bg-primary-300/10 dark:border-white/10 dark:text-gray-400 dark:hover:text-gray-50" | ||||||
|       {{ partial "utils/icon.html" (dict "name" "check" "attributes" "class=\"hidden group-[.copied]/copybtn:block success-icon pointer-events-none h-4 w-4\"") }} |       title="Copy code" | ||||||
|  |       data-clipboard-target="#code-block-{{ .Ordinal }}" | ||||||
|  |     > | ||||||
|  |       <div class="group-[.copied]/copybtn:hidden copy-icon pointer-events-none h-4 w-4"></div> | ||||||
|  |       <div class="hidden group-[.copied]/copybtn:block success-icon pointer-events-none h-4 w-4"></div> | ||||||
|     </button> |     </button> | ||||||
|   </div> |   </div> | ||||||
| </div> | </div> | ||||||
|   | |||||||
| @@ -1,10 +1,13 @@ | |||||||
| <!DOCTYPE html> | <!DOCTYPE html> | ||||||
| <html lang="{{ .Site.Language.Lang }}"> | <html lang="{{ .Site.Language.Lang }}"> | ||||||
|   {{- partial "head.html" . -}} |   {{ partial "head.html" . -}} | ||||||
|   <body dir="ltr"> |   <body dir="ltr"> | ||||||
|     {{- partial "navbar.html" . -}} |     {{ partial "navbar.html" . -}} | ||||||
|     {{- block "main" . }}{{ end -}} |     {{- block "main" . }}{{ end -}} | ||||||
|     {{- if (.Site.Params.footer.enable | default true) }}{{ partial "footer.html" . }}{{ end }} |     {{- if or (eq .Site.Params.footer.enable nil) (.Site.Params.footer.enable) }} | ||||||
|  |       {{ partial "footer.html" . }} | ||||||
|  |     {{ end -}} | ||||||
|   </body> |   </body> | ||||||
|   {{ partial "scripts.html" . }} |   {{ partialCached "scripts.html" . }} | ||||||
|  |   {{ partial "third-party/scripts.html" . }} | ||||||
| </html> | </html> | ||||||
|   | |||||||
| @@ -10,6 +10,7 @@ | |||||||
|         </div> |         </div> | ||||||
|         <div class="mt-16"></div> |         <div class="mt-16"></div> | ||||||
|         {{ partial "components/last-updated.html" . }} |         {{ partial "components/last-updated.html" . }} | ||||||
|  |         {{ partial "components/comments.html" . }} | ||||||
|       </main> |       </main> | ||||||
|     </article> |     </article> | ||||||
|   </div> |   </div> | ||||||
|   | |||||||
| @@ -10,6 +10,8 @@ | |||||||
|         <div class="content"> |         <div class="content"> | ||||||
|           {{ .Content }} |           {{ .Content }} | ||||||
|         </div> |         </div> | ||||||
|  |         <div class="mt-16"></div> | ||||||
|  |         {{ partial "components/comments.html" . }} | ||||||
|       </main> |       </main> | ||||||
|     </article> |     </article> | ||||||
|   </div> |   </div> | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| {{ define "main" }} | {{ define "main" }} | ||||||
|  | {{- $readMore := (T "readMore") | default "Read more →" -}} | ||||||
|   <div class='mx-auto flex {{ partial "utils/page-width" . }}'> |   <div class='mx-auto flex {{ partial "utils/page-width" . }}'> | ||||||
|     {{ partial "sidebar.html" (dict "context" . "disableSidebar" true "displayPlaceholder" true) }} |     {{ partial "sidebar.html" (dict "context" . "disableSidebar" true "displayPlaceholder" true) }} | ||||||
|     <article class="w-full break-words flex min-h-[calc(100vh-var(--navbar-height))] min-w-0 justify-center pb-8 pr-[calc(env(safe-area-inset-right)-1.5rem)]"> |     <article class="w-full break-words flex min-h-[calc(100vh-var(--navbar-height))] min-w-0 justify-center pb-8 pr-[calc(env(safe-area-inset-right)-1.5rem)]"> | ||||||
| @@ -11,7 +12,7 @@ | |||||||
|             <h3><a style="color: inherit; text-decoration: none;" class="block font-semibold mt-8 text-2xl " href="{{ .RelPermalink }}">{{ .Title }}</a></h3> |             <h3><a style="color: inherit; text-decoration: none;" class="block font-semibold mt-8 text-2xl " href="{{ .RelPermalink }}">{{ .Title }}</a></h3> | ||||||
|             <p class="opacity-80 mt-6 leading-7"> |             <p class="opacity-80 mt-6 leading-7"> | ||||||
|               {{- partial "utils/page-description" . }} |               {{- partial "utils/page-description" . }} | ||||||
|               <span class="inline-block"> <a class="text-[color:hsl(var(--primary-hue),100%,50%)] underline underline-offset-2 decoration-from-font" href="{{ .RelPermalink }}">Read more →</a> </span> |               <span class="inline-block"> <a class="text-[color:hsl(var(--primary-hue),100%,50%)] underline underline-offset-2 decoration-from-font" href="{{ .RelPermalink }}">{{ $readMore }}</a> </span> | ||||||
|             </p> |             </p> | ||||||
|             <p class="opacity-50 text-sm mt-6 leading-7">{{ partial "utils/format-date" .Date }}</p> |             <p class="opacity-50 text-sm mt-6 leading-7">{{ partial "utils/format-date" .Date }}</p> | ||||||
|           </div> |           </div> | ||||||
|   | |||||||
| @@ -28,6 +28,7 @@ | |||||||
|         {{ partial "components/last-updated.html" . }} |         {{ partial "components/last-updated.html" . }} | ||||||
|         {{ .Scratch.Set "reversePagination" true }} |         {{ .Scratch.Set "reversePagination" true }} | ||||||
|         {{ partial "components/pager.html" . }} |         {{ partial "components/pager.html" . }} | ||||||
|  |         {{ partial "components/comments.html" . }} | ||||||
|       </main> |       </main> | ||||||
|     </article> |     </article> | ||||||
|   </div> |   </div> | ||||||
|   | |||||||
| @@ -9,9 +9,9 @@ | |||||||
|           <h1>{{ .Title }}</h1> |           <h1>{{ .Title }}</h1> | ||||||
|           {{ .Content }} |           {{ .Content }} | ||||||
|         </div> |         </div> | ||||||
|         <div class="mt-16"></div> |  | ||||||
|         {{ partial "components/last-updated.html" . }} |         {{ partial "components/last-updated.html" . }} | ||||||
|         {{ partial "components/pager.html" . }} |         {{ partial "components/pager.html" . }} | ||||||
|  |         {{ partial "components/comments.html" . }} | ||||||
|       </main> |       </main> | ||||||
|     </article> |     </article> | ||||||
|   </div> |   </div> | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ | |||||||
|         </div> |         </div> | ||||||
|         {{ partial "components/last-updated.html" . }} |         {{ partial "components/last-updated.html" . }} | ||||||
|         {{ partial "components/pager.html" . }} |         {{ partial "components/pager.html" . }} | ||||||
|  |         {{ partial "components/comments.html" . }} | ||||||
|       </main> |       </main> | ||||||
|     </article> |     </article> | ||||||
|   </div> |   </div> | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								layouts/partials/components/comments.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								layouts/partials/components/comments.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | {{- $enableComments := site.Params.comments.enable | default false -}} | ||||||
|  |  | ||||||
|  | {{ if not (eq .Params.comments nil) }} | ||||||
|  |   {{ $enableComments = .Params.comments }} | ||||||
|  | {{ end }} | ||||||
|  |  | ||||||
|  | {{- if $enableComments -}} | ||||||
|  |   {{- if eq site.Params.comments.type "giscus" -}} | ||||||
|  |     {{ partial "components/giscus.html" . }} | ||||||
|  |   {{- end -}} | ||||||
|  | {{- end -}} | ||||||
							
								
								
									
										62
									
								
								layouts/partials/components/giscus.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								layouts/partials/components/giscus.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | |||||||
|  | {{- $lang := site.Language.LanguageCode | default `en` -}} | ||||||
|  |  | ||||||
|  | {{- with site.Params.comments.giscus -}} | ||||||
|  | <script> | ||||||
|  |   /* | ||||||
|  |    * "preferred color scheme" theme in giscus works using "prefers-color-scheme" in media query. | ||||||
|  |    * but, hugo's theme switch function works by using "color-theme" in local storage. | ||||||
|  |    * This solution was created with reference to: | ||||||
|  |    * https://github.com/giscus/giscus/issues/336#issuecomment-1214366281 | ||||||
|  |   */ | ||||||
|  |   function getGiscusTheme() { | ||||||
|  |     return localStorage.getItem("color-theme"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   function setGiscusTheme() { | ||||||
|  |     function sendMessage(message) { | ||||||
|  |       const iframe = document.querySelector('iframe.giscus-frame'); | ||||||
|  |       if (!iframe) return; | ||||||
|  |       iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app'); | ||||||
|  |     } | ||||||
|  |     sendMessage({ | ||||||
|  |       setConfig: { | ||||||
|  |         theme: getGiscusTheme(), | ||||||
|  |       }, | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   document.addEventListener('DOMContentLoaded', function () { | ||||||
|  |     const giscusAttributes = { | ||||||
|  |       "src": "https://giscus.app/client.js", | ||||||
|  |       "data-repo": "{{ .repo }}", | ||||||
|  |       "data-repo-id": "{{ .repoId }}", | ||||||
|  |       "data-category": "{{ .category }}", | ||||||
|  |       "data-category-id": "{{ .categoryId }}", | ||||||
|  |       "data-mapping": "{{ .mapping | default `pathname` }}", | ||||||
|  |       "data-strict": "{{ (string .strict) | default 0 }}", | ||||||
|  |       "data-reactions-enabled": "{{ (string .reactionsEnabled) |  default 1 }}", | ||||||
|  |       "data-emit-metadata": "{{ (string .emitMetadata) | default 0 }}", | ||||||
|  |       "data-input-position": "{{ .inputPosition | default `top` }}", | ||||||
|  |       "data-theme": getGiscusTheme(), | ||||||
|  |       "data-lang": "{{ .lang | default $lang }}", | ||||||
|  |       "crossorigin": "anonymous", | ||||||
|  |       "async": "", | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     // Dynamically create script tag | ||||||
|  |     const giscusScript = document.createElement("script"); | ||||||
|  |     Object.entries(giscusAttributes).forEach(([key, value]) => giscusScript.setAttribute(key, value)); | ||||||
|  |     document.getElementById('giscus').appendChild(giscusScript); | ||||||
|  |  | ||||||
|  |     // Update giscus theme when theme switcher is clicked | ||||||
|  |     const toggles = document.querySelectorAll(".theme-toggle"); | ||||||
|  |     if (toggles) { | ||||||
|  |       toggles.forEach(toggle => toggle.addEventListener('click', setGiscusTheme)); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <div id="giscus"></div> | ||||||
|  | {{- else -}} | ||||||
|  |   {{ warnf "giscus is not configured" }} | ||||||
|  | {{- end -}} | ||||||
| @@ -5,15 +5,23 @@ | |||||||
| {{- $prev := cond $reversePagination .PrevInSection .NextInSection -}} | {{- $prev := cond $reversePagination .PrevInSection .NextInSection -}} | ||||||
| {{- $next := cond $reversePagination .NextInSection .PrevInSection -}} | {{- $next := cond $reversePagination .NextInSection .PrevInSection -}} | ||||||
|  |  | ||||||
| {{- with .Params.prev -}} | {{- if eq .Params.prev false }} | ||||||
|   {{- with $.Site.GetPage . -}} |   {{- if $reversePagination }}{{ $next = false }}{{ else }}{{ $prev = false }}{{ end -}} | ||||||
|     {{- if $reversePagination }}{{ $next = . }}{{ else }}{{ $prev = . }}{{ end -}} | {{ else }} | ||||||
|  |   {{- with .Params.prev -}} | ||||||
|  |     {{- with $.Site.GetPage . -}} | ||||||
|  |       {{- if $reversePagination }}{{ $next = . }}{{ else }}{{ $prev = . }}{{ end -}} | ||||||
|  |     {{- end -}} | ||||||
|   {{- end -}} |   {{- end -}} | ||||||
| {{- end -}} | {{- end -}} | ||||||
|  |  | ||||||
| {{- with .Params.next -}} | {{- if eq .Params.next false }} | ||||||
|   {{- with $.Site.GetPage . -}} |   {{- if $reversePagination }}{{ $prev = false }}{{ else }}{{ $next = false }}{{ end -}} | ||||||
|     {{- if $reversePagination }}{{ $prev = . }}{{ else }}{{ $next = . }}{{ end -}} | {{ else }} | ||||||
|  |   {{- with .Params.next -}} | ||||||
|  |     {{- with $.Site.GetPage . -}} | ||||||
|  |       {{- if $reversePagination }}{{ $prev = . }}{{ else }}{{ $next = . }}{{ end -}} | ||||||
|  |     {{- end -}} | ||||||
|   {{- end -}} |   {{- end -}} | ||||||
| {{- end -}} | {{- end -}} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| {{- $enableFooterSwitches := .Scratch.Get "enableFooterSwitches" | default false -}} | {{- $enableFooterSwitches := .Scratch.Get "enableFooterSwitches" | default false -}} | ||||||
|  | {{- $displayThemeToggle := site.Params.theme.displayToggle | default true -}} | ||||||
|  |  | ||||||
| {{- $copyright := (T "copyright") | default "© 2023 Hextra." -}} | {{- $copyright := (T "copyright") | default "© 2023 Hextra." -}} | ||||||
|  |  | ||||||
| @@ -11,20 +12,23 @@ | |||||||
|   {{ end -}} |   {{ end -}} | ||||||
| {{- end -}} | {{- end -}} | ||||||
|  |  | ||||||
|  |  | ||||||
| <footer class="hextra-footer bg-gray-100 pb-[env(safe-area-inset-bottom)] dark:bg-neutral-900 print:bg-transparent"> | <footer class="hextra-footer bg-gray-100 pb-[env(safe-area-inset-bottom)] dark:bg-neutral-900 print:bg-transparent"> | ||||||
|   {{- if $enableFooterSwitches }} |   {{- if $enableFooterSwitches -}} | ||||||
|     <div class='mx-auto flex gap-2 py-2 px-4 {{ $footerWidth }}'> |     <div class="mx-auto flex gap-2 py-2 px-4 {{ $footerWidth }}"> | ||||||
|       {{- partial "language-switch.html" (dict "context" .) -}} |       {{- partial "language-switch.html" (dict "context" .) -}} | ||||||
|       {{- partial "theme-toggle.html" -}} |       {{- with $displayThemeToggle }}{{ partial "theme-toggle.html" }}{{ end -}} | ||||||
|     </div> |     </div> | ||||||
|   {{ end -}} |     {{- if or site.IsMultiLingual $displayThemeToggle -}} | ||||||
|   <hr class="dark:border-neutral-800" /> |       <hr class="dark:border-neutral-800" /> | ||||||
|  |     {{- end -}} | ||||||
|  |   {{- end -}} | ||||||
|   <div |   <div | ||||||
|     class='{{ $footerWidth }} mx-auto flex justify-center py-12 pl-[max(env(safe-area-inset-left),1.5rem)] pr-[max(env(safe-area-inset-right),1.5rem)] text-gray-600 dark:text-gray-400 md:justify-start' |     class="{{ $footerWidth }} mx-auto flex justify-center py-12 pl-[max(env(safe-area-inset-left),1.5rem)] pr-[max(env(safe-area-inset-right),1.5rem)] text-gray-600 dark:text-gray-400 md:justify-start" | ||||||
|   > |   > | ||||||
|     <div class="flex w-full flex-col items-center sm:items-start"> |     <div class="flex w-full flex-col items-center sm:items-start"> | ||||||
|       {{- if (.Site.Params.footer.displayPoweredBy | default true) }}<div class="font-semibold">{{ template "theme-credit" . }}</div>{{ end }} |       {{- if (.Site.Params.footer.displayPoweredBy | default true) }}<div class="font-semibold">{{ template "theme-credit" . }}</div>{{ end }} | ||||||
|       {{- if .Site.Params.footer.displayCopyright }}<p class="mt-6 text-xs">{{ $copyright | markdownify }}</p>{{ end }} |       {{- if .Site.Params.footer.displayCopyright }}<div class="mt-6 text-xs">{{ $copyright | markdownify }}</div>{{ end }} | ||||||
|     </div> |     </div> | ||||||
|   </div> |   </div> | ||||||
| </footer> | </footer> | ||||||
|   | |||||||
| @@ -33,13 +33,25 @@ | |||||||
|  |  | ||||||
|   <script> |   <script> | ||||||
|     /* Initialize light/dark mode */ |     /* Initialize light/dark mode */ | ||||||
|     if (localStorage.getItem("color-theme") === "dark" || (!("color-theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches)) { |     const defaultTheme = '{{ site.Params.theme.default | default `system`}}'; | ||||||
|  |  | ||||||
|  |     const setDarkTheme = () => { | ||||||
|       document.documentElement.classList.add("dark"); |       document.documentElement.classList.add("dark"); | ||||||
|       document.documentElement.style.colorScheme = "dark"; |       document.documentElement.style.colorScheme = "dark"; | ||||||
|     } else { |     } | ||||||
|  |     const setLightTheme = () => { | ||||||
|       document.documentElement.classList.remove("dark"); |       document.documentElement.classList.remove("dark"); | ||||||
|       document.documentElement.style.colorScheme = "light"; |       document.documentElement.style.colorScheme = "light"; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if ("color-theme" in localStorage) { | ||||||
|  |       localStorage.getItem("color-theme") === "dark" ? setDarkTheme() : setLightTheme(); | ||||||
|  |     } else { | ||||||
|  |       defaultTheme === "dark" ? setDarkTheme() : setLightTheme(); | ||||||
|  |       if (defaultTheme === "system") { | ||||||
|  |         window.matchMedia("(prefers-color-scheme: dark)").matches ? setDarkTheme() : setLightTheme(); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|   </script> |   </script> | ||||||
|  |  | ||||||
|   {{ partial "custom/head-end.html" . }} |   {{ partial "custom/head-end.html" . }} | ||||||
|   | |||||||
| @@ -30,7 +30,7 @@ | |||||||
|     {{- $currentPage := . -}} |     {{- $currentPage := . -}} | ||||||
|     {{- range .Site.Menus.main -}} |     {{- range .Site.Menus.main -}} | ||||||
|       {{- if eq .Params.type "search" -}} |       {{- if eq .Params.type "search" -}} | ||||||
|         {{- partial "search.html" (dict "params" .Params) -}} |         {{- partialCached "search.html" $currentPage -}} | ||||||
|       {{- else -}} |       {{- else -}} | ||||||
|         {{- $external := strings.HasPrefix .URL "http" -}} |         {{- $external := strings.HasPrefix .URL "http" -}} | ||||||
|         {{/* Display icon menu item */}} |         {{/* Display icon menu item */}} | ||||||
|   | |||||||
| @@ -1,68 +1,32 @@ | |||||||
| {{- $jsTheme := resources.Get "js/theme.js" -}} | {{- $jsTheme := resources.Get "js/theme.js" | resources.ExecuteAsTemplate "theme.js" . -}} | ||||||
| {{- $jsMenu := resources.Get "js/menu.js" -}} | {{- $jsMenu := resources.Get "js/menu.js" -}} | ||||||
| {{- $jsTabs := resources.Get "js/tabs.js" -}} | {{- $jsTabs := resources.Get "js/tabs.js" -}} | ||||||
| {{- $jsLang := resources.Get "js/lang.js" -}} | {{- $jsLang := resources.Get "js/lang.js" -}} | ||||||
| {{- $jsCodeCopy := resources.Get "js/code-copy.js" -}} | {{- $jsCodeCopy := resources.Get "js/code-copy.js" -}} | ||||||
| {{- $jsFileTree := resources.Get "js/filetree.js" -}} | {{- $jsFileTree := resources.Get "js/filetree.js" -}} | ||||||
| {{- $jsSidebar := resources.Get "js/sidebar.js" -}} | {{- $jsSidebar := resources.Get "js/sidebar.js" -}} | ||||||
|  | {{- $jsBackToTop := resources.Get "js/back-to-top.js" -}} | ||||||
|  |  | ||||||
| {{- $scripts := slice $jsTheme $jsMenu $jsCodeCopy $jsTabs $jsLang $jsFileTree $jsSidebar | resources.Concat "js/main.js" -}} | {{- $scripts := slice $jsTheme $jsMenu $jsCodeCopy $jsTabs $jsLang $jsFileTree $jsSidebar $jsBackToTop | resources.Concat "js/main.js" -}} | ||||||
| {{- if hugo.IsProduction -}} | {{- if hugo.IsProduction -}} | ||||||
|   {{- $scripts = $scripts | minify | fingerprint -}} |   {{- $scripts = $scripts | minify | fingerprint -}} | ||||||
| {{- end -}} | {{- end -}} | ||||||
| <script defer src="{{ $scripts.RelPermalink }}" integrity="{{ $scripts.Data.Integrity }}"></script> | <script defer src="{{ $scripts.RelPermalink }}" integrity="{{ $scripts.Data.Integrity }}"></script> | ||||||
|  |  | ||||||
| {{/* FlexSearch */}} |  | ||||||
|  | {{/* Search */}} | ||||||
| {{- if (site.Params.search.enable | default true) -}} | {{- if (site.Params.search.enable | default true) -}} | ||||||
|   {{- $jsSearchScript := printf "%s.search.js" .Language.Lang -}} |   {{- $searchType := site.Params.search.type | default "flexsearch" -}} | ||||||
|   {{- $jsSearch := resources.Get "js/flexsearch.js" | resources.ExecuteAsTemplate $jsSearchScript . -}} |   {{- if eq $searchType "flexsearch" -}} | ||||||
|   {{- if hugo.IsProduction -}} |     {{- $jsSearchScript := printf "%s.search.js" .Language.Lang -}} | ||||||
|     {{- $jsSearch = $jsSearch | minify | fingerprint -}} |     {{- $jsSearch := resources.Get "js/flexsearch.js" | resources.ExecuteAsTemplate $jsSearchScript . -}} | ||||||
|  |     {{- if hugo.IsProduction -}} | ||||||
|  |       {{- $jsSearch = $jsSearch | minify | fingerprint -}} | ||||||
|  |     {{- end -}} | ||||||
|  |     {{- $flexSearchJS := resources.Get "lib/flexsearch/flexsearch.bundle.min.js" | fingerprint -}} | ||||||
|  |     <script defer src="{{ $flexSearchJS.RelPermalink }}" integrity="{{ $flexSearchJS.Data.Integrity }}"></script> | ||||||
|  |     <script defer src="{{ $jsSearch.RelPermalink }}" integrity="{{ $jsSearch.Data.Integrity }}"></script> | ||||||
|  |   {{- else -}} | ||||||
|  |     {{- errorf `search type "%s" is not supported` $searchType -}} | ||||||
|   {{- end -}} |   {{- end -}} | ||||||
|   {{- $flexSearchJS := resources.Get "lib/flexsearch/flexsearch.bundle.min.js" | fingerprint -}} |  | ||||||
|   <script defer src="{{ $flexSearchJS.RelPermalink }}" integrity="{{ $flexSearchJS.Data.Integrity }}"></script> |  | ||||||
|   <script defer src="{{ $jsSearch.RelPermalink }}" integrity="{{ $jsSearch.Data.Integrity }}"></script> |  | ||||||
| {{- end -}} | {{- end -}} | ||||||
|  |  | ||||||
| {{/* Mermaid */}} |  | ||||||
| {{/* FIXME: need to investigate .Page.Store hasMermaid is set for homepage */}} |  | ||||||
| {{- if and (.Page.Store.Get "hasMermaid") (not .Page.IsHome) -}} |  | ||||||
|   {{- $mermaidJS := resources.Get "lib/mermaid/mermaid.min.js" | fingerprint -}} |  | ||||||
|   <script defer src="{{ $mermaidJS.RelPermalink }}" integrity="{{ $mermaidJS.Data.Integrity }}"></script> |  | ||||||
|   <script> |  | ||||||
|     document.addEventListener("DOMContentLoaded", function () { |  | ||||||
|       const theme = document.documentElement.classList.contains("dark") ? "dark" : "default"; |  | ||||||
|       mermaid.initialize({ startOnLoad: true, theme: theme }); |  | ||||||
|     }); |  | ||||||
|   </script> |  | ||||||
| {{- end -}} |  | ||||||
|  |  | ||||||
| {{/* KaTex */}} |  | ||||||
| {{- if .Page.Params.math -}} |  | ||||||
|   {{- $katexCSS := resources.Get "lib/katex/katex.min.css" | fingerprint -}} |  | ||||||
|   {{- $katexJS := resources.Get "lib/katex/katex.min.js" | fingerprint -}} |  | ||||||
|   {{- $mhchemJS := resources.Get "lib/katex/mhchem.min.js" | fingerprint -}} |  | ||||||
|   {{- $katexAutoRenderJS := resources.Get "lib/katex/auto-render.min.js" | fingerprint -}} |  | ||||||
|   <link type="text/css" rel="stylesheet" href="{{ $katexCSS.RelPermalink }}" integrity="{{ $katexCSS.Data.Integrity }}" /> |  | ||||||
|   <script defer src="{{ $katexJS.RelPermalink }}" integrity="{{ $katexJS.Data.Integrity }}"></script> |  | ||||||
|   <script defer src="{{ $katexAutoRenderJS.RelPermalink }}" integrity="{{ $katexAutoRenderJS.Data.Integrity }}"></script> |  | ||||||
|   <script defer src="{{ $mhchemJS.RelPermalink }}" integrity="{{ $mhchemJS.Data.Integrity }}"></script> |  | ||||||
|   {{ $katexFonts := resources.Match "lib/katex/fonts/*" }} |  | ||||||
|   {{- range $katexFonts -}} |  | ||||||
|     {{ .Publish }} |  | ||||||
|   {{- end -}} |  | ||||||
|   <script> |  | ||||||
|     // TODO: make render options configurable |  | ||||||
|     document.addEventListener("DOMContentLoaded", function () { |  | ||||||
|       renderMathInElement(document.body, { |  | ||||||
|         delimiters: [ |  | ||||||
|           { left: "$$", right: "$$", display: true }, |  | ||||||
|           { left: "$", right: "$", display: false }, |  | ||||||
|           { left: "\\(", right: "\\)", display: false }, |  | ||||||
|           { left: "\\[", right: "\\]", display: true }, |  | ||||||
|         ], |  | ||||||
|         throwOnError: false, |  | ||||||
|       }); |  | ||||||
|     }); |  | ||||||
|   </script> |  | ||||||
| {{ end }} |  | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ | |||||||
|     <kbd |     <kbd | ||||||
|       class="absolute my-1.5 select-none ltr:right-1.5 rtl:left-1.5 h-5 rounded bg-white px-1.5 font-mono text-[10px] font-medium text-gray-500 border dark:border-gray-100/20 dark:bg-dark/50 contrast-more:border-current contrast-more:text-current contrast-more:dark:border-current items-center gap-1 transition-opacity pointer-events-none hidden sm:flex" |       class="absolute my-1.5 select-none ltr:right-1.5 rtl:left-1.5 h-5 rounded bg-white px-1.5 font-mono text-[10px] font-medium text-gray-500 border dark:border-gray-100/20 dark:bg-dark/50 contrast-more:border-current contrast-more:text-current contrast-more:dark:border-current items-center gap-1 transition-opacity pointer-events-none hidden sm:flex" | ||||||
|     > |     > | ||||||
|       <span class="text-xs">⌘</span>K |       CTRL K | ||||||
|     </kbd> |     </kbd> | ||||||
|   </div> |   </div> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6,134 +6,40 @@ | |||||||
| {{- $sidebarClass := cond $disableSidebar (cond $displayPlaceholder "md:hidden xl:block" "md:hidden") "md:sticky" -}} | {{- $sidebarClass := cond $disableSidebar (cond $displayPlaceholder "md:hidden xl:block" "md:hidden") "md:sticky" -}} | ||||||
|  |  | ||||||
| {{- $navRoot := cond (eq site.Home.Type "docs") site.Home $context.FirstSection -}} | {{- $navRoot := cond (eq site.Home.Type "docs") site.Home $context.FirstSection -}} | ||||||
| {{- $navPages := union $navRoot.RegularPages $navRoot.Sections -}} |  | ||||||
| {{- $pageURL := $context.RelPermalink -}} | {{- $pageURL := $context.RelPermalink -}} | ||||||
|  |  | ||||||
|  |  | ||||||
| <aside class="sidebar-container flex flex-col print:hidden md:top-16 md:shrink-0 md:w-64 md:self-start max-md:[transform:translate3d(0,-100%,0)] {{ $sidebarClass }}"> | <aside class="sidebar-container flex flex-col print:hidden md:top-16 md:shrink-0 md:w-64 md:self-start max-md:[transform:translate3d(0,-100%,0)] {{ $sidebarClass }}"> | ||||||
|   <!-- Search bar on small screen --> |   {{/* Search bar on small screen */}} | ||||||
|   <div class="px-4 pt-4 md:hidden"> |   {{- partialCached "sidebar/mobile-search" . -}} | ||||||
|     {{ partial "search.html" }} |  | ||||||
|   </div> |  | ||||||
|   <div class="hextra-scrollbar overflow-y-auto overflow-x-hidden p-4 grow md:h-[calc(100vh-var(--navbar-height)-var(--menu-height))]"> |   <div class="hextra-scrollbar overflow-y-auto overflow-x-hidden p-4 grow md:h-[calc(100vh-var(--navbar-height)-var(--menu-height))]"> | ||||||
|     <ul class="flex flex-col gap-1 md:hidden"> |     <ul class="flex flex-col gap-1 md:hidden"> | ||||||
|       <!-- Nav --> |       {{/* Mobile Navigation */}} | ||||||
|       {{ template "sidebar-main" (dict "context" site.Home "pageURL" $pageURL "page" $context "toc" true) -}} |       {{ $treeMobile := partialCached "sidebar/section-tree" site.Home site.Home }} | ||||||
|       {{ template "sidebar-footer" }} |       {{ partial "sidebar/render-tree" (dict "context" site.Home "page" $context "tree" ($treeMobile | unmarshal)) }} | ||||||
|  |       {{ partialCached "sidebar/extra" $context }} | ||||||
|     </ul> |     </ul> | ||||||
|  |  | ||||||
|     <!-- Sidebar on large screen --> |     {{/* Sidebar on large screen */}} | ||||||
|     {{- if $disableSidebar -}} |     <ul class="flex flex-col gap-1 max-md:hidden"> | ||||||
|       {{- if $displayPlaceholder }}<div class="max-xl:hidden h-0 w-64 shrink-0"></div>{{ end -}} |       {{ $tree := partialCached "sidebar/section-tree" $navRoot $navRoot }} | ||||||
|       {{ .context.Scratch.Set "enableFooterSwitches" true }} |       {{ partial "sidebar/render-tree" (dict "context" $navRoot "page" $context "tree" ($tree | unmarshal)) }} | ||||||
|     {{- else -}} |       {{ partialCached "sidebar/extra" $context }} | ||||||
|       <ul class="flex flex-col gap-1 max-md:hidden"> |     </ul> | ||||||
|         {{ template "sidebar-main" (dict "context" $navRoot "page" $context  "pageURL" $pageURL) }} |  | ||||||
|         {{ template "sidebar-footer" }} |  | ||||||
|       </ul> |  | ||||||
|     {{ end -}} |  | ||||||
|   </div> |  | ||||||
|   {{/* Hide theme switch when sidebar is disabled */}} |  | ||||||
|   {{ $switchesClass := cond $disableSidebar "md:hidden" "" }} |  | ||||||
|   <div class="{{ $switchesClass }} {{ with site.IsMultiLingual }}justify-end{{ end }} sticky bottom-0 bg-white dark:bg-dark mx-4 py-4 shadow-[0_-12px_16px_#fff] flex items-center gap-2 dark:border-neutral-800 dark:shadow-[0_-12px_16px_#111] contrast-more:border-neutral-400 contrast-more:shadow-none contrast-more:dark:shadow-none border-t" data-toggle-animation="show"> |  | ||||||
|     {{- with site.IsMultiLingual }} |  | ||||||
|       {{ partial "language-switch" (dict "context" $context "grow" true) }} |  | ||||||
|       {{ partial "theme-toggle" (dict "hideLabel" true) }} |  | ||||||
|     {{ else }} |  | ||||||
|       <div class="flex grow flex-col"> |  | ||||||
|         {{ partial "theme-toggle" }} |  | ||||||
|       </div> |  | ||||||
|     {{ end -}} |  | ||||||
|   </div> |   </div> | ||||||
|  |  | ||||||
|  |   {{ partial "sidebar/switches" (dict "context" $context "disableSidebar" $disableSidebar) }} | ||||||
| </aside> | </aside> | ||||||
|  |  | ||||||
| {{- define "sidebar-main" -}} | {{- define "partials/sidebar/mobile-search" -}} | ||||||
|   {{ template "sidebar-tree" (dict "context" .context "level" 0 "page" .page "pageURL" .pageURL "toc" (.toc | default false)) }} |   <div class="px-4 pt-4 md:hidden"> | ||||||
| {{- end -}} |     {{- partialCached "search.html" . -}} | ||||||
|  |   </div> | ||||||
| {{- define "sidebar-tree" -}} |  | ||||||
|   {{- if ge .level 4 -}} |  | ||||||
|     {{- return -}} |  | ||||||
|   {{- end -}} |  | ||||||
|  |  | ||||||
|   {{- $context := .context -}} |  | ||||||
|   {{- $page := .page }} |  | ||||||
|   {{- $pageURL := .page.RelPermalink -}} |  | ||||||
|   {{- $level := .level -}} |  | ||||||
|   {{- $toc := .toc | default false -}} |  | ||||||
|  |  | ||||||
|   {{- with $items := union .context.RegularPages .context.Sections -}} |  | ||||||
|     {{- if eq $level 0 -}} |  | ||||||
|       {{- range $items.ByWeight }} |  | ||||||
|         {{- $active := eq $pageURL .RelPermalink -}} |  | ||||||
|         {{- $shouldOpen := or (.Params.sidebar.open) (.IsAncestor $page) $active | default true }} |  | ||||||
|         <li class="{{ if $shouldOpen }}open{{ end }}"> |  | ||||||
|           {{- template "sidebar-item-link" dict "context" . "active" $active "title" .LinkTitle "link" .RelPermalink -}} |  | ||||||
|           {{- if and $toc $active -}} |  | ||||||
|             {{- template "sidebar-toc" dict "page" . -}} |  | ||||||
|           {{- end -}} |  | ||||||
|           {{- template "sidebar-tree" dict "context" . "page" $page "pageURL" $pageURL "level" (add $level 1) "toc" $toc -}} |  | ||||||
|         </li> |  | ||||||
|       {{- end -}} |  | ||||||
|     {{- else -}} |  | ||||||
|       <div class="pt-1 ltr:pr-0 overflow-hidden transition-all ease-in-out duration-200"> |  | ||||||
|         <ul class='relative flex flex-col gap-1 before:absolute before:inset-y-1 before:w-px before:bg-gray-200 before:content-[""] ltr:ml-3 ltr:pl-3 ltr:before:left-0 rtl:mr-3 rtl:pr-3 rtl:before:right-0 dark:before:bg-neutral-800'> |  | ||||||
|           {{- range $items.ByWeight }} |  | ||||||
|             {{- $active := eq $pageURL .RelPermalink -}} |  | ||||||
|             {{- $shouldOpen := or (.Params.sidebar.open) (.IsAncestor $page) $active | default true }} |  | ||||||
|             {{- $title := .LinkTitle | default .File.BaseFileName -}} |  | ||||||
|             <li class="flex flex-col gap-1 {{ if $shouldOpen }}open{{ end }}"> |  | ||||||
|               {{- template "sidebar-item-link" dict "context" . "active" $active "title" $title "link" .RelPermalink -}} |  | ||||||
|               {{- if and $toc $active -}} |  | ||||||
|                 {{ template "sidebar-toc" dict "page" . }} |  | ||||||
|               {{- end }} |  | ||||||
|               {{ template "sidebar-tree" dict "context" . "page" $page "pageURL" $pageURL "level" (add $level 1) "toc" $toc }} |  | ||||||
|             </li> |  | ||||||
|           {{- end -}} |  | ||||||
|         </ul> |  | ||||||
|       </div> |  | ||||||
|     {{- end -}} |  | ||||||
|   {{- end }} |  | ||||||
| {{- end -}} |  | ||||||
|  |  | ||||||
| {{- define "sidebar-toc" -}} |  | ||||||
|   {{ $page := .page }} |  | ||||||
|   {{ with $page.Fragments.Headings }} |  | ||||||
|     <ul class='flex flex-col gap-1 relative before:absolute before:inset-y-1 before:w-px before:bg-gray-200 before:content-[""] dark:before:bg-neutral-800 ltr:pl-3 ltr:before:left-0 rtl:pr-3 rtl:before:right-0 ltr:ml-3 rtl:mr-3'> |  | ||||||
|       {{- range . }} |  | ||||||
|         {{- with .Headings }} |  | ||||||
|           {{- range . -}} |  | ||||||
|             <li> |  | ||||||
|               <a |  | ||||||
|                 href="#{{ anchorize .ID }}" |  | ||||||
|                 class="flex rounded px-2 py-1.5 text-sm transition-colors [word-break:break-word] cursor-pointer [-webkit-tap-highlight-color:transparent] [-webkit-touch-callout:none] contrast-more:border flex gap-2 before:opacity-25 before:content-['#'] text-gray-500 hover:bg-gray-100 hover:text-gray-900 dark:text-neutral-400 dark:hover:bg-primary-100/5 dark:hover:text-gray-50 contrast-more:text-gray-900 contrast-more:dark:text-gray-50 contrast-more:border-transparent contrast-more:hover:border-gray-900 contrast-more:dark:hover:border-gray-50" |  | ||||||
|               > |  | ||||||
|                 {{- .Title -}} |  | ||||||
|               </a> |  | ||||||
|             </li> |  | ||||||
|           {{ end -}} |  | ||||||
|         {{ end -}} |  | ||||||
|       {{ end -}} |  | ||||||
|     </ul> |  | ||||||
|   {{ end }} |  | ||||||
| {{- end -}} |  | ||||||
|  |  | ||||||
| {{- define "sidebar-footer" -}} |  | ||||||
|   {{- range site.Menus.sidebar -}} |  | ||||||
|     {{- $name := or (T .Identifier) .Name -}} |  | ||||||
|     {{ if eq .Params.type "separator" }} |  | ||||||
|       <li class="[word-break:break-word] mt-5 mb-2 px-2 py-1.5 text-sm font-semibold text-gray-900 first:mt-0 dark:text-gray-100"> |  | ||||||
|         <span class="cursor-default">{{ $name }}</span> |  | ||||||
|       </li> |  | ||||||
|     {{ else }} |  | ||||||
|       <li>{{ template "sidebar-item-link" dict "active" false "title" $name "link" (.URL | relLangURL) }}</li> |  | ||||||
|     {{ end }} |  | ||||||
|   {{- end -}} |  | ||||||
| {{- end -}} | {{- end -}} | ||||||
|  |  | ||||||
| {{- define "sidebar-item-link" -}} | {{- define "sidebar-item-link" -}} | ||||||
|   {{- $external := strings.HasPrefix .link "http" -}} |   {{- $external := strings.HasPrefix .link "http" -}} | ||||||
|   {{- $open := .open | default true -}} |  | ||||||
|   <a |   <a | ||||||
|     class="flex items-center justify-between gap-2 cursor-pointer rounded px-2 py-1.5 text-sm transition-colors [-webkit-tap-highlight-color:transparent] [-webkit-touch-callout:none] [word-break:break-word] |     class="flex items-center justify-between gap-2 cursor-pointer rounded px-2 py-1.5 text-sm transition-colors [-webkit-tap-highlight-color:transparent] [-webkit-touch-callout:none] [word-break:break-word] | ||||||
|     {{- if .active }} |     {{- if .active }} | ||||||
| @@ -144,21 +50,30 @@ | |||||||
|     href="{{ .link }}" |     href="{{ .link }}" | ||||||
|     {{ if $external }}target="_blank" rel="noreferer"{{ end }} |     {{ if $external }}target="_blank" rel="noreferer"{{ end }} | ||||||
|   > |   > | ||||||
|     {{- .title -}} |     {{- .title | htmlUnescape | safeHTML -}} | ||||||
|     {{- with .context }} |     {{- with .context }} | ||||||
|       {{- if or .RegularPages .Sections }} |       {{- if or .RegularPages .Sections .section }}{{ partialCached "sidebar/collapsible-button" . }}{{ end -}} | ||||||
|         <span class="hextra-sidebar-collapsible-button"> |  | ||||||
|           {{- template "sidebear-collapsible-button" -}} |  | ||||||
|         </span> |  | ||||||
|       {{- end }} |  | ||||||
|     {{ end -}} |     {{ end -}} | ||||||
|   </a> |   </a> | ||||||
| {{- end -}} | {{- end -}} | ||||||
|  |  | ||||||
| {{- define "sidebar-separator" -}} | {{- define "partials/sidebar/switches" -}} | ||||||
|   <div class="mt-4 border-t py-4 dark:border-neutral-800 contrast-more:border-neutral-400 dark:contrast-more:border-neutral-400" /> |   {{- $context := .context -}} | ||||||
| {{- end -}} |   {{- $disableSidebar := .disableSidebar -}} | ||||||
|  |   {{/* Hide theme switch when sidebar is disabled */}} | ||||||
|  |   {{ $switchesClass := cond $disableSidebar "md:hidden" "" -}} | ||||||
|  |   {{ $displayThemeToggle := (site.Params.theme.displayToggle | default true) -}} | ||||||
|  |  | ||||||
| {{- define "sidebear-collapsible-button" -}} |   {{ if or site.IsMultiLingual $displayThemeToggle }} | ||||||
|   <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-[18px] min-w-[18px] rounded-sm p-0.5 hover:bg-gray-800/5 dark:hover:bg-gray-100/5"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" class="origin-center transition-transform rtl:-rotate-180"></path></svg> |     <div class="{{ $switchesClass }} {{ with site.IsMultiLingual }}justify-end{{ end }} sticky bottom-0 bg-white dark:bg-dark mx-4 py-4 shadow-[0_-12px_16px_#fff] flex items-center gap-2 dark:border-neutral-800 dark:shadow-[0_-12px_16px_#111] contrast-more:border-neutral-400 contrast-more:shadow-none contrast-more:dark:shadow-none border-t" data-toggle-animation="show"> | ||||||
|  |       {{- with site.IsMultiLingual -}} | ||||||
|  |         {{- partial "language-switch" (dict "context" $context "grow" true) -}} | ||||||
|  |         {{- with $displayThemeToggle }}{{ partial "theme-toggle" (dict "hideLabel" true) }}{{ end -}} | ||||||
|  |       {{- else -}} | ||||||
|  |         {{- with $displayThemeToggle -}} | ||||||
|  |           <div class="flex grow flex-col">{{ partial "theme-toggle" }}</div> | ||||||
|  |         {{- end -}} | ||||||
|  |       {{- end -}} | ||||||
|  |     </div> | ||||||
|  |   {{- end -}} | ||||||
| {{- end -}} | {{- end -}} | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								layouts/partials/sidebar/collapsible-button.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								layouts/partials/sidebar/collapsible-button.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | <span class="hextra-sidebar-collapsible-button"> | ||||||
|  |   <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-[18px] min-w-[18px] rounded-sm p-0.5 hover:bg-gray-800/5 dark:hover:bg-gray-100/5"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" class="origin-center transition-transform rtl:-rotate-180"></path></svg> | ||||||
|  | </span> | ||||||
							
								
								
									
										10
									
								
								layouts/partials/sidebar/extra.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								layouts/partials/sidebar/extra.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | {{- range site.Menus.sidebar -}} | ||||||
|  |   {{- $name := or (T .Identifier) .Name -}} | ||||||
|  |   {{ if eq .Params.type "separator" }} | ||||||
|  |     <li class="[word-break:break-word] mt-5 mb-2 px-2 py-1.5 text-sm font-semibold text-gray-900 first:mt-0 dark:text-gray-100"> | ||||||
|  |       <span class="cursor-default">{{ $name }}</span> | ||||||
|  |     </li> | ||||||
|  |   {{ else }} | ||||||
|  |     <li>{{ template "sidebar-item-link" (dict "active" false "title" $name "link" (.URL | relLangURL)) }}</li> | ||||||
|  |   {{ end }} | ||||||
|  | {{- end -}} | ||||||
| @@ -0,0 +1,15 @@ | |||||||
|  | {{- $entry := . -}} | ||||||
|  |  | ||||||
|  | <div class="pt-1 ltr:pr-0 overflow-hidden transition-all ease-in-out duration-200"> | ||||||
|  |   <ul class='relative flex flex-col gap-1 before:absolute before:inset-y-1 before:w-px before:bg-gray-200 before:content-[""] ltr:ml-3 ltr:pl-3 ltr:before:left-0 rtl:mr-3 rtl:pr-3 rtl:before:right-0 dark:before:bg-neutral-800'> | ||||||
|  |     {{- range $entry }} | ||||||
|  |       {{- $shouldOpen := .open | default false }} | ||||||
|  |       <li class="flex flex-col gap-1 {{ if $shouldOpen }}open{{ end }}"> | ||||||
|  |         {{- template "sidebar-item-link" (dict "context" . "active" false "title" .title "link" .link) -}} | ||||||
|  |         {{- if .section -}} | ||||||
|  |           {{- partial "sidebar/render-tree-branch-without-leaf" .section -}} | ||||||
|  |         {{- end -}} | ||||||
|  |       </li> | ||||||
|  |     {{- end -}} | ||||||
|  |   </ul> | ||||||
|  | </div> | ||||||
							
								
								
									
										19
									
								
								layouts/partials/sidebar/render-tree-branch.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								layouts/partials/sidebar/render-tree-branch.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | {{- $context := .context -}} | ||||||
|  | {{- $page := .page -}} | ||||||
|  | {{- $entry := .entry -}} | ||||||
|  | {{- $pageLink := .page.RelPermalink -}} | ||||||
|  |  | ||||||
|  | <div class="pt-1 ltr:pr-0 overflow-hidden transition-all ease-in-out duration-200"> | ||||||
|  |   <ul class='relative flex flex-col gap-1 before:absolute before:inset-y-1 before:w-px before:bg-gray-200 before:content-[""] ltr:ml-3 ltr:pl-3 ltr:before:left-0 rtl:mr-3 rtl:pr-3 rtl:before:right-0 dark:before:bg-neutral-800'> | ||||||
|  |     {{- range $entry }} | ||||||
|  |       {{- $active := eq $pageLink .link -}} | ||||||
|  |       {{- $shouldOpen := or (.open) (hasPrefix $pageLink .link) $active | default true }} | ||||||
|  |       <li class="flex flex-col gap-1 {{ if $shouldOpen }}open{{ end }}"> | ||||||
|  |         {{- template "sidebar-item-link" (dict "context" . "active" $active "title" .title "link" .link) -}} | ||||||
|  |         {{- if .section -}} | ||||||
|  |           {{- partial "sidebar/render-tree-branch" (dict "context" $context "entry" .section "page" $page) -}} | ||||||
|  |         {{- end -}} | ||||||
|  |       </li> | ||||||
|  |     {{- end -}} | ||||||
|  |   </ul> | ||||||
|  | </div> | ||||||
							
								
								
									
										18
									
								
								layouts/partials/sidebar/render-tree.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								layouts/partials/sidebar/render-tree.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | {{- $context := .context -}} | ||||||
|  | {{- $page := .page -}} | ||||||
|  | {{- $pageLink := .page.RelPermalink -}} | ||||||
|  | {{- range .tree -}} | ||||||
|  |   {{- $active := eq $pageLink .link -}} | ||||||
|  |   {{- $containsPage := hasPrefix $pageLink .link -}} | ||||||
|  |   {{- $shouldOpen := or (.open) $containsPage $active | default false }} | ||||||
|  |   <li class="{{ if $shouldOpen }}open{{ end }}"> | ||||||
|  |     {{- template "sidebar-item-link" (dict "context" . "active" $active "title" .title "link" .link) -}} | ||||||
|  |     {{- if .section -}} | ||||||
|  |       {{- if not $containsPage -}} | ||||||
|  |         {{- partialCached "sidebar/render-tree-branch-without-leaf" .section .section -}} | ||||||
|  |       {{- else -}} | ||||||
|  |         {{- partial "sidebar/render-tree-branch" (dict "context" $context "entry" .section "page" $page) -}} | ||||||
|  |       {{- end -}} | ||||||
|  |     {{- end -}} | ||||||
|  |   </li> | ||||||
|  | {{ end }} | ||||||
							
								
								
									
										51
									
								
								layouts/partials/sidebar/section-tree.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								layouts/partials/sidebar/section-tree.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | |||||||
|  | {{ $context := . -}} | ||||||
|  |  | ||||||
|  | {{- $pages := union .RegularPages .Sections -}} | ||||||
|  | {{- $pages = where $pages "Params.sidebar.exclude" "!=" true -}} | ||||||
|  |  | ||||||
|  | {{- $data := slice -}} | ||||||
|  |  | ||||||
|  | {{- range $pages.ByWeight -}} | ||||||
|  |   {{ $structure := (partial "sidebar/section-walk" .) | unmarshal -}} | ||||||
|  |   {{ $data = $data | append $structure -}} | ||||||
|  | {{ end -}} | ||||||
|  |  | ||||||
|  | {{- define "partials/sidebar/section-walk" -}} | ||||||
|  |   {{- with . -}} | ||||||
|  |   { | ||||||
|  |     "title": "{{ .LinkTitle | default .File.BaseFileName }}", | ||||||
|  |     "link": "{{ .RelPermalink }}", | ||||||
|  |     "toc": {{ partial "sidebar/section-page-toc" . }}, | ||||||
|  |     "open": {{ .Params.sidebar.open | default false }} | ||||||
|  |     {{- if .IsSection }}, | ||||||
|  |     "section": [ | ||||||
|  |       {{ $pages := union .RegularPages .Sections -}} | ||||||
|  |       {{ $pages = where $pages "Params.sidebar.exclude" "!=" true -}} | ||||||
|  |       {{ range $index, $page := $pages.ByWeight -}} | ||||||
|  |         {{ partial "sidebar/section-walk" . }}{{ if not (ge $index (sub (len $pages) 1)) }},{{ end -}} | ||||||
|  |       {{ end -}} | ||||||
|  |     ] | ||||||
|  |     {{ end -}} | ||||||
|  |   } | ||||||
|  |   {{- end }} | ||||||
|  | {{- end -}} | ||||||
|  |  | ||||||
|  | {{- define "partials/sidebar/section-page-toc" -}} | ||||||
|  |   {{/* Get level 2 headings list used mainly for mobile navigation */}} | ||||||
|  |   [ | ||||||
|  |     {{- with .Fragments.Headings -}} | ||||||
|  |       {{/* Loop over level 1 headings */}} | ||||||
|  |       {{- range . }} | ||||||
|  |         {{- with .Headings }} | ||||||
|  |           {{ $headings := . }} | ||||||
|  |           {{- range $index, $heading := $headings }} | ||||||
|  |             {{ $heading.Title | jsonify (dict "noHTMLEscape" true) }} | ||||||
|  |             {{- if not (ge $index (sub (len $headings) 1)) }},{{ end -}} | ||||||
|  |           {{ end -}} | ||||||
|  |         {{- end -}} | ||||||
|  |       {{ end -}} | ||||||
|  |     {{- end -}} | ||||||
|  |   ] | ||||||
|  | {{- end -}} | ||||||
|  |  | ||||||
|  | {{ return ($data | jsonify (dict "noHTMLEscape" true)) }} | ||||||
							
								
								
									
										21
									
								
								layouts/partials/sidebar/toc.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								layouts/partials/sidebar/toc.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | {{ $page := . }} | ||||||
|  | {{ with $page.Fragments.Headings }} | ||||||
|  |   <ul | ||||||
|  |     class='flex flex-col gap-1 relative before:absolute before:inset-y-1 before:w-px before:bg-gray-200 before:content-[""] dark:before:bg-neutral-800 ltr:pl-3 ltr:before:left-0 rtl:pr-3 rtl:before:right-0 ltr:ml-3 rtl:mr-3' | ||||||
|  |   > | ||||||
|  |     {{- range . }} | ||||||
|  |       {{- with .Headings }} | ||||||
|  |         {{- range . -}} | ||||||
|  |           <li> | ||||||
|  |             <a | ||||||
|  |               href="#{{ anchorize .ID }}" | ||||||
|  |               class="flex rounded px-2 py-1.5 text-sm transition-colors [word-break:break-word] cursor-pointer [-webkit-tap-highlight-color:transparent] [-webkit-touch-callout:none] contrast-more:border gap-2 before:opacity-25 before:content-['#'] text-gray-500 hover:bg-gray-100 hover:text-gray-900 dark:text-neutral-400 dark:hover:bg-primary-100/5 dark:hover:text-gray-50 contrast-more:text-gray-900 contrast-more:dark:text-gray-50 contrast-more:border-transparent contrast-more:hover:border-gray-900 contrast-more:dark:hover:border-gray-50" | ||||||
|  |             > | ||||||
|  |               {{- .Title -}} | ||||||
|  |             </a> | ||||||
|  |           </li> | ||||||
|  |         {{ end -}} | ||||||
|  |       {{ end -}} | ||||||
|  |     {{ end -}} | ||||||
|  |   </ul> | ||||||
|  | {{ end }} | ||||||
							
								
								
									
										42
									
								
								layouts/partials/third-party/scripts.html
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								layouts/partials/third-party/scripts.html
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | |||||||
|  | {{/* Mermaid */}} | ||||||
|  | {{/* FIXME: need to investigate .Page.Store hasMermaid is set for homepage */}} | ||||||
|  | {{- if and (.Page.Store.Get "hasMermaid") (not .Page.IsHome) -}} | ||||||
|  |   {{- $mermaidJS := resources.Get "lib/mermaid/mermaid.min.js" | fingerprint -}} | ||||||
|  |   <script defer src="{{ $mermaidJS.RelPermalink }}" integrity="{{ $mermaidJS.Data.Integrity }}"></script> | ||||||
|  |   <script> | ||||||
|  |     document.addEventListener("DOMContentLoaded", function () { | ||||||
|  |       const theme = document.documentElement.classList.contains("dark") ? "dark" : "default"; | ||||||
|  |       mermaid.initialize({ startOnLoad: true, theme: theme }); | ||||||
|  |     }); | ||||||
|  |   </script> | ||||||
|  | {{- end -}} | ||||||
|  |  | ||||||
|  | {{/* KaTex */}} | ||||||
|  | {{- if .Page.Params.math -}} | ||||||
|  |   {{- $katexCSS := resources.Get "lib/katex/katex.min.css" | fingerprint -}} | ||||||
|  |   {{- $katexJS := resources.Get "lib/katex/katex.min.js" | fingerprint -}} | ||||||
|  |   {{- $mhchemJS := resources.Get "lib/katex/mhchem.min.js" | fingerprint -}} | ||||||
|  |   {{- $katexAutoRenderJS := resources.Get "lib/katex/auto-render.min.js" | fingerprint -}} | ||||||
|  |   <link type="text/css" rel="stylesheet" href="{{ $katexCSS.RelPermalink }}" integrity="{{ $katexCSS.Data.Integrity }}" /> | ||||||
|  |   <script defer src="{{ $katexJS.RelPermalink }}" integrity="{{ $katexJS.Data.Integrity }}"></script> | ||||||
|  |   <script defer src="{{ $katexAutoRenderJS.RelPermalink }}" integrity="{{ $katexAutoRenderJS.Data.Integrity }}"></script> | ||||||
|  |   <script defer src="{{ $mhchemJS.RelPermalink }}" integrity="{{ $mhchemJS.Data.Integrity }}"></script> | ||||||
|  |   {{ $katexFonts := resources.Match "lib/katex/fonts/*" }} | ||||||
|  |   {{- range $katexFonts -}} | ||||||
|  |     {{ .Publish }} | ||||||
|  |   {{- end -}} | ||||||
|  |   <script> | ||||||
|  |     // TODO: make render options configurable | ||||||
|  |     document.addEventListener("DOMContentLoaded", function () { | ||||||
|  |       renderMathInElement(document.body, { | ||||||
|  |         delimiters: [ | ||||||
|  |           { left: "$$", right: "$$", display: true }, | ||||||
|  |           { left: "$", right: "$", display: false }, | ||||||
|  |           { left: "\\(", right: "\\)", display: false }, | ||||||
|  |           { left: "\\[", right: "\\]", display: true }, | ||||||
|  |         ], | ||||||
|  |         throwOnError: false, | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  |   </script> | ||||||
|  | {{ end }} | ||||||
| @@ -3,6 +3,7 @@ | |||||||
| {{- $toc := .Params.toc | default true -}} | {{- $toc := .Params.toc | default true -}} | ||||||
| {{- $onThisPage := (T "onThisPage") | default "On this page"}} | {{- $onThisPage := (T "onThisPage") | default "On this page"}} | ||||||
| {{- $editThisPage := (T "editThisPage") | default "Edit this page"}} | {{- $editThisPage := (T "editThisPage") | default "Edit this page"}} | ||||||
|  | {{- $backToTop := (T "backToTop") | default "Scroll to top" -}} | ||||||
|  |  | ||||||
| <nav class="hextra-toc order-last hidden w-64 shrink-0 xl:block print:hidden px-4" aria-label="table of contents"> | <nav class="hextra-toc order-last hidden w-64 shrink-0 xl:block print:hidden px-4" aria-label="table of contents"> | ||||||
|   {{- if $toc }} |   {{- if $toc }} | ||||||
| @@ -25,10 +26,19 @@ | |||||||
|       <div class="{{ $borderClass }} sticky bottom-0 flex flex-col items-start gap-2 pb-8 dark:border-neutral-800 contrast-more:border-t contrast-more:border-neutral-400 contrast-more:shadow-none contrast-more:dark:border-neutral-400"> |       <div class="{{ $borderClass }} sticky bottom-0 flex flex-col items-start gap-2 pb-8 dark:border-neutral-800 contrast-more:border-t contrast-more:border-neutral-400 contrast-more:shadow-none contrast-more:dark:border-neutral-400"> | ||||||
|         {{- if site.Params.editURL.enable -}} |         {{- if site.Params.editURL.enable -}} | ||||||
|           {{- $editURL := site.Params.editURL.base | default "" -}} |           {{- $editURL := site.Params.editURL.base | default "" -}} | ||||||
|           {{- with .File -}}{{ $editURL = urls.JoinPath $editURL .Path }}{{- end -}} |           {{- with .File -}}{{ $editURL = urls.JoinPath $editURL (replace .Path "\\" "/") }}{{- end -}} | ||||||
|           {{- with .Params.editURL -}}{{ $editURL = .Params.editURL }}{{- end -}} |           {{- with .Params.editURL -}}{{ $editURL = .Params.editURL }}{{- end -}} | ||||||
|           <a class="text-xs font-medium text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100 contrast-more:text-gray-800 contrast-more:dark:text-gray-50" href="{{ $editURL }}" target="_blank" rel="noreferer">{{ $editThisPage }}</a> |           <a class="text-xs font-medium text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100 contrast-more:text-gray-800 contrast-more:dark:text-gray-50" href="{{ $editURL }}" target="_blank" rel="noreferer">{{ $editThisPage }}</a> | ||||||
|         {{- end -}} |         {{- end -}} | ||||||
|  |         {{/* Scroll To Top */}} | ||||||
|  |         <button aria-hidden="true" id="backToTop" onClick="scrollUp();" class="transition-all transition duration-75 opacity-0 text-xs font-medium text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100 contrast-more:text-gray-800 contrast-more:dark:text-gray-50"> | ||||||
|  |           <span> | ||||||
|  |             {{- $backToTop -}} | ||||||
|  |           </span> | ||||||
|  |           <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="inline ml-1 h-3.5 w-3.5 border rounded-full border-gray-500 hover:border-gray-900 dark:border-gray-400 dark:hover:border-gray-100 contrast-more:border-gray-800 contrast-more:dark:border-gray-50"> | ||||||
|  |             <path stroke-linecap="round" stroke-linejoin="round" d="M4.5 15.75l7.5-7.5 7.5 7.5" /> | ||||||
|  |           </svg> | ||||||
|  |         </button> | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|   {{ end -}} |   {{ end -}} | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| {{/* Split page raw content into fragments */}} | {{/* Split page raw content into fragments */}} | ||||||
| {{ $page := . }} | {{ $page := .context }} | ||||||
|  | {{ $type := .type | default "content" }} | ||||||
|  |  | ||||||
| {{ $headingKeys := slice }} | {{ $headingKeys := slice }} | ||||||
| {{ $headingTitles := slice }} | {{ $headingTitles := slice }} | ||||||
| @@ -22,24 +23,40 @@ | |||||||
| {{ $len := len $headingKeys }} | {{ $len := len $headingKeys }} | ||||||
| {{ $data := dict }} | {{ $data := dict }} | ||||||
|  |  | ||||||
| {{ if eq $len 0 }} | {{ if eq $type "content" }} | ||||||
|   {{ $data = $data | merge (dict "" $page.Plain) }} |   {{/* Include full content of the page */}} | ||||||
| {{ else }} |   {{ if eq $len 0 }} | ||||||
|   {{ range seq $len }} |     {{ $data = $data | merge (dict "" ($page.Plain | htmlUnescape | chomp)) }} | ||||||
|     {{ $i := sub $len . }} |   {{ else }} | ||||||
|     {{ $headingKey := index $headingKeys $i }} |     {{/* Split the raw content from bottom to top */}} | ||||||
|     {{ $headingTitle := index $headingTitles $i }} |     {{ range seq $len }} | ||||||
|  |       {{ $i := sub $len . }} | ||||||
|  |       {{ $headingKey := index $headingKeys $i }} | ||||||
|  |       {{ $headingTitle := index $headingTitles $i }} | ||||||
|  |  | ||||||
|     {{ if eq $i 0 }} |       {{ if eq $i 0 }} | ||||||
|       {{ $data = $data | merge (dict $headingKey ($content | markdownify | plainify)) }} |         {{ $data = $data | merge (dict $headingKey ($content | markdownify | plainify | htmlUnescape | chomp)) }} | ||||||
|     {{ else }} |       {{ else }} | ||||||
|       {{ $parts := split $content (printf "\n%s\n" $headingTitle) }} |         {{ $parts := split $content (printf "\n%s\n" $headingTitle) }} | ||||||
|       {{ $lastPart := index $parts (sub (len $parts) 1) }} |         {{ $lastPart := index $parts (sub (len $parts) 1) }} | ||||||
|  |  | ||||||
|       {{ $data = $data | merge (dict $headingKey ($lastPart | markdownify | plainify)) }} |         {{ $data = $data | merge (dict $headingKey ($lastPart | markdownify | plainify | htmlUnescape | chomp)) }} | ||||||
|       {{ $content = strings.TrimSuffix $lastPart $content }} |         {{ $content = strings.TrimSuffix $lastPart $content }} | ||||||
|       {{ $content = strings.TrimSuffix (printf "\n%s\n" $headingTitle) $content }} |         {{ $content = strings.TrimSuffix (printf "\n%s\n" $headingTitle) $content }} | ||||||
|  |       {{ end }} | ||||||
|     {{ end }} |     {{ end }} | ||||||
|   {{ end }} |   {{ end }} | ||||||
|  | {{ else if (eq $type "heading" ) }} | ||||||
|  |   {{/* Put heading keys with empty content to the data object */}} | ||||||
|  |   {{ $data = dict "" "" }} | ||||||
|  |   {{ range $headingKeys }} | ||||||
|  |     {{ $data = $data | merge (dict . "") }} | ||||||
|  |   {{ end }} | ||||||
|  | {{ else if (eq $type "title") }} | ||||||
|  |   {{/* Use empty data object since title is included in search-data.json */}} | ||||||
|  |   {{ $data = $data | merge (dict "" "") }} | ||||||
|  | {{ else if (eq $type "summary" ) }} | ||||||
|  |   {{ $data = $data | merge (dict "" ($page.Summary | plainify | htmlUnescape | chomp)) }} | ||||||
| {{ end }} | {{ end }} | ||||||
|  |  | ||||||
| {{ return $data }} | {{ return $data }} | ||||||
|   | |||||||
| @@ -17,8 +17,8 @@ | |||||||
| <div class="overflow-x-auto mt-6 flex rounded-lg border py-2 ltr:pr-4 rtl:pl-4 contrast-more:border-current contrast-more:dark:border-current {{ $class }}"> | <div class="overflow-x-auto mt-6 flex rounded-lg border py-2 ltr:pr-4 rtl:pl-4 contrast-more:border-current contrast-more:dark:border-current {{ $class }}"> | ||||||
|   <div class="select-none text-xl ltr:pl-3 ltr:pr-2 rtl:pr-3 rtl:pl-2" style='font-family: "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";'>{{ $emoji }}</div> |   <div class="select-none text-xl ltr:pl-3 ltr:pr-2 rtl:pr-3 rtl:pl-2" style='font-family: "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";'>{{ $emoji }}</div> | ||||||
|   <div class="w-full min-w-0 leading-7"> |   <div class="w-full min-w-0 leading-7"> | ||||||
|     <p class="mt-6 leading-7 first:mt-0"> |     <div class="mt-6 leading-7 first:mt-0"> | ||||||
|       {{ .Inner | markdownify }} |       {{ .Inner | markdownify }} | ||||||
|     </p> |     </div> | ||||||
|   </div> |   </div> | ||||||
| </div> | </div> | ||||||
|   | |||||||
| @@ -3,7 +3,8 @@ | |||||||
|     "dev:theme": "hugo server --logLevel=debug --config=hugo.yaml,../dev.toml --environment=theme --source=exampleSite --themesDir=../.. --disableFastRender -D --port 1313", |     "dev:theme": "hugo server --logLevel=debug --config=hugo.yaml,../dev.toml --environment=theme --source=exampleSite --themesDir=../.. --disableFastRender -D --port 1313", | ||||||
|     "dev": "hugo server --source=exampleSite --themesDir=../.. --disableFastRender -D --port 1313", |     "dev": "hugo server --source=exampleSite --themesDir=../.. --disableFastRender -D --port 1313", | ||||||
|     "build:css": "npx postcss --config postcss.config.js --env production assets/css/styles.css -o assets/css/compiled/main.css", |     "build:css": "npx postcss --config postcss.config.js --env production assets/css/styles.css -o assets/css/compiled/main.css", | ||||||
|     "build": "hugo --gc --minify --themesDir=../.. --source=exampleSite" |     "build": "hugo --gc --minify --themesDir=../.. --source=exampleSite", | ||||||
|  |     "metrics": "hugo --themesDir=../.. --source=exampleSite --templateMetrics --templateMetricsHints" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "@tailwindcss/nesting": "^0.0.0-insiders.565cd3e", |     "@tailwindcss/nesting": "^0.0.0-insiders.565cd3e", | ||||||
|   | |||||||
| @@ -3,10 +3,10 @@ const colors = require('tailwindcss/colors') | |||||||
| const makePrimaryColor = | const makePrimaryColor = | ||||||
|   l => |   l => | ||||||
|     ({ opacityValue }) => { |     ({ opacityValue }) => { | ||||||
|       if (opacityValue === undefined) { |       return ( | ||||||
|         return `hsl(var(--primary-hue) 100% ${l}%)` |         `hsl(var(--primary-hue) var(--primary-saturation) ${l}%` + | ||||||
|       } |         (opacityValue ? ` / ${opacityValue})` : ')') | ||||||
|       return `hsl(var(--primary-hue) 100% ${l}% / ${opacityValue})` |       ) | ||||||
|     } |     } | ||||||
|  |  | ||||||
| /** @type {import('tailwindcss').Config} */ | /** @type {import('tailwindcss').Config} */ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user