mirror of
				https://github.com/imfing/hextra.git
				synced 2025-10-31 16:24:51 -04:00 
			
		
		
		
	Compare commits
	
		
			25 Commits
		
	
	
		
			image-zoom
			...
			sidebar-da
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | f8e02e6151 | ||
|   | b01c8ee405 | ||
|   | 2acfb3b877 | ||
|   | 4d9015aefe | ||
|   | 783ab1e97f | ||
|   | 168ecf91f4 | ||
|   | 9e7b13a0da | ||
|   | 66489e5274 | ||
|   | 2004648076 | ||
|   | 0da6f97e99 | ||
|   | a4bfa2d97e | ||
|   | 3a2ce0b5c0 | ||
|   | 55af474f51 | ||
|   | b91cc79674 | ||
|   | 68e1e25119 | ||
|   | 8c789626be | ||
|   | a1c7acd6b5 | ||
|   | e444156bb9 | ||
|   | 33f2cf653b | ||
|   | 63f153999e | ||
|   | c62b1fd401 | ||
|   | fdfdef69b5 | ||
|   | 462cc5b68d | ||
|   | f40c7fd5d4 | ||
|   | 74fb165358 | 
| @@ -3,7 +3,7 @@ | ||||
|   "features": { | ||||
|     "ghcr.io/devcontainers/features/hugo:1": { | ||||
|       "extended": true, | ||||
|       "version": "0.147.7" | ||||
|       "version": "0.131.0" | ||||
|     }, | ||||
|     "ghcr.io/devcontainers/features/node:1": {} | ||||
|   }, | ||||
| @@ -18,7 +18,5 @@ | ||||
|     } | ||||
|   }, | ||||
|   "postCreateCommand": "npm install", | ||||
|   "forwardPorts": [ | ||||
|     1313 | ||||
|   ] | ||||
|   "forwardPorts": [1313] | ||||
| } | ||||
							
								
								
									
										6
									
								
								.github/CONTRIBUTING.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/CONTRIBUTING.md
									
									
									
									
										vendored
									
									
								
							| @@ -31,7 +31,7 @@ Use [Conventional Commits][conventional commits] message to make it easier to un | ||||
|  | ||||
| Similar to contributing code, you can also contribute to the documentation by submitting a pull request. | ||||
|  | ||||
| The documentation site is located in the [`docs`](../docs/) folder. | ||||
| The documentation site is located in the [`exampleSite`](../exampleSite/) folder. | ||||
| You can make changes to the documentation and create a pull request. A preview of the new documentation will be automatically generated and displayed in the pull request comment via [Netlify][netlify deploy preview]. | ||||
|  | ||||
| ### 💬 GitHub Discussions | ||||
| @@ -71,7 +71,7 @@ npm i | ||||
|  | ||||
| - [`assets`](../assets/): CSS styles and JavaScript files. | ||||
| - [`data`](../data/): The theme data files. Now only contains the `icons.yaml` file. | ||||
| - [`docs`](../docs/): The documentation site for the theme. | ||||
| - [`exampleSite`](../exampleSite/): The documentation site for the theme. | ||||
| - [`i18n`](../i18n/): The theme translation files. | ||||
| - [`layouts`](../layouts/): The theme layouts. | ||||
| - [`static`](../static/): The static files for the theme. For example, the favicon and the site logo. | ||||
| @@ -84,7 +84,7 @@ Please refer to the [Hugo documentation][hugo] for more information. | ||||
| npm run dev:theme | ||||
| ``` | ||||
|  | ||||
| It starts the Hugo server on `http://localhost:1313/` for the `docs` content. | ||||
| It will start the Hugo server on `http://localhost:1313/` for the `exampleSite` content. | ||||
|  | ||||
| ### Compile the styles | ||||
|  | ||||
|   | ||||
							
								
								
									
										28
									
								
								.github/workflows/pages.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								.github/workflows/pages.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| # Build and deploy Hextra docs site to GitHub Pages | ||||
| name: Deploy Hextra docs site to Pages | ||||
| # Sample workflow for building and deploying a Hugo site to GitHub Pages | ||||
| name: Deploy Hugo site to Pages | ||||
|  | ||||
| on: | ||||
|   # Runs on pushes targeting the default branch | ||||
| @@ -31,43 +31,39 @@ jobs: | ||||
|   build: | ||||
|     runs-on: ubuntu-latest | ||||
|     env: | ||||
|       HUGO_VERSION: 0.147.7 | ||||
|       HUGO_VERSION: 0.138.0 | ||||
|     steps: | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v4 | ||||
|         with: | ||||
|           fetch-depth: 0  # fetch all history for .GitInfo and .Lastmod | ||||
|           fetch-tags: true | ||||
|           submodules: recursive | ||||
|  | ||||
|       - name: Setup Go | ||||
|         uses: actions/setup-go@v5 | ||||
|         with: | ||||
|           go-version: "1.24" | ||||
|  | ||||
|           go-version: '1.23' | ||||
|       - name: Setup Pages | ||||
|         id: pages | ||||
|         uses: actions/configure-pages@v5 | ||||
|  | ||||
|       - name: Setup Hugo | ||||
|         run: | | ||||
|           wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \ | ||||
|           && sudo dpkg -i ${{ runner.temp }}/hugo.deb | ||||
|  | ||||
|       - name: Make build script executable | ||||
|         run: chmod +x ./build.sh | ||||
|  | ||||
|       - name: Build all site versions | ||||
|       - name: Build with Hugo | ||||
|         env: | ||||
|           # For maximum backward compatibility with Hugo modules | ||||
|           HUGO_ENVIRONMENT: production | ||||
|           HUGO_ENV: production | ||||
|         # Use the latest release of the theme to build exampleSite | ||||
|         run: | | ||||
|           ./build.sh "${{ steps.pages.outputs.base_url }}" | ||||
|  | ||||
|           cd exampleSite && rm go.mod | ||||
|           hugo mod init github.com/imfing/hextra/exampleSite | ||||
|           hugo mod get -u github.com/imfing/hextra | ||||
|           hugo --minify --baseURL "${{ steps.pages.outputs.base_url }}/" | ||||
|       - name: Upload artifact | ||||
|         uses: actions/upload-pages-artifact@v3 | ||||
|         with: | ||||
|           path: ./public | ||||
|           path: ./exampleSite/public | ||||
|  | ||||
|   # Deployment job | ||||
|   deploy: | ||||
|   | ||||
							
								
								
									
										161
									
								
								CLAUDE.md
									
									
									
									
									
								
							
							
						
						
									
										161
									
								
								CLAUDE.md
									
									
									
									
									
								
							| @@ -1,161 +0,0 @@ | ||||
| # CLAUDE.md | ||||
|  | ||||
| This file provides guidance to [Claude Code](claude.ai/code) when working with code in this repository. | ||||
|  | ||||
| ## Project Overview | ||||
|  | ||||
| Hextra is a modern, responsive Hugo theme designed for creating documentation websites, technical blogs, and static sites. Built with Tailwind CSS and inspired by Nextra, it offers features like full-text search, dark mode, multi-language support, and extensive customization options. | ||||
|  | ||||
| ## Development Commands | ||||
|  | ||||
| ### Development Server | ||||
|  | ||||
| ```bash | ||||
| # Start development server with theme reloading (recommended for theme development) | ||||
| npm run dev:theme | ||||
|  | ||||
| # Using Task runner | ||||
| task dev | ||||
| ``` | ||||
|  | ||||
| ### Building | ||||
|  | ||||
| ```bash | ||||
| # Build the example site | ||||
| npm run build | ||||
| # or | ||||
| task build | ||||
|  | ||||
| # Build CSS assets only | ||||
| npm run build:css | ||||
| # or | ||||
| task css | ||||
| ``` | ||||
|  | ||||
| ### Alternative Task Commands | ||||
|  | ||||
| The project uses Task runner (`taskfile.yaml`) for simplified commands: | ||||
|  | ||||
| - `task dev` - Start development server (runs `npm run dev:theme`) | ||||
| - `task build` - Build example site | ||||
| - `task css` - Compile CSS (depends on build) | ||||
|  | ||||
| ## Architecture Overview | ||||
|  | ||||
| ### Hugo Theme Structure | ||||
|  | ||||
| - **Base Layout**: `layouts/baseof.html` wraps all pages | ||||
| - **Specialized Layouts**: `layouts/docs/`, `layouts/blog/`, `layouts/hextra-home.html` | ||||
| - **Partials**: Reusable components in `layouts/_partials/` | ||||
|   - Core UI: `navbar.html`, `sidebar.html`, `footer.html`, `breadcrumb.html`, `toc.html` | ||||
|   - Utilities: `layouts/_partials/utils/` for helper functions | ||||
|   - Custom overrides: `layouts/_partials/custom/` for user customizations | ||||
| - **Shortcodes**: Custom Markdown extensions in `layouts/_shortcodes/` | ||||
| - **Render Hooks**: Custom Markdown rendering in `layouts/_markup/` for codeblocks, headings, images, and links | ||||
|  | ||||
| ### Asset Organization | ||||
|  | ||||
| ``` | ||||
| assets/ | ||||
| ├── css/ | ||||
| │   ├── styles.css              # Main stylesheet | ||||
| │   ├── compiled/main.css       # Built CSS output (generated) | ||||
| │   ├── components/             # Component-specific styles | ||||
| │   └── chroma/                 # Syntax highlighting themes | ||||
| ├── js/                         # JavaScript components | ||||
| └── lib/                        # External libraries | ||||
| ``` | ||||
|  | ||||
| ### Key Components | ||||
|  | ||||
| - **Search**: FlexSearch-powered full-text search (`assets/js/flexsearch.js`) | ||||
| - **Navigation**: Responsive navbar and auto-generated sidebar | ||||
| - **Theme Toggle**: Dark/light mode switching | ||||
| - **Internationalization**: 20+ language support in `i18n/` | ||||
|  | ||||
| ### Content Features | ||||
|  | ||||
| - **Shortcodes**: `callout`, `card`, `cards`, `tabs`, `details`, `steps`, `jupyter`, `filetree` | ||||
| - **Code Features**: Syntax highlighting (Chroma), copy buttons, line numbers via render hooks | ||||
| - **SEO**: Open Graph, Twitter Cards, structured data | ||||
| - **Performance**: Minimal JavaScript, optimized CSS with Tailwind | ||||
|  | ||||
| ## Development Workflow | ||||
|  | ||||
| ### Example Site Development | ||||
|  | ||||
| The `docs/` directory serves as both documentation and testing ground: | ||||
|  | ||||
| - Test new features here before releasing | ||||
| - Configuration examples in `docs/hugo.yaml` showing multi-language setup | ||||
| - Content examples demonstrate all theme capabilities | ||||
| - Run from docs with: `hugo server --themesDir=../..` | ||||
|  | ||||
| ### CSS Development Workflow | ||||
|  | ||||
| - Source: `assets/css/styles.css` (main stylesheet) | ||||
| - Build process: Tailwind CSS → PostCSS → `assets/css/compiled/main.css` | ||||
| - Component styles organized in `assets/css/components/` | ||||
| - Chroma syntax highlighting themes in `assets/css/chroma/` | ||||
| - CSS compilation requires Node.js dependencies (PostCSS, Tailwind CSS v4+) | ||||
|  | ||||
| ### Customization Points | ||||
|  | ||||
| - Custom partials: `layouts/_partials/custom/` | ||||
| - Custom CSS: `assets/css/custom.css` | ||||
| - Site-specific overrides: Copy any layout to your site's `layouts/` directory | ||||
|  | ||||
| ## Configuration & Requirements | ||||
|  | ||||
| ### Theme Requirements | ||||
|  | ||||
| - Hugo minimum version: 0.146.0 (extended version required - see `theme.toml`) | ||||
| - Go 1.20+ (as specified in `go.mod`) | ||||
| - Node.js for CSS compilation (PostCSS, Tailwind CSS v4+) | ||||
|  | ||||
| ### Key Configuration Files | ||||
|  | ||||
| - `docs/hugo.yaml` - Example Hugo configuration with multi-language setup | ||||
| - `postcss.config.mjs` - PostCSS configuration for CSS processing | ||||
| - `package.json` - Node.js dependencies and build scripts | ||||
| - `taskfile.yaml` - Task runner configuration | ||||
|  | ||||
| ### Development Environment | ||||
|  | ||||
| - Default Hugo development server: Port 1313 | ||||
| - Development server runs with `--disableFastRender -D` for better development experience | ||||
| - Theme development uses `--logLevel=debug` for detailed logging | ||||
|  | ||||
| ### Multi-language Support | ||||
|  | ||||
| - Configure languages in `hugo.yaml` (supports 20+ languages including RTL) | ||||
| - Translation files in `i18n/` directory (e.g., `en.yaml`, `fa.yaml`, `ja.yaml`, `zh-cn.yaml`) | ||||
| - Example supports English, Persian (RTL), Japanese, and Simplified Chinese | ||||
|  | ||||
| ## Theme Development Guidelines | ||||
|  | ||||
| ### Hugo Theme Conventions | ||||
|  | ||||
| - Theme files in this repository override Hugo defaults | ||||
| - Follow Hugo's theme development guidelines for compatibility | ||||
| - Maintain backward compatibility with existing configurations | ||||
|  | ||||
| ### JavaScript & Performance | ||||
|  | ||||
| - All JavaScript components are designed to have minimal footprint | ||||
| - Core JS components: `theme.js`, `search.js`, `nav-menu.js`, `code-copy.js` | ||||
| - FlexSearch powers offline full-text search functionality | ||||
|  | ||||
| ### CSS Architecture | ||||
|  | ||||
| - Uses Tailwind CSS v4+ with PostCSS processing | ||||
| - Component-based CSS organization in `assets/css/components/` | ||||
| - Compiled output goes to `assets/css/compiled/main.css` | ||||
| - Prettier formatting for Go templates and code consistency | ||||
|  | ||||
| ### Testing & Quality Assurance | ||||
|  | ||||
| - Test all changes in `docs/` before releasing | ||||
| - Use `npm run dev:theme` for theme development with hot reloading | ||||
| - Format code with `npx prettier --write .` before committing | ||||
| - Verify multi-language functionality across supported languages | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -1,3 +1,3 @@ | ||||
| .hextra-badge { | ||||
|   @apply hx:inline-flex hx:items-center; | ||||
|   @apply hx-inline-flex hx-items-center; | ||||
| } | ||||
| @@ -1,12 +0,0 @@ | ||||
| .hextra-banner-hidden .hextra-banner { | ||||
|   display: none; | ||||
| } | ||||
|  | ||||
| .hextra-banner { | ||||
|   :where(a):not(:where([class~=not-prose],[class~=not-prose] *)) { | ||||
|     @apply hx:underline hx:decoration-from-font; | ||||
|   } | ||||
|   :where(p):not(:where([class~=not-prose],[class~=not-prose] *)) { | ||||
|     @apply hx:leading-7 hx:first:mt-0; | ||||
|   } | ||||
| } | ||||
| @@ -10,11 +10,11 @@ | ||||
|   user-select: none; | ||||
| } | ||||
|  | ||||
| .hextra-card:hover .hextra-card-icon svg { | ||||
| .hextra-card:hover svg { | ||||
|   color: currentColor; | ||||
| } | ||||
|  | ||||
| .hextra-card .hextra-card-icon svg { | ||||
| .hextra-card svg { | ||||
|   width: 1.5rem; | ||||
|   color: #00000033; | ||||
|   transition: color 0.3s ease; | ||||
| @@ -25,22 +25,17 @@ | ||||
|   position: relative; | ||||
| } | ||||
|  | ||||
| .dark .hextra-card .hextra-card-icon svg { | ||||
| .dark .hextra-card svg { | ||||
|   color: #ffffff66; | ||||
| } | ||||
|  | ||||
| .dark .hextra-card:hover .hextra-card-icon svg { | ||||
| .dark .hextra-card:hover svg { | ||||
|   color: currentColor; | ||||
| } | ||||
|  | ||||
| .hextra-card-tag { | ||||
|   position: absolute; | ||||
|   z-index: 10; | ||||
|   top: 5px; | ||||
|   &:where(:dir(ltr)) { | ||||
|   right: 5px; | ||||
|   } | ||||
|   &:where(:dir(rtl)) { | ||||
|     left: 5px; | ||||
|   } | ||||
|   z-index: 10; | ||||
| } | ||||
|   | ||||
| @@ -2,6 +2,6 @@ | ||||
|   (-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px)) | ||||
| ) { | ||||
|   .hextra-code-copy-btn { | ||||
|     @apply hx:backdrop-blur-md hx:opacity-85 hx:dark:opacity-80; | ||||
|     @apply hx-backdrop-blur-md hx-bg-opacity-[.85] dark:hx-bg-opacity-80; | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,84 +0,0 @@ | ||||
| .hextra-zoom-image-overlay { | ||||
|   position: fixed; | ||||
|   inset: 0; | ||||
|   background: var(--hextra-image-zoom-backdrop, rgba(0, 0, 0, 0.9)); | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   justify-content: center; | ||||
|   z-index: 9999; | ||||
|   opacity: 0; | ||||
|   transition: opacity 260ms cubic-bezier(0.2, 0, 0, 1); | ||||
|   cursor: zoom-out; | ||||
|   overscroll-behavior: contain; | ||||
|   touch-action: none; | ||||
|   backdrop-filter: blur(var(--hextra-image-zoom-blur, 4px)); | ||||
|   -webkit-backdrop-filter: blur(var(--hextra-image-zoom-blur, 4px)); | ||||
|   /* Prevent iOS bounce */ | ||||
|   position: fixed; | ||||
|   overflow: hidden; | ||||
|   will-change: transform; | ||||
| } | ||||
|  | ||||
| .hextra-zoom-image-overlay.show { | ||||
|   opacity: 1; | ||||
| } | ||||
|  | ||||
| .hextra-zoom-image-overlay.closing { | ||||
|   opacity: 0; | ||||
|   transition: opacity 360ms cubic-bezier(0.2, 0, 0, 1); | ||||
| } | ||||
|  | ||||
| .hextra-zoom-image { | ||||
|   border-radius: 8px; | ||||
|   box-shadow: 0 18px 80px rgba(0, 0, 0, 0.5); | ||||
|   image-rendering: -webkit-optimize-contrast; | ||||
|   image-rendering: high-quality; | ||||
|   will-change: transform; | ||||
|   /* Prevent image selection on mobile */ | ||||
|   user-select: none; | ||||
|   -webkit-user-select: none; | ||||
|   -webkit-touch-callout: none; | ||||
|   /* Hardware acceleration */ | ||||
|   transform: translateZ(0); | ||||
|   -webkit-transform: translateZ(0); | ||||
| } | ||||
|  | ||||
| .hextra-zoom-image-overlay.show .hextra-zoom-image { | ||||
|   transition: | ||||
|     transform 320ms cubic-bezier(0.2, 0.8, 0.2, 1), | ||||
|     left 320ms cubic-bezier(0.2, 0.8, 0.2, 1), | ||||
|     top 320ms cubic-bezier(0.2, 0.8, 0.2, 1); | ||||
| } | ||||
|  | ||||
| .hextra-zoom-image-overlay.closing .hextra-zoom-image { | ||||
|   transition: | ||||
|     transform 340ms cubic-bezier(0.3, 0, 0.2, 1), | ||||
|     left 340ms cubic-bezier(0.3, 0, 0.2, 1), | ||||
|     top 340ms cubic-bezier(0.3, 0, 0.2, 1); | ||||
| } | ||||
|  | ||||
| /* Disable transitions during interaction */ | ||||
| .hextra-zoom-image-overlay.interacting .hextra-zoom-image { | ||||
|   transition: none !important; | ||||
| } | ||||
|  | ||||
| @media (prefers-reduced-motion: reduce) { | ||||
|   .hextra-zoom-image-overlay, | ||||
|   .hextra-zoom-image { | ||||
|     transition: none !important; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .content img:not([data-no-zoom]):not(.not-prose img) { | ||||
|   cursor: zoom-in; | ||||
| } | ||||
|  | ||||
| /* Loading indicator */ | ||||
| .hextra-zoom-image.loading { | ||||
|   opacity: 0; | ||||
| } | ||||
|  | ||||
| .hextra-zoom-image.loaded { | ||||
|   opacity: 1; | ||||
|   transition: opacity 200ms ease-in-out; | ||||
| } | ||||
| @@ -1,16 +1,16 @@ | ||||
| .hextra-jupyter-code-cell { | ||||
|   scrollbar-gutter: auto; | ||||
|  | ||||
|   @apply hx:mt-6; | ||||
|   @apply hx-mt-6; | ||||
|  | ||||
|   .hextra-jupyter-code-cell-outputs-container { | ||||
|     @apply hx:text-xs hx:overflow-hidden; | ||||
|     @apply hx-text-xs hx-overflow-hidden; | ||||
|  | ||||
|     .hextra-jupyter-code-cell-outputs { | ||||
|       @apply hx:overflow-auto hx:max-h-[50vh]; | ||||
|       @apply hx-overflow-auto hx-max-h-[50vh]; | ||||
|  | ||||
|       pre { | ||||
|         @apply hx:text-xs hx:overflow-auto hx:max-w-full; | ||||
|         @apply hx-text-xs hx-overflow-auto hx-max-w-full; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   | ||||
| @@ -1,50 +1,55 @@ | ||||
| nav { | ||||
|   .hextra-search-wrapper { | ||||
|     @apply hx:hidden hx:md:inline-block; | ||||
|   .search-wrapper { | ||||
|     @apply hx-hidden md:hx-inline-block; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @supports ( | ||||
|   (-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px)) | ||||
| ) { | ||||
|   .hextra-nav-container-blur { | ||||
|     @apply hx:backdrop-blur-md hx:bg-white/[.85] hx:dark:bg-dark/80!; | ||||
|   .nav-container-blur { | ||||
|     @apply hx-backdrop-blur-md hx-bg-white/[.85] dark:!hx-bg-dark/80; | ||||
|   } | ||||
| } | ||||
|  | ||||
| /* Hamburger Menu - Flattened Structure */ | ||||
| .hextra-hamburger-menu svg g { | ||||
|   @apply hx:origin-center hx:transition-all hx:duration-100 hx:ease-out; | ||||
| } | ||||
| .hamburger-menu svg { | ||||
|   g { | ||||
|     @apply hx-origin-center; | ||||
|     transition: transform 0.2s cubic-bezier(0.25, 1, 0.5, 1); | ||||
|   } | ||||
|   path { | ||||
|     opacity: 1; | ||||
|     transition: | ||||
|       transform 0.2s cubic-bezier(0.25, 1, 0.5, 1) 0.2s, | ||||
|       opacity 0.2s ease 0.2s; | ||||
|   } | ||||
|  | ||||
| .hextra-hamburger-menu svg path { | ||||
|   @apply hx:opacity-100 hx:transition-all hx:duration-100 hx:ease-out hx:delay-100; | ||||
| } | ||||
|   &.open { | ||||
|     path { | ||||
|       transition: | ||||
|         transform 0.2s cubic-bezier(0.25, 1, 0.5, 1), | ||||
|         opacity 0s ease 0.2s; | ||||
|     } | ||||
|     g { | ||||
|       transition: transform 0.2s cubic-bezier(0.25, 1, 0.5, 1) 0.2s; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| .hextra-hamburger-menu svg.open path { | ||||
|   @apply hx:transition-transform hx:duration-100 hx:ease-out hx:delay-0; | ||||
| } | ||||
|  | ||||
| .hextra-hamburger-menu svg.open g { | ||||
|   @apply hx:transition-transform hx:duration-100 hx:ease-out hx:delay-100; | ||||
| } | ||||
|  | ||||
| .hextra-hamburger-menu svg.open > path { | ||||
|   @apply hx:opacity-0; | ||||
| } | ||||
|  | ||||
| .hextra-hamburger-menu svg.open > g:nth-of-type(1) { | ||||
|   @apply hx:rotate-45; | ||||
| } | ||||
|  | ||||
| .hextra-hamburger-menu svg.open > g:nth-of-type(1) path { | ||||
|   @apply hx:translate-y-1; | ||||
| } | ||||
|  | ||||
| .hextra-hamburger-menu svg.open > g:nth-of-type(2) { | ||||
|   @apply hx:-rotate-45; | ||||
| } | ||||
|  | ||||
| .hextra-hamburger-menu svg.open > g:nth-of-type(2) path { | ||||
|   @apply hx:-translate-y-1; | ||||
|   &.open > { | ||||
|     path { | ||||
|       @apply hx-opacity-0; | ||||
|     } | ||||
|     g:nth-of-type(1) { | ||||
|       @apply hx-rotate-45; | ||||
|       path { | ||||
|         transform: translate3d(0, 4px, 0); | ||||
|       } | ||||
|     } | ||||
|     g:nth-of-type(2) { | ||||
|       @apply -hx-rotate-45; | ||||
|       path { | ||||
|         transform: translate3d(0, -4px, 0); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -4,18 +4,18 @@ | ||||
|  | ||||
|   scrollbar-gutter: stable; | ||||
|   &::-webkit-scrollbar { | ||||
|     @apply hx:w-3 hx:h-3; | ||||
|     @apply hx-w-3 hx-h-3; | ||||
|   } | ||||
|   &::-webkit-scrollbar-track { | ||||
|     @apply hx:bg-transparent; | ||||
|     @apply hx-bg-transparent; | ||||
|   } | ||||
|   &::-webkit-scrollbar-thumb { | ||||
|     @apply hx:rounded-[10px]; | ||||
|     @apply hx-rounded-[10px]; | ||||
|   } | ||||
|   &:hover::-webkit-scrollbar-thumb { | ||||
|     border: 3px solid transparent; | ||||
|     background-color: var(--tw-shadow-color); | ||||
|     background-clip: content-box; | ||||
|     @apply hx:shadow-neutral-500/20 hx:hover:shadow-neutral-500/40; | ||||
|     @apply hx-shadow-neutral-500/20 hover:hx-shadow-neutral-500/40; | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,38 +1,38 @@ | ||||
| .hextra-search-wrapper { | ||||
| .search-wrapper { | ||||
|   li { | ||||
|     @apply hx:mx-2.5 hx:break-words hx:rounded-md hx:contrast-more:border hx:text-gray-800 hx:contrast-more:border-transparent hx:dark:text-gray-300; | ||||
|     @apply hx-mx-2.5 hx-break-words hx-rounded-md contrast-more:hx-border hx-text-gray-800 contrast-more:hx-border-transparent dark:hx-text-gray-300; | ||||
|     a { | ||||
|       @apply hx:focus-visible:outline-none hx:focus:outline-none hx:block hx:scroll-m-12 hx:px-2.5 hx:py-2; | ||||
|       @apply hx-block hx-scroll-m-12 hx-px-2.5 hx-py-2; | ||||
|     } | ||||
|  | ||||
|     .hextra-search-title { | ||||
|       @apply hx:text-base hx:font-semibold hx:leading-5; | ||||
|     .title { | ||||
|       @apply hx-text-base hx-font-semibold hx-leading-5; | ||||
|     } | ||||
|  | ||||
|     .hextra-search-active { | ||||
|       @apply hx:rounded-md hx:bg-primary-500/10 hx:contrast-more:border-primary-500; | ||||
|     .active { | ||||
|       @apply hx-rounded-md hx-bg-primary-500/10 contrast-more:hx-border-primary-500; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .hextra-search-no-result { | ||||
|     @apply hx:block hx:select-none hx:p-8 hx:text-center hx:text-sm hx:text-gray-400; | ||||
|   .no-result { | ||||
|     @apply hx-block hx-select-none hx-p-8 hx-text-center hx-text-sm hx-text-gray-400; | ||||
|   } | ||||
|  | ||||
|   .hextra-search-prefix { | ||||
|     @apply hx:mx-2.5 hx:mb-2 hx:mt-6 hx:select-none hx:border-b hx:border-black/10 hx:px-2.5 hx:pb-1.5 hx:text-xs hx:font-semibold | ||||
|     hx:uppercase hx:text-gray-500 hx:first:mt-0 hx:dark:border-white/20 hx:dark:text-gray-300 hx:contrast-more:border-gray-600 | ||||
|     hx:contrast-more:text-gray-900 hx:contrast-more:dark:border-gray-50 hx:contrast-more:dark:text-gray-50; | ||||
|   .prefix { | ||||
|     @apply hx-mx-2.5 hx-mb-2 hx-mt-6 hx-select-none hx-border-b hx-border-black/10 hx-px-2.5 hx-pb-1.5 hx-text-xs hx-font-semibold | ||||
|     hx-uppercase hx-text-gray-500 first:hx-mt-0 dark:hx-border-white/20 dark:hx-text-gray-300 contrast-more:hx-border-gray-600 | ||||
|     contrast-more:hx-text-gray-900 contrast-more:dark:hx-border-gray-50 contrast-more:dark:hx-text-gray-50; | ||||
|   } | ||||
|  | ||||
|   .hextra-search-excerpt { | ||||
|     @apply hx:overflow-hidden hx:text-ellipsis hx:mt-1 hx:text-sm hx:leading-[1.35rem] hx:text-gray-600 hx:dark:text-gray-400 hx:contrast-more:dark:text-gray-50; | ||||
|   .excerpt { | ||||
|     @apply hx-overflow-hidden hx-text-ellipsis hx-mt-1 hx-text-sm hx-leading-[1.35rem] hx-text-gray-600 dark:hx-text-gray-400 contrast-more:dark:hx-text-gray-50; | ||||
|     display: -webkit-box; | ||||
|     line-clamp: 1; | ||||
|     -webkit-line-clamp: 1; | ||||
|     -webkit-box-orient: vertical; | ||||
|   } | ||||
|  | ||||
|   .hextra-search-match { | ||||
|     @apply hx:text-primary-600; | ||||
|   .match { | ||||
|     @apply hx-text-primary-600; | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| @media (max-width: 48rem) { | ||||
| @media (max-width: 767px) { | ||||
|   .hextra-sidebar-container { | ||||
|     @apply hx:fixed hx:pt-[calc(var(--navbar-height)+var(--hextra-banner-height))] hx:top-0 hx:w-full hx:bottom-0 hx:z-[15] hx:overscroll-contain hx:bg-white hx:dark:bg-dark; | ||||
|     transition: transform 0.4s cubic-bezier(0.52, 0.16, 0.04, 1); | ||||
|     @apply hx-fixed hx-pt-[calc(var(--navbar-height))] hx-top-0 hx-w-full hx-bottom-0 hx-z-[15] hx-overscroll-contain hx-bg-white dark:hx-bg-dark; | ||||
|     transition: transform 0.8s cubic-bezier(0.52, 0.16, 0.04, 1); | ||||
|     will-change: transform, opacity; | ||||
|     contain: layout style; | ||||
|     backface-visibility: hidden; | ||||
| @@ -10,12 +10,27 @@ | ||||
|  | ||||
| .hextra-sidebar-container { | ||||
|   li > div { | ||||
|     @apply hx:h-0; | ||||
|     @apply hx-h-0; | ||||
|   } | ||||
|   li.open > div { | ||||
|     @apply hx:h-auto hx:pt-1; | ||||
|     @apply hx-h-auto hx-pt-1; | ||||
|   } | ||||
|   li.open > a > span > svg > path { | ||||
|     @apply hx:rotate-90; | ||||
|     @apply hx-rotate-90; | ||||
|   } | ||||
|  | ||||
|   .hextra-sidebar-item-list { | ||||
|     @apply hx-relative hx-flex hx-flex-col hx-gap-1 before:hx-absolute before:hx-inset-y-1 before:hx-w-px before:hx-bg-gray-200 ltr:hx-ml-3 ltr:hx-pl-3 ltr:before:hx-left-0 rtl:hx-mr-3 rtl:hx-pr-3 rtl:before:hx-right-0 dark:before:hx-bg-neutral-800; | ||||
|   } | ||||
|  | ||||
|   .hextra-sidebar-item-link { | ||||
|     @apply hx-flex hx-items-center hx-justify-between hx-gap-2 hx-cursor-pointer hx-rounded hx-px-2 hx-py-1.5 hx-text-sm hx-transition-colors; | ||||
|  | ||||
|     &.active { | ||||
|       @apply hx-bg-primary-100 hx-font-semibold hx-text-primary-800 contrast-more:hx-border contrast-more:hx-border-primary-500 dark:hx-bg-primary-400/10 dark:hx-text-primary-600 contrast-more:dark:hx-border-primary-500; | ||||
|     } | ||||
|     &.inactive { | ||||
|       @apply hx-text-gray-500 hover:hx-bg-gray-100 hover:hx-text-gray-900 contrast-more:hx-border contrast-more:hx-border-transparent contrast-more:hx-text-gray-900 contrast-more:hover:hx-border-gray-900 dark:hx-text-neutral-400 dark:hover:hx-bg-primary-100/5 dark:hover:hx-text-gray-50 contrast-more:dark:hx-text-gray-50 contrast-more:dark:hover:hx-border-gray-50; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,22 +1,17 @@ | ||||
| .hextra-steps { | ||||
|   :where(h2, h3, h4, h5, h6):not(.no-step-marker) { | ||||
| .steps h3 { | ||||
|   counter-increment: step; | ||||
|     @apply hx:ltr:before:ml-[-41px] hx:rtl:before:mr-[-44px]; | ||||
|     /* https://github.com/tailwindlabs/tailwindcss/issues/15597#issuecomment-2582673546 */ | ||||
|     @apply hx:before:bg-gray-100 hx:dark:before:bg-neutral-800; | ||||
|     @apply hx:before:border-4 hx:before:border-white hx:dark:before:border-dark; | ||||
|  | ||||
|   &:before { | ||||
|     @apply hx-absolute hx-w-[33px] hx-h-[33px]; | ||||
|     @apply hx-border-4 hx-border-white hx-bg-gray-100 dark:hx-border-dark dark:hx-bg-neutral-800; | ||||
|     @apply hx-rounded-full hx-text-neutral-400 hx-text-base hx-font-normal hx-text-center -hx-indent-px; | ||||
|     @apply hx-mt-[3px] ltr:hx-ml-[-41px] rtl:hx-mr-[-44px]; | ||||
|     content: counter(step); | ||||
|       @apply hx:absolute hx:size-[33px]; | ||||
|       @apply hx:rounded-full hx:text-neutral-400 hx:text-base hx:font-normal hx:text-center hx:-indent-px; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| :lang(fa) .hextra-steps { | ||||
|   :where(h2, h3, h4, h5, h6):not(.no-step-marker) { | ||||
| :lang(fa) .steps h3 { | ||||
|   &:before { | ||||
|     content: counter(step, persian); | ||||
|   } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,4 +0,0 @@ | ||||
| /* Table of Contents Scroll Spy Styles */ | ||||
| .hextra-toc a.hextra-toc-active { | ||||
|   @apply hx:text-gray-900! hx:dark:text-gray-50! hx:transition-all hx:duration-200; | ||||
| } | ||||
| @@ -1,53 +1,53 @@ | ||||
| /* Code syntax highlight */ | ||||
| @import "./chroma/light.css"; | ||||
| @import "./chroma/dark.css"; | ||||
| @import "chroma/light.css"; | ||||
| @import "chroma/dark.css"; | ||||
|  | ||||
| .hextra-code-block { | ||||
|   @apply hx:text-[.9em] hx:leading-5; | ||||
|   @apply hx-text-[.9em] hx-leading-5; | ||||
|  | ||||
|   pre { | ||||
|     @apply hx:text-[.9em] hx:bg-primary-700/5 hx:overflow-x-auto hx:font-medium hx:subpixel-antialiased hx:dark:bg-primary-300/10 hx:contrast-more:border hx:contrast-more:border-primary-900/20 hx:contrast-more:contrast-150 hx:contrast-more:dark:border-primary-100/40; | ||||
|     @apply hx-text-[.9em] hx-bg-primary-700/5 hx-overflow-x-auto hx-font-medium hx-subpixel-antialiased dark:hx-bg-primary-300/10 contrast-more:hx-border contrast-more:hx-border-primary-900/20 contrast-more:hx-contrast-150 contrast-more:dark:hx-border-primary-100/40; | ||||
|   } | ||||
|  | ||||
|   .hextra-code-filename { | ||||
|     @apply hx:absolute hx:top-0 hx:z-[1] hx:w-full hx:truncate hx:rounded-t-xl hx:bg-primary-700/5 hx:py-2 hx:px-4 hx:text-xs hx:text-gray-700 hx:dark:bg-primary-300/10 hx:dark:text-gray-200; | ||||
|   .filename { | ||||
|     @apply hx-absolute hx-top-0 hx-z-[1] hx-w-full hx-truncate hx-rounded-t-xl hx-bg-primary-700/5 hx-py-2 hx-px-4 hx-text-xs hx-text-gray-700 dark:hx-bg-primary-300/10 dark:hx-text-gray-200; | ||||
|   } | ||||
|  | ||||
|   .hextra-code-filename + pre:not(.lntable pre) { | ||||
|   .filename + pre:not(.lntable pre) { | ||||
|     /* Override padding for code blocks with filename but no highlight */ | ||||
|     @apply hx:pt-12; | ||||
|     @apply hx-pt-12; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .hextra-code-block pre:not(.lntable pre) { | ||||
|   @apply hx:px-4 hx:mb-4 hx:py-4 hx:rounded-xl; | ||||
|   @apply hx-px-4 hx-mb-4 hx-py-4 hx-rounded-xl; | ||||
| } | ||||
|  | ||||
| .hextra-code-block div:nth-of-type(2) pre { | ||||
|   @apply hx:pt-12 hx:pb-4; | ||||
|   @apply hx-pt-12 hx-pb-4; | ||||
| } | ||||
|  | ||||
| .chroma { | ||||
|   .lntable { | ||||
|     @apply hx:m-0 hx:block hx:w-auto hx:overflow-auto hx:rounded-xl; | ||||
|     @apply hx-m-0 hx-block hx-w-auto hx-overflow-auto hx-rounded-xl; | ||||
|  | ||||
|     pre { | ||||
|       @apply hx:pt-4 hx:pb-4; | ||||
|       @apply hx-pt-4 hx-pb-4; | ||||
|     } | ||||
|   } | ||||
|   .ln, | ||||
|   .lnt:not(.hl > .lnt), | ||||
|   .hl:not(.line) { | ||||
|     @apply hx:pl-4 hx:pr-4 hx:min-w-[2.6rem] hx:text-neutral-600 hx:dark:text-neutral-300; | ||||
|     @apply hx-pl-4 hx-pr-4 hx-min-w-[2.6rem] hx-text-neutral-600 dark:hx-text-neutral-300; | ||||
|   } | ||||
|   .lntd { | ||||
|     @apply hx:p-0 hx:align-top; | ||||
|     @apply hx-p-0 hx-align-top; | ||||
|   } | ||||
|   .lntd:last-of-type { | ||||
|     @apply hx:w-full; | ||||
|     @apply hx-w-full; | ||||
|   } | ||||
|   /* LineHighlight */ | ||||
|   .hl { | ||||
|     @apply hx:block hx:w-full hx:bg-primary-800/10; | ||||
|     @apply hx-block hx-w-full hx-bg-primary-800/10; | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1 +0,0 @@ | ||||
| hx:max-w-full | ||||
| @@ -1,27 +1,26 @@ | ||||
| @import "tailwindcss" prefix(hx); | ||||
| @import "tailwind.css"; | ||||
|  | ||||
| @custom-variant dark (&:where(.dark, .dark *)); | ||||
|  | ||||
| @theme { | ||||
|   --color-primary-50: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 47)); | ||||
|   --color-primary-100: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 44)); | ||||
|   --color-primary-200: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 36)); | ||||
|   --color-primary-300: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 27)); | ||||
|   --color-primary-400: hsl(var(--primary-hue) var(--primary-saturation) calc(var(--primary-lightness) + calc(calc(100% - var(--primary-lightness)) / 50) * 16)); | ||||
|   --color-primary-500: hsl(var(--primary-hue) var(--primary-saturation) var(--primary-lightness)); | ||||
|   --color-primary-600: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 45)); | ||||
|   --color-primary-700: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 39)); | ||||
|   --color-primary-800: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 32)); | ||||
|   --color-primary-900: hsl(var(--primary-hue) var(--primary-saturation) calc(calc(var(--primary-lightness) / 50) * 24)); | ||||
|   --color-dark: #111; | ||||
| } | ||||
| @import "typography.css"; | ||||
| @import "highlight.css"; | ||||
| @import "components/cards.css"; | ||||
| @import "components/steps.css"; | ||||
| @import "components/search.css"; | ||||
| @import "components/sidebar.css"; | ||||
| @import "components/navbar.css"; | ||||
| @import "components/scrollbar.css"; | ||||
| @import "components/code-copy.css"; | ||||
| @import "components/hextra/feature-grid.css"; | ||||
| @import "components/jupyter.css"; | ||||
| @import "components/badge.css"; | ||||
|  | ||||
| html { | ||||
|   @apply hx:text-base hx:antialiased; | ||||
|   @apply hx-text-base hx-antialiased; | ||||
|   font-feature-settings: "rlig" 1, "calt" 1, "ss01" 1; | ||||
|   -webkit-tap-highlight-color: transparent; | ||||
| } | ||||
|  | ||||
| body { | ||||
|   @apply hx:w-full hx:bg-white hx:dark:bg-dark hx:dark:text-gray-100; | ||||
|   @apply hx-w-full hx-bg-white dark:hx-bg-dark dark:hx-text-gray-100; | ||||
| } | ||||
|  | ||||
| :root { | ||||
| @@ -29,8 +28,7 @@ body { | ||||
|   --primary-saturation: 100%; | ||||
|   --primary-lightness: 50%; | ||||
|   --navbar-height: 4rem; | ||||
|   --hextra-banner-height: 2rem; | ||||
|   --menu-height: 3.75rem; /* 60px */ | ||||
|   --menu-height: 3.75rem; | ||||
| } | ||||
|  | ||||
| .dark { | ||||
| @@ -38,22 +36,3 @@ body { | ||||
|   --primary-saturation: 100%; | ||||
|   --primary-lightness: 50%; | ||||
| } | ||||
|  | ||||
| @utility hextra-focus { | ||||
|   @apply hx:outline-none hx:ring-2 hx:ring-primary-200 hx:ring-offset-1 hx:ring-offset-primary-300 hx:dark:ring-primary-800 hx:dark:ring-offset-primary-700; | ||||
| } | ||||
|  | ||||
| @import "./typography.css"; | ||||
| @import "./highlight.css"; | ||||
| @import "./components/cards.css"; | ||||
| @import "./components/steps.css"; | ||||
| @import "./components/search.css"; | ||||
| @import "./components/sidebar.css"; | ||||
| @import "./components/banner.css"; | ||||
| @import "./components/navbar.css"; | ||||
| @import "./components/scrollbar.css"; | ||||
| @import "./components/code-copy.css"; | ||||
| @import "./components/hextra/feature-grid.css"; | ||||
| @import "./components/jupyter.css"; | ||||
| @import "./components/badge.css"; | ||||
| @import "./components/toc.css"; | ||||
|   | ||||
							
								
								
									
										3
									
								
								assets/css/tailwind.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/css/tailwind.css
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| @tailwind base; | ||||
| @tailwind components; | ||||
| @tailwind utilities; | ||||
| @@ -1,140 +1,126 @@ | ||||
| .content { | ||||
|   :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)) { | ||||
|     @apply hx:mt-2 hx:text-4xl hx:font-bold hx:tracking-tight hx:text-slate-900 hx:dark:text-slate-100; | ||||
|     @apply hx-mt-2 hx-text-4xl hx-font-bold hx-tracking-tight hx-text-slate-900 dark:hx-text-slate-100; | ||||
|   } | ||||
|   :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)) { | ||||
|     @apply hx:font-semibold hx:tracking-tight hx:text-slate-900 hx:dark:text-slate-100 hx:mt-10 hx:border-b hx:pb-1 hx:text-3xl hx:border-neutral-200/70 hx:contrast-more:border-neutral-400 hx:dark:border-primary-100/10 hx:contrast-more:dark:border-neutral-400; | ||||
|     @apply hx-font-semibold hx-tracking-tight hx-text-slate-900 dark:hx-text-slate-100 hx-mt-10 hx-border-b hx-pb-1 hx-text-3xl hx-border-neutral-200/70 contrast-more:hx-border-neutral-400 dark:hx-border-primary-100/10 contrast-more:dark:hx-border-neutral-400; | ||||
|   } | ||||
|   :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)) { | ||||
|     @apply hx:font-semibold hx:tracking-tight hx:text-slate-900 hx:dark:text-slate-100 hx:mt-8 hx:text-2xl; | ||||
|     @apply hx-font-semibold hx-tracking-tight hx-text-slate-900 dark:hx-text-slate-100 hx-mt-8 hx-text-2xl; | ||||
|   } | ||||
|   :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)) { | ||||
|     @apply hx:font-semibold hx:tracking-tight hx:text-slate-900 hx:dark:text-slate-100 hx:mt-8 hx:text-xl; | ||||
|     @apply hx-font-semibold hx-tracking-tight hx-text-slate-900 dark:hx-text-slate-100 hx-mt-8 hx-text-xl; | ||||
|   } | ||||
|   :where(h5):not(:where([class~=not-prose],[class~=not-prose] *)) { | ||||
|     @apply hx:font-semibold hx:tracking-tight hx:text-slate-900 hx:dark:text-slate-100 hx:mt-8 hx:text-lg; | ||||
|     @apply hx-font-semibold hx-tracking-tight hx-text-slate-900 dark:hx-text-slate-100 hx-mt-8 hx-text-lg; | ||||
|   } | ||||
|   :where(h6):not(:where([class~=not-prose],[class~=not-prose] *)) { | ||||
|     @apply hx:font-semibold hx:tracking-tight hx:text-slate-900 hx:dark:text-slate-100 hx:mt-8 hx:text-base; | ||||
|     @apply hx-font-semibold hx-tracking-tight hx-text-slate-900 dark:hx-text-slate-100 hx-mt-8 hx-text-base; | ||||
|   } | ||||
|   :where(p):not(:where([class~=not-prose],[class~=not-prose] *)) { | ||||
|     @apply hx:mt-6 hx:leading-7 hx:first:mt-0; | ||||
|     @apply hx-mt-6 hx-leading-7 first:hx-mt-0; | ||||
|   } | ||||
|   :where(a):not(:where([class~=not-prose],[class~=not-prose] *)) { | ||||
|     @apply hx:text-primary-600 hx:underline hx:decoration-from-font; | ||||
|     @apply hx-text-primary-600 hx-underline hx-decoration-from-font [text-underline-position:from-font]; | ||||
|   } | ||||
|   :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)) { | ||||
|     @apply hx:mt-6 hx:border-gray-300 hx:italic hx:text-gray-700 hx:dark:border-gray-700 hx:dark:text-gray-400 hx:first:mt-0 hx:ltr:border-l-2 hx:ltr:pl-6 hx:rtl:border-r-2 hx:rtl:pr-6; | ||||
|     @apply hx-mt-6 hx-border-gray-300 hx-italic hx-text-gray-700 dark:hx-border-gray-700 dark:hx-text-gray-400 first:hx-mt-0 ltr:hx-border-l-2 ltr:hx-pl-6 rtl:hx-border-r-2 rtl:hx-pr-6; | ||||
|   } | ||||
|   :where(pre):not(:where(.hextra-code-block pre, [class~=not-prose],[class~=not-prose] *)) { | ||||
|     @apply hx:bg-primary-700/5 hx:mb-4 hx:overflow-x-auto hx:rounded-xl hx:font-medium hx:subpixel-antialiased hx:dark:bg-primary-300/10 hx:text-[.9em] hx:contrast-more:border hx:contrast-more:border-primary-900/20 hx:contrast-more:contrast-150 hx:contrast-more:dark:border-primary-100/40 hx:py-4; | ||||
|     @apply hx-bg-primary-700/5 hx-mb-4 hx-overflow-x-auto hx-rounded-xl hx-font-medium hx-subpixel-antialiased dark:hx-bg-primary-300/10 hx-text-[.9em] contrast-more:hx-border contrast-more:hx-border-primary-900/20 contrast-more:hx-contrast-150 contrast-more:dark:hx-border-primary-100/40 hx-py-4; | ||||
|   } | ||||
|   :where(code):not(:where(.hextra-code-block code, [class~=not-prose],[class~=not-prose] *)) { | ||||
|     @apply hx:border-black/4 hx:bg-black/3 hx:break-words hx:rounded-md hx:border hx:py-0.5 hx:px-[.25em] hx:text-[.9em] hx:dark:border-white/10 hx:dark:bg-white/10; | ||||
|     @apply hx-border-black hx-border-opacity-[0.04] hx-bg-opacity-[0.03] hx-bg-black hx-break-words hx-rounded-md hx-border hx-py-0.5 hx-px-[.25em] hx-text-[.9em] dark:hx-border-white/10 dark:hx-bg-white/10; | ||||
|   } | ||||
|   :where(table):not(:where(.hextra-code-block table, [class~=not-prose],[class~=not-prose] *)) { | ||||
|     @apply hx:block hx:overflow-x-auto hx:my-6 hx:p-0 hx:first:mt-0 hx:w-full hx:text-sm hx:leading-5 hx:border-collapse; | ||||
|     @apply hx-block hx-overflow-x-auto hx-mt-6 hx-p-0 first:hx-mt-0; | ||||
|  | ||||
|     thead { | ||||
|       @apply hx:bg-gray-50 hx:dark:bg-gray-600/20; | ||||
|     } | ||||
|     tr { | ||||
|       @apply hx:m-0 hx:border-t hx:border-gray-300 hx:p-0 hx:dark:border-gray-600; | ||||
|       @apply hx-m-0 hx-border-t hx-border-gray-300 hx-p-0 dark:hx-border-gray-600 even:hx-bg-gray-100 even:dark:hx-bg-gray-600/20; | ||||
|     } | ||||
|     th { | ||||
|       @apply hx:m-0 hx:border hx:border-gray-300 hx:p-2 hx:font-semibold hx:dark:border-gray-600; | ||||
|       @apply hx-m-0 hx-border hx-border-gray-300 hx-px-4 hx-py-2 hx-font-semibold dark:hx-border-gray-600; | ||||
|     } | ||||
|     td { | ||||
|       @apply hx:m-0 hx:border hx:border-gray-300 hx:p-2 hx:dark:border-gray-600; | ||||
|       @apply hx-m-0 hx-border hx-border-gray-300 hx-px-4 hx-py-2 dark:hx-border-gray-600; | ||||
|     } | ||||
|   } | ||||
|   :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)) { | ||||
|     @apply hx:mt-6 hx:list-decimal hx:first:mt-0 hx:ltr:ml-6 hx:rtl:mr-6; | ||||
|     @apply hx-mt-6 hx-list-decimal first:hx-mt-0 ltr:hx-ml-6 rtl:hx-mr-6; | ||||
|     li { | ||||
|       @apply hx:my-2; | ||||
|       @apply hx-my-2; | ||||
|     } | ||||
|   } | ||||
|   :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)) { | ||||
|     @apply hx:mt-6 hx:list-disc hx:first:mt-0 hx:ltr:ml-6 hx:rtl:mr-6; | ||||
|     @apply hx-mt-6 hx-list-disc first:hx-mt-0 ltr:hx-ml-6 rtl:hx-mr-6; | ||||
|     li { | ||||
|       @apply hx:my-2; | ||||
|       @apply hx-my-2; | ||||
|     } | ||||
|   } | ||||
|   /* Task lists - hide list markers for lists containing checkboxes */ | ||||
|   :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)):has(li input[type="checkbox"]) { | ||||
|     @apply hx:list-none; | ||||
|   } | ||||
|   /* This CSS rule targets the first nested unordered (ul) or ordered (ol) list | ||||
|      inside the list item (li) of any parent ul or ol. | ||||
|      The rule sets the top margin of the selected list to zero. */ | ||||
|   :where(ul, ol) > li > :where(ul, ol):not(:where([class~=not-prose],[class~=not-prose] *)) { | ||||
|     @apply hx:mt-0; | ||||
|     @apply hx-mt-0; | ||||
|   } | ||||
|   :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)) { | ||||
|     @apply hx:border-black/4 hx:bg-black/3 hx:break-words hx:rounded-md hx:border hx:py-0.5 hx:px-[.25em] hx:text-[.9em] hx:dark:border-white/10 hx:dark:bg-white/10; | ||||
|     @apply hx-border-black hx-border-opacity-[0.04] hx-bg-opacity-[0.03] hx-bg-black hx-break-words hx-rounded-md hx-border hx-py-0.5 hx-px-[.25em] hx-text-[.9em] dark:hx-border-white/10 dark:hx-bg-white/10; | ||||
|   } | ||||
|   :where(pre.mermaid):not(:where(.hextra-code-block pre, [class~=not-prose],[class~=not-prose] *)) { | ||||
|     @apply hx:bg-transparent hx:rounded-none hx:dark:bg-transparent; | ||||
|     @apply hx-bg-transparent hx-rounded-none dark:hx-bg-transparent; | ||||
|   } | ||||
|   :where(img):not(:where([class~=not-prose],[class~=not-prose] *)) { | ||||
|     @apply hx:mx-auto hx:my-4 hx:rounded-md; | ||||
|     @apply hx-mx-auto hx-my-4 hx-rounded-md; | ||||
|   } | ||||
|   :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)) { | ||||
|     figcaption { | ||||
|       @apply hx:text-sm hx:text-gray-500 hx:dark:text-gray-400 hx:mt-2 hx:block hx:text-center; | ||||
|       @apply hx-text-sm hx-text-gray-500 dark:hx-text-gray-400 hx-mt-2 hx-block hx-text-center; | ||||
|     } | ||||
|   } | ||||
|   /* Definition list */ | ||||
|   :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)) { | ||||
|     dt { | ||||
|       @apply hx:mt-6 hx:font-semibold; | ||||
|       @apply hx-mt-6 hx-font-semibold; | ||||
|     } | ||||
|     dd { | ||||
|       @apply hx:my-2 hx:ps-6; | ||||
|       @apply hx-my-2 hx-ps-6; | ||||
|     } | ||||
|   } | ||||
|   /* Horizontal line */ | ||||
|   :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)) { | ||||
|     @apply hx:my-10 hx:first:mt-0 hx:last:mb-0 hx:border-gray-200 hx:dark:border-neutral-800; | ||||
|   } | ||||
|   .footnotes { | ||||
|     @apply hx:mt-12 hx:text-sm; | ||||
|     @apply hx-mt-12 hx-text-sm; | ||||
|   } | ||||
| } | ||||
|  | ||||
|     hr { | ||||
|       @apply hx:border-gray-200 hx:dark:border-neutral-800; | ||||
|     } | ||||
|   } | ||||
|   .subheading-anchor { | ||||
|     @apply hx:opacity-0 hx:transition-opacity hx:ltr:ml-1 hx:rtl:mr-1; | ||||
| .subheading-anchor { | ||||
|   @apply hx-opacity-0 hx-transition-opacity ltr:hx-ml-1 rtl:hx-mr-1; | ||||
|  | ||||
|   span:target + &, | ||||
|   :hover > &, | ||||
|   &:focus { | ||||
|       @apply hx:opacity-100; | ||||
|     @apply hx-opacity-100; | ||||
|   } | ||||
|  | ||||
|   span + &, | ||||
|   :hover > & { | ||||
|       @apply hx:no-underline!; | ||||
|     @apply !hx-no-underline; | ||||
|   } | ||||
|  | ||||
|     @apply hx:after:text-gray-300 hx:dark:after:text-neutral-700; | ||||
|   &:after { | ||||
|       @apply hx:content-['#'] hx:px-1; | ||||
|     @apply hx-content-['#'] hx-px-1; | ||||
|     @apply hx-text-gray-300 dark:hx-text-neutral-700; | ||||
|     span:target + & { | ||||
|         @apply hx:text-gray-400; | ||||
|         @apply hx:dark:text-neutral-500; | ||||
|       } | ||||
|       @apply hx-text-gray-400; | ||||
|       @apply dark:hx-text-neutral-500; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| article details > summary { | ||||
|   &::-webkit-details-marker { | ||||
|     @apply hx:hidden; | ||||
|     @apply hx-hidden; | ||||
|   } | ||||
|   &::before { | ||||
|     background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='hx:h-5 hx:w-5' viewBox='0 0 20 20' fill='currentColor'%3E%3Cpath fill-rule='evenodd' d='M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z' clip-rule='evenodd' /%3E%3C/svg%3E"); | ||||
|     background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='hx-h-5 hx-w-5' viewBox='0 0 20 20' fill='currentColor'%3E%3Cpath fill-rule='evenodd' d='M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z' clip-rule='evenodd' /%3E%3C/svg%3E"); | ||||
|     height: 1.2em; | ||||
|     width: 1.2em; | ||||
|     vertical-align: -4px; | ||||
|   | ||||
| @@ -1,30 +0,0 @@ | ||||
| /* Hugo template to derive CSS variables from site and page parameters */ | ||||
|  | ||||
| /* Do not remove the following comment. It is used by Hugo to render CSS variables. | ||||
| {{- $pageWidth := site.Params.page.width -}} | ||||
| {{- $maxPageWidth := cond (eq $pageWidth "wide") "90rem" (cond (eq $pageWidth "full") "100%" "80rem") -}} | ||||
|  | ||||
| {{- $navbarWidth := site.Params.navbar.width -}} | ||||
| {{- $maxNavbarWidth := cond (eq $navbarWidth "wide") "90rem" (cond (eq $navbarWidth "full") "100%" "80rem") -}} | ||||
|  | ||||
| {{- $footerWidth := site.Params.footer.width -}} | ||||
| {{- $maxFooterWidth := cond (eq $footerWidth "wide") "90rem" (cond (eq $footerWidth "full") "100%" "80rem") -}} | ||||
| */ | ||||
|  | ||||
| :root { | ||||
|   --hextra-max-page-width: {{ $maxPageWidth }}; | ||||
|   --hextra-max-navbar-width: {{ $maxNavbarWidth }}; | ||||
|   --hextra-max-footer-width: {{ $maxFooterWidth }}; | ||||
| } | ||||
|  | ||||
| .hextra-max-page-width { | ||||
|   max-width: var(--hextra-max-page-width); | ||||
| } | ||||
|  | ||||
| .hextra-max-navbar-width { | ||||
|   max-width: var(--hextra-max-navbar-width); | ||||
| } | ||||
|  | ||||
| .hextra-max-footer-width { | ||||
|   max-width: var(--hextra-max-footer-width); | ||||
| } | ||||
| @@ -5,9 +5,9 @@ document.addEventListener("DOMContentLoaded", function () { | ||||
|   if (backToTop) { | ||||
|     document.addEventListener("scroll", (e) => { | ||||
|       if (window.scrollY > 300) { | ||||
|         backToTop.classList.remove("hx:opacity-0"); | ||||
|         backToTop.classList.remove("hx-opacity-0"); | ||||
|       } else { | ||||
|         backToTop.classList.add("hx:opacity-0"); | ||||
|         backToTop.classList.add("hx-opacity-0"); | ||||
|       } | ||||
|     }); | ||||
|   } | ||||
| @@ -27,8 +27,8 @@ document.addEventListener('DOMContentLoaded', function () { | ||||
| 
 | ||||
|   document.querySelectorAll('.hextra-code-copy-btn').forEach(function (button) { | ||||
|     // Add copy and success icons
 | ||||
|     button.querySelector('.hextra-copy-icon')?.appendChild(getCopyIcon()); | ||||
|     button.querySelector('.hextra-success-icon')?.appendChild(getSuccessIcon()); | ||||
|     button.querySelector('.copy-icon')?.appendChild(getCopyIcon()); | ||||
|     button.querySelector('.success-icon')?.appendChild(getSuccessIcon()); | ||||
| 
 | ||||
|     // Add click event listener for copy button
 | ||||
|     button.addEventListener('click', function (e) { | ||||
| @@ -1,15 +0,0 @@ | ||||
| // {{- if site.Params.banner }} | ||||
| (function () { | ||||
|   const banner = document.querySelector(".hextra-banner") | ||||
|   document.documentElement.style.setProperty("--hextra-banner-height", banner.clientHeight+"px"); | ||||
|  | ||||
|   const closeBtn = banner.querySelector(".hextra-banner-close-button"); | ||||
|  | ||||
|   closeBtn.addEventListener("click", () => { | ||||
|     document.documentElement.classList.add("hextra-banner-hidden"); | ||||
|     document.documentElement.style.setProperty("--hextra-banner-height", "0px"); | ||||
|  | ||||
|     localStorage.setItem('{{ site.Params.banner.key | default `banner-closed` }}', "0"); | ||||
|   }); | ||||
| })(); | ||||
| // {{- end -}} | ||||
| @@ -1,22 +0,0 @@ | ||||
| // {{ $faviconDarkExists := fileExists (path.Join "static" "favicon-dark.svg") }} | ||||
| (function () { | ||||
|   const faviconEl = document.getElementById("favicon-svg"); | ||||
|   const faviconDarkExists = "{{ $faviconDarkExists }}" === "true"; | ||||
|  | ||||
|   if (faviconEl && faviconDarkExists) { | ||||
|     const lightFavicon = '{{ "favicon.svg" | relURL }}'; | ||||
|     const darkFavicon = '{{ "favicon-dark.svg" | relURL }}'; | ||||
|  | ||||
|     const darkModeQuery = window.matchMedia("(prefers-color-scheme: dark)"); | ||||
|  | ||||
|     function updateFavicon(e) { | ||||
|       faviconEl.href = e.matches ? darkFavicon : lightFavicon; | ||||
|     } | ||||
|  | ||||
|     // Set favicon on load | ||||
|     updateFavicon(darkModeQuery); | ||||
|  | ||||
|     // Listen for system preference changes | ||||
|     darkModeQuery.addEventListener("change", updateFavicon); | ||||
|   } | ||||
| })(); | ||||
| @@ -1,26 +0,0 @@ | ||||
| (function () { | ||||
|   const languageSwitchers = document.querySelectorAll('.hextra-language-switcher'); | ||||
|  | ||||
|   languageSwitchers.forEach((switcher) => { | ||||
|     switcher.addEventListener('click', (e) => { | ||||
|       e.preventDefault(); | ||||
|  | ||||
|       switcher.dataset.state = switcher.dataset.state === 'open' ? 'closed' : 'open'; | ||||
|  | ||||
|       toggleMenu(switcher); | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
|   window.addEventListener("resize", () => languageSwitchers.forEach(resizeMenu)) | ||||
|  | ||||
|   // Dismiss language switcher when clicking outside | ||||
|   document.addEventListener('click', (e) => { | ||||
|     if (e.target.closest('.hextra-language-switcher') === null) { | ||||
|       languageSwitchers.forEach((switcher) => { | ||||
|         switcher.dataset.state = 'closed'; | ||||
|         const optionsElement = switcher.nextElementSibling; | ||||
|         optionsElement.classList.add('hx:hidden'); | ||||
|       }); | ||||
|     } | ||||
|   }); | ||||
| })(); | ||||
| @@ -1,40 +0,0 @@ | ||||
| // Hamburger menu for mobile navigation | ||||
|  | ||||
| document.addEventListener('DOMContentLoaded', function () { | ||||
|   const menu = document.querySelector('.hextra-hamburger-menu'); | ||||
|   const sidebarContainer = document.querySelector('.hextra-sidebar-container'); | ||||
|  | ||||
|   function toggleMenu() { | ||||
|     // Toggle the hamburger menu | ||||
|     menu.querySelector('svg').classList.toggle('open'); | ||||
|  | ||||
|     // When the menu is open, we want to show the navigation sidebar | ||||
|     sidebarContainer.classList.toggle('hx:max-md:[transform:translate3d(0,-100%,0)]'); | ||||
|     sidebarContainer.classList.toggle('hx:max-md:[transform:translate3d(0,0,0)]'); | ||||
|  | ||||
|     // When the menu is open, we want to prevent the body from scrolling | ||||
|     document.body.classList.toggle('hx:overflow-hidden'); | ||||
|     document.body.classList.toggle('hx:md:overflow-auto'); | ||||
|   } | ||||
|  | ||||
|   menu.addEventListener('click', (e) => { | ||||
|     e.preventDefault(); | ||||
|     toggleMenu(); | ||||
|   }); | ||||
|  | ||||
|   // Select all anchor tags in the sidebar container | ||||
|   const sidebarLinks = sidebarContainer.querySelectorAll('a'); | ||||
|  | ||||
|   // Add click event listener to each anchor tag | ||||
|   sidebarLinks.forEach(link => { | ||||
|     link.addEventListener('click', (e) => { | ||||
|       // Check if the href attribute contains a hash symbol (links to a heading) | ||||
|       if (link.getAttribute('href') && link.getAttribute('href').startsWith('#')) { | ||||
|         // Only dismiss overlay on mobile view | ||||
|         if (window.innerWidth < 768) { | ||||
|           toggleMenu(); | ||||
|         } | ||||
|       } | ||||
|     }); | ||||
|   }); | ||||
| }); | ||||
| @@ -1,62 +0,0 @@ | ||||
| (function () { | ||||
|   const hiddenClass = "hx:hidden"; | ||||
|   const dropdownToggles = document.querySelectorAll(".hextra-nav-menu-toggle"); | ||||
|  | ||||
|   dropdownToggles.forEach((toggle) => { | ||||
|     toggle.addEventListener("click", (e) => { | ||||
|       e.preventDefault(); | ||||
|       e.stopPropagation(); | ||||
|  | ||||
|       // Close all other dropdowns first | ||||
|       dropdownToggles.forEach((otherToggle) => { | ||||
|         if (otherToggle !== toggle) { | ||||
|           otherToggle.dataset.state = "closed"; | ||||
|           const otherMenuItems = otherToggle.nextElementSibling; | ||||
|           otherMenuItems.classList.add(hiddenClass); | ||||
|         } | ||||
|       }); | ||||
|  | ||||
|       // Toggle current dropdown | ||||
|       const isOpen = toggle.dataset.state === "open"; | ||||
|       toggle.dataset.state = isOpen ? "closed" : "open"; | ||||
|       const menuItemsElement = toggle.nextElementSibling; | ||||
|  | ||||
|       if (!isOpen) { | ||||
|         // Position dropdown centered with toggle | ||||
|         menuItemsElement.style.position = "absolute"; | ||||
|         menuItemsElement.style.top = "100%"; | ||||
|         menuItemsElement.style.left = "50%"; | ||||
|         menuItemsElement.style.transform = "translateX(-50%)"; | ||||
|         menuItemsElement.style.zIndex = "1000"; | ||||
|  | ||||
|         // Show dropdown | ||||
|         menuItemsElement.classList.remove(hiddenClass); | ||||
|       } else { | ||||
|         // Hide dropdown | ||||
|         menuItemsElement.classList.add(hiddenClass); | ||||
|       } | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
|   // Dismiss dropdown when clicking outside | ||||
|   document.addEventListener("click", (e) => { | ||||
|     if (e.target.closest(".hextra-nav-menu-toggle") === null) { | ||||
|       dropdownToggles.forEach((toggle) => { | ||||
|         toggle.dataset.state = "closed"; | ||||
|         const menuItemsElement = toggle.nextElementSibling; | ||||
|         menuItemsElement.classList.add(hiddenClass); | ||||
|       }); | ||||
|     } | ||||
|   }); | ||||
|  | ||||
|   // Close dropdowns on escape key | ||||
|   document.addEventListener("keydown", (e) => { | ||||
|     if (e.key === "Escape") { | ||||
|       dropdownToggles.forEach((toggle) => { | ||||
|         toggle.dataset.state = "closed"; | ||||
|         const menuItemsElement = toggle.nextElementSibling; | ||||
|         menuItemsElement.classList.add(hiddenClass); | ||||
|       }); | ||||
|     } | ||||
|   }); | ||||
| })(); | ||||
| @@ -1,36 +0,0 @@ | ||||
| document.addEventListener("DOMContentLoaded", function () { | ||||
|   scrollToActiveItem(); | ||||
|   enableCollapsibles(); | ||||
| }); | ||||
|  | ||||
| function enableCollapsibles() { | ||||
|   const buttons = document.querySelectorAll(".hextra-sidebar-collapsible-button"); | ||||
|   buttons.forEach(function (button) { | ||||
|     button.addEventListener("click", function (e) { | ||||
|       e.preventDefault(); | ||||
|       const list = button.parentElement.parentElement; | ||||
|       if (list) { | ||||
|         list.classList.toggle("open") | ||||
|       } | ||||
|     }); | ||||
|   }); | ||||
| } | ||||
|  | ||||
| function scrollToActiveItem() { | ||||
|   const sidebarScrollbar = document.querySelector("aside.hextra-sidebar-container > .hextra-scrollbar"); | ||||
|   const activeItems = document.querySelectorAll(".hextra-sidebar-active-item"); | ||||
|   const visibleActiveItem = Array.from(activeItems).find(function (activeItem) { | ||||
|     return activeItem.getBoundingClientRect().height > 0; | ||||
|   }); | ||||
|  | ||||
|   if (!visibleActiveItem) { | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   const yOffset = visibleActiveItem.clientHeight; | ||||
|   const yDistance = visibleActiveItem.getBoundingClientRect().top - sidebarScrollbar.getBoundingClientRect().top; | ||||
|   sidebarScrollbar.scrollTo({ | ||||
|     behavior: "instant", | ||||
|     top: yDistance - yOffset | ||||
|   }); | ||||
| } | ||||
| @@ -1,52 +0,0 @@ | ||||
| function computeMenuTranslation(switcher, optionsElement) { | ||||
|   // Calculate the position of a language options element. | ||||
|   const switcherRect = switcher.getBoundingClientRect(); | ||||
|  | ||||
|   // Must be called before optionsElement.clientWidth. | ||||
|   optionsElement.style.minWidth = `${Math.max(switcherRect.width, 50)}px`; | ||||
|  | ||||
|   const isOnTop = switcher.dataset.location === 'top'; | ||||
|   const isOnBottom = switcher.dataset.location === 'bottom'; | ||||
|   const isOnBottomRight = switcher.dataset.location === 'bottom-right'; | ||||
|   const isRTL = document.documentElement.dir === 'rtl' | ||||
|  | ||||
|   // Stuck on the left side of the switcher. | ||||
|   let x = switcherRect.left; | ||||
|  | ||||
|   if (isOnTop && !isRTL || isOnBottom && isRTL || isOnBottomRight && !isRTL) { | ||||
|     // Stuck on the right side of the switcher. | ||||
|     x = switcherRect.right - optionsElement.clientWidth; | ||||
|   } | ||||
|  | ||||
|   // Stuck on the top of the switcher. | ||||
|   let y = switcherRect.top - window.innerHeight - 10; | ||||
|  | ||||
|   if (isOnTop) { | ||||
|     // Stuck on the bottom of the switcher. | ||||
|     y = switcherRect.top - window.innerHeight + optionsElement.clientHeight + switcher.clientHeight + 4; | ||||
|   } | ||||
|  | ||||
|   return { x: x, y: y }; | ||||
| } | ||||
|  | ||||
| function toggleMenu(switcher) { | ||||
|   const optionsElement = switcher.nextElementSibling; | ||||
|  | ||||
|   optionsElement.classList.toggle('hx:hidden'); | ||||
|  | ||||
|   // Calculate the position of a language options element. | ||||
|   const translate = computeMenuTranslation(switcher, optionsElement); | ||||
|  | ||||
|   optionsElement.style.transform = `translate3d(${translate.x}px, ${translate.y}px, 0)`; | ||||
| } | ||||
|  | ||||
| function resizeMenu(switcher) { | ||||
|   const optionsElement = switcher.nextElementSibling; | ||||
|  | ||||
|   if (optionsElement.classList.contains('hx:hidden')) return; | ||||
|  | ||||
|   // Calculate the position of a language options element. | ||||
|   const translate = computeMenuTranslation(switcher, optionsElement); | ||||
|  | ||||
|   optionsElement.style.transform = `translate3d(${translate.x}px, ${translate.y}px, 0)`; | ||||
| } | ||||
| @@ -1,57 +0,0 @@ | ||||
| (function () { | ||||
|   function updateGroup(container, index) { | ||||
|     const tabs = Array.from(container.querySelectorAll('.hextra-tabs-toggle')); | ||||
|     tabs.forEach((tab, i) => { | ||||
|       tab.dataset.state = i === index ? 'selected' : ''; | ||||
|       if (i === index) { | ||||
|         tab.setAttribute('aria-selected', 'true'); | ||||
|         tab.tabIndex = 0; | ||||
|       } else { | ||||
|         tab.removeAttribute('aria-selected'); | ||||
|         tab.removeAttribute('tabindex'); | ||||
|       } | ||||
|     }); | ||||
|     const panelsContainer = container.parentElement.nextElementSibling; | ||||
|     if (!panelsContainer) return; | ||||
|     Array.from(panelsContainer.children).forEach((panel, i) => { | ||||
|       panel.dataset.state = i === index ? 'selected' : ''; | ||||
|       if (i === index) { | ||||
|         panel.tabIndex = 0; | ||||
|       } else { | ||||
|         panel.removeAttribute('tabindex'); | ||||
|       } | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   const syncGroups = document.querySelectorAll('[data-tab-group]'); | ||||
|  | ||||
|   syncGroups.forEach((group) => { | ||||
|     const key = encodeURIComponent(group.dataset.tabGroup); | ||||
|     const saved = localStorage.getItem('hextra-tab-' + key); | ||||
|     if (saved !== null) { | ||||
|       updateGroup(group, parseInt(saved, 10)); | ||||
|     } | ||||
|   }); | ||||
|  | ||||
|   document.querySelectorAll('.hextra-tabs-toggle').forEach((button) => { | ||||
|     button.addEventListener('click', function (e) { | ||||
|       const container = e.target.parentElement; | ||||
|       const index = Array.from(container.querySelectorAll('.hextra-tabs-toggle')).indexOf( | ||||
|         e.target | ||||
|       ); | ||||
|        | ||||
|       if (container.dataset.tabGroup) { | ||||
|         // Sync behavior: update all tab groups with the same name | ||||
|         const tabGroupValue = container.dataset.tabGroup; | ||||
|         const key = encodeURIComponent(tabGroupValue); | ||||
|         document | ||||
|           .querySelectorAll('[data-tab-group="' + tabGroupValue + '"]') | ||||
|           .forEach((grp) => updateGroup(grp, index)); | ||||
|         localStorage.setItem('hextra-tab-' + key, index.toString()); | ||||
|       } else { | ||||
|         // Non-sync behavior: update only this specific tab group | ||||
|         updateGroup(container, index); | ||||
|       } | ||||
|     }); | ||||
|   }); | ||||
| })(); | ||||
| @@ -1,61 +0,0 @@ | ||||
| // Light / Dark theme toggle | ||||
| (function () { | ||||
|   const defaultTheme = '{{ site.Params.theme.default | default `system`}}' | ||||
|   const themes = ["light", "dark"]; | ||||
|  | ||||
|   const themeToggleButtons = document.querySelectorAll(".hextra-theme-toggle"); | ||||
|   const themeToggleOptions = document.querySelectorAll(".hextra-theme-toggle-options p"); | ||||
|  | ||||
|   function applyTheme(theme) { | ||||
|     theme = themes.includes(theme) ? theme : "system"; | ||||
|  | ||||
|     themeToggleButtons.forEach((btn) => btn.parentElement.dataset.theme = theme ); | ||||
|  | ||||
|     localStorage.setItem("color-theme", theme); | ||||
|   } | ||||
|  | ||||
|   function switchTheme(theme) { | ||||
|     setTheme(theme); | ||||
|     applyTheme(theme); | ||||
|   } | ||||
|  | ||||
|   const colorTheme = "color-theme" in localStorage ? localStorage.getItem("color-theme") : defaultTheme; | ||||
|   switchTheme(colorTheme); | ||||
|  | ||||
|   // Add click event handler to the menu items. | ||||
|   themeToggleOptions.forEach((option) => { | ||||
|     option.addEventListener("click", function (e) { | ||||
|       e.preventDefault(); | ||||
|  | ||||
|       switchTheme(option.dataset.item); | ||||
|     }) | ||||
|   }) | ||||
|  | ||||
|   // Add click event handler to the buttons | ||||
|   themeToggleButtons.forEach((toggler) => { | ||||
|     toggler.addEventListener("click", function (e) { | ||||
|       e.preventDefault(); | ||||
|  | ||||
|       toggleMenu(toggler); | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
|   window.addEventListener("resize", () => themeToggleButtons.forEach(resizeMenu)) | ||||
|  | ||||
|   // Dismiss the menu when clicking outside | ||||
|   document.addEventListener('click', (e) => { | ||||
|     if (e.target.closest('.hextra-theme-toggle') === null) { | ||||
|       themeToggleButtons.forEach((toggler) => { | ||||
|         toggler.dataset.state = 'closed'; | ||||
|         toggler.nextElementSibling.classList.add('hx:hidden'); | ||||
|       }); | ||||
|     } | ||||
|   }); | ||||
|  | ||||
|   // Listen for system theme changes | ||||
|   window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => { | ||||
|     if (localStorage.getItem("color-theme") === "system") { | ||||
|       setTheme("system"); | ||||
|     } | ||||
|   }); | ||||
| })(); | ||||
| @@ -1,93 +0,0 @@ | ||||
| /** | ||||
|  * TOC Scroll - Highlights active TOC links based on visible headings | ||||
|  *  | ||||
|  * Uses Intersection Observer to track heading visibility and applies | ||||
|  * 'hextra-toc-active' class to corresponding TOC links. Selects the | ||||
|  * topmost heading when multiple are visible. | ||||
|  *  | ||||
|  * Requires: .hextra-toc element, matching heading IDs, toc.css styles | ||||
|  */ | ||||
| document.addEventListener("DOMContentLoaded", function () { | ||||
|   const toc = document.querySelector(".hextra-toc"); | ||||
|   if (!toc) return; | ||||
|  | ||||
|   const tocLinks = toc.querySelectorAll('a[href^="#"]'); | ||||
|   if (tocLinks.length === 0) return; | ||||
|  | ||||
|   const headingIds = Array.from(tocLinks).map((link) => link.getAttribute("href").substring(1)); | ||||
|  | ||||
|   const headings = headingIds.map((id) => document.getElementById(decodeURIComponent(id))).filter(Boolean); | ||||
|   if (headings.length === 0) return; | ||||
|  | ||||
|   let currentActiveLink = null; | ||||
|   let isHashNavigation = false; | ||||
|  | ||||
|   // Create intersection observer | ||||
|   const observer = new IntersectionObserver( | ||||
|     (entries) => { | ||||
|       // Skip observer updates during hash navigation | ||||
|       if (isHashNavigation) return; | ||||
|  | ||||
|       const visibleHeadings = entries.filter((entry) => entry.isIntersecting).map((entry) => entry.target); | ||||
|  | ||||
|       if (visibleHeadings.length === 0) return; | ||||
|  | ||||
|       // Find the heading closest to the top of the viewport | ||||
|       const topMostHeading = visibleHeadings.reduce((closest, heading) => { | ||||
|         const headingTop = heading.getBoundingClientRect().top; | ||||
|         const closestTop = closest.getBoundingClientRect().top; | ||||
|         return Math.abs(headingTop) < Math.abs(closestTop) ? heading : closest; | ||||
|       }); | ||||
|  | ||||
|       // Encode the id and make it lowercase to match the TOC link | ||||
|       const targetId = encodeURIComponent(topMostHeading.id).toLowerCase(); | ||||
|       const targetLink = toc.querySelector(`a[href="#${targetId}"]`); | ||||
|  | ||||
|       if (targetLink && targetLink !== currentActiveLink) { | ||||
|         // Remove active class from previous link | ||||
|         if (currentActiveLink) { | ||||
|           currentActiveLink.classList.remove("hextra-toc-active"); | ||||
|         } | ||||
|  | ||||
|         // Add active class to current link | ||||
|         targetLink.classList.add("hextra-toc-active"); | ||||
|         currentActiveLink = targetLink; | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       rootMargin: "-20px 0px -60% 0px", // Adjust sensitivity | ||||
|       threshold: [0, 0.1, 0.5, 1], | ||||
|     } | ||||
|   ); | ||||
|  | ||||
|   // Observe all headings | ||||
|   headings.forEach((heading) => observer.observe(heading)); | ||||
|  | ||||
|   // Handle direct navigation to page with hash | ||||
|   function handleHashNavigation() { | ||||
|     const hash = window.location.hash; // already url encoded | ||||
|     if (hash) { | ||||
|       const targetLink = toc.querySelector(`a[href="${hash}"]`); | ||||
|       if (targetLink) { | ||||
|         // Disable observer temporarily during hash navigation | ||||
|         isHashNavigation = true; | ||||
|  | ||||
|         if (currentActiveLink) { | ||||
|           currentActiveLink.classList.remove("hextra-toc-active"); | ||||
|         } | ||||
|         targetLink.classList.add("hextra-toc-active"); | ||||
|         currentActiveLink = targetLink; | ||||
|  | ||||
|         // Re-enable observer after scroll settles | ||||
|         setTimeout(() => { isHashNavigation = false; }, 500); | ||||
|         return; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // Handle hash changes navigation | ||||
|   window.addEventListener("hashchange", handleHashNavigation); | ||||
|  | ||||
|   // Handle initial load | ||||
|   setTimeout(handleHashNavigation, 100); | ||||
| }); | ||||
| @@ -3,10 +3,10 @@ | ||||
| // 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 .hextra-search-wrapper class | ||||
|     const keys = document.querySelectorAll(".hextra-search-wrapper kbd"); | ||||
|     // select the kbd element under the .search-wrapper class | ||||
|     const keys = document.querySelectorAll(".search-wrapper kbd"); | ||||
|     keys.forEach(key => { | ||||
|       key.innerHTML = '<span class="hx:text-xs">⌘</span>K'; | ||||
|       key.innerHTML = '<span class="hx-text-xs">⌘</span>K'; | ||||
|     }); | ||||
|   } | ||||
| }); | ||||
| @@ -22,7 +22,7 @@ document.addEventListener("DOMContentLoaded", function () { | ||||
| (function () { | ||||
|   const searchDataURL = '{{ $searchData.RelPermalink }}'; | ||||
|  | ||||
|   const inputElements = document.querySelectorAll('.hextra-search-input'); | ||||
|   const inputElements = document.querySelectorAll('.search-input'); | ||||
|   for (const el of inputElements) { | ||||
|     el.addEventListener('focus', init); | ||||
|     el.addEventListener('keyup', search); | ||||
| @@ -30,7 +30,7 @@ document.addEventListener("DOMContentLoaded", function () { | ||||
|     el.addEventListener('input', handleInputChange); | ||||
|   } | ||||
|  | ||||
|   const shortcutElements = document.querySelectorAll('.hextra-search-wrapper kbd'); | ||||
|   const shortcutElements = document.querySelectorAll('.search-wrapper kbd'); | ||||
|  | ||||
|   function setShortcutElementsOpacity(opacity) { | ||||
|     shortcutElements.forEach(el => { | ||||
| @@ -45,12 +45,12 @@ document.addEventListener("DOMContentLoaded", function () { | ||||
|  | ||||
|   // Get the search wrapper, input, and results elements. | ||||
|   function getActiveSearchElement() { | ||||
|     const inputs = Array.from(document.querySelectorAll('.hextra-search-wrapper')).filter(el => el.clientHeight > 0); | ||||
|     const inputs = Array.from(document.querySelectorAll('.search-wrapper')).filter(el => el.clientHeight > 0); | ||||
|     if (inputs.length === 1) { | ||||
|       return { | ||||
|         wrapper: inputs[0], | ||||
|         inputElement: inputs[0].querySelector('.hextra-search-input'), | ||||
|         resultsElement: inputs[0].querySelector('.hextra-search-results') | ||||
|         inputElement: inputs[0].querySelector('.search-input'), | ||||
|         resultsElement: inputs[0].querySelector('.search-results') | ||||
|       }; | ||||
|     } | ||||
|     return undefined; | ||||
| @@ -103,7 +103,7 @@ document.addEventListener("DOMContentLoaded", function () { | ||||
|     const { resultsElement } = getActiveSearchElement(); | ||||
|     if (!resultsElement) return { result: undefined, index: -1 }; | ||||
|  | ||||
|     const result = resultsElement.querySelector('.hextra-search-active'); | ||||
|     const result = resultsElement.querySelector('.active'); | ||||
|     if (!result) return { result: undefined, index: -1 }; | ||||
|  | ||||
|     const index = parseInt(result.dataset.index, 10); | ||||
| @@ -116,10 +116,10 @@ document.addEventListener("DOMContentLoaded", function () { | ||||
|     if (!resultsElement) return; | ||||
|  | ||||
|     const { result: activeResult } = getActiveResult(); | ||||
|     activeResult && activeResult.classList.remove('hextra-search-active'); | ||||
|     activeResult && activeResult.classList.remove('active'); | ||||
|     const result = resultsElement.querySelector(`[data-index="${index}"]`); | ||||
|     if (result) { | ||||
|       result.classList.add('hextra-search-active'); | ||||
|       result.classList.add('active'); | ||||
|       result.focus(); | ||||
|     } | ||||
|   } | ||||
| @@ -143,7 +143,7 @@ document.addEventListener("DOMContentLoaded", function () { | ||||
|   function hideSearchResults() { | ||||
|     const { resultsElement } = getActiveSearchElement(); | ||||
|     if (!resultsElement) return; | ||||
|     resultsElement.classList.add('hx:hidden'); | ||||
|     resultsElement.classList.add('hx-hidden'); | ||||
|   } | ||||
|  | ||||
|   // Handle keyboard events. | ||||
| @@ -195,17 +195,8 @@ document.addEventListener("DOMContentLoaded", function () { | ||||
|    */ | ||||
|   async function preloadIndex() { | ||||
|     const tokenize = '{{- site.Params.search.flexsearch.tokenize | default  "forward" -}}'; | ||||
|  | ||||
|     // https://github.com/TryGhost/Ghost/pull/21148 | ||||
|     const regex = new RegExp( | ||||
|       `[\u{4E00}-\u{9FFF}\u{3040}-\u{309F}\u{30A0}-\u{30FF}\u{AC00}-\u{D7A3}\u{3400}-\u{4DBF}\u{20000}-\u{2A6DF}\u{2A700}-\u{2B73F}\u{2B740}-\u{2B81F}\u{2B820}-\u{2CEAF}\u{2CEB0}-\u{2EBEF}\u{30000}-\u{3134F}\u{31350}-\u{323AF}\u{2EBF0}-\u{2EE5F}\u{F900}-\u{FAFF}\u{2F800}-\u{2FA1F}]|[0-9A-Za-zа-я\u00C0-\u017F\u0400-\u04FF\u0600-\u06FF\u0980-\u09FF\u1E00-\u1EFF\u0590-\u05FF]+`, | ||||
|       'mug' | ||||
|     ); | ||||
|     const encode = (str) => { return ('' + str).toLowerCase().match(regex) ?? []; } | ||||
|  | ||||
|     window.pageIndex = new FlexSearch.Document({ | ||||
|       tokenize, | ||||
|       encode, | ||||
|       cache: 100, | ||||
|       document: { | ||||
|         id: 'id', | ||||
| @@ -216,15 +207,12 @@ document.addEventListener("DOMContentLoaded", function () { | ||||
|  | ||||
|     window.sectionIndex = new FlexSearch.Document({ | ||||
|       tokenize, | ||||
|       encode, | ||||
|       cache: 100, | ||||
|       document: { | ||||
|         id: 'id', | ||||
|         store: ['title', 'content', 'url', 'display', 'crumb'], | ||||
|         index: "content", | ||||
|         tag: [{ | ||||
|           field: "pageId" | ||||
|         }] | ||||
|         tag: 'pageId' | ||||
|       } | ||||
|     }); | ||||
|  | ||||
| @@ -237,7 +225,7 @@ document.addEventListener("DOMContentLoaded", function () { | ||||
|       const urlParts = route.split('/').filter(x => x != "" && !x.startsWith('#')); | ||||
|  | ||||
|       let crumb = ''; | ||||
|       let searchUrl = '/'; | ||||
|       let searchUrl = '/' | ||||
|       for (let i = 0; i < urlParts.length; i++) { | ||||
|         const urlPart = urlParts[i]; | ||||
|         searchUrl += urlPart + '/' | ||||
| @@ -316,7 +304,7 @@ document.addEventListener("DOMContentLoaded", function () { | ||||
|     while (resultsElement.firstChild) { | ||||
|       resultsElement.removeChild(resultsElement.firstChild); | ||||
|     } | ||||
|     resultsElement.classList.remove('hx:hidden'); | ||||
|     resultsElement.classList.remove('hx-hidden'); | ||||
|  | ||||
|     const pageResults = window.pageIndex.search(query, 5, { enrich: true, suggest: true })[0]?.result || []; | ||||
|  | ||||
| @@ -328,7 +316,7 @@ document.addEventListener("DOMContentLoaded", function () { | ||||
|       pageTitleMatches[i] = 0; | ||||
|  | ||||
|       // Show the top 5 results for each page | ||||
|       const sectionResults = window.sectionIndex.search(query, 5, { enrich: true, suggest: true, tag: { 'pageId': `page_${result.id}` } })[0]?.result || []; | ||||
|       const sectionResults = window.sectionIndex.search(query, 5, { enrich: true, suggest: true, tag: `page_${result.id}` })[0]?.result || []; | ||||
|       let isFirstItemOfPage = true | ||||
|       const occurred = {} | ||||
|  | ||||
| @@ -384,7 +372,7 @@ document.addEventListener("DOMContentLoaded", function () { | ||||
|     if (!resultsElement) return; | ||||
|  | ||||
|     if (!results.length) { | ||||
|       resultsElement.innerHTML = `<span class="hextra-search-no-result">{{ $noResultsFound | safeHTML }}</span>`; | ||||
|       resultsElement.innerHTML = `<span class="no-result">{{ $noResultsFound | safeHTML }}</span>`; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
| @@ -392,7 +380,7 @@ document.addEventListener("DOMContentLoaded", function () { | ||||
|     function highlightMatches(text, query) { | ||||
|       const escapedQuery = query.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&'); | ||||
|       const regex = new RegExp(escapedQuery, 'gi'); | ||||
|       return text.replace(regex, (match) => `<span class="hextra-search-match">${match}</span>`); | ||||
|       return text.replace(regex, (match) => `<span class="match">${match}</span>`); | ||||
|     } | ||||
|  | ||||
|     // Create a DOM element from the HTML string. | ||||
| @@ -405,11 +393,11 @@ document.addEventListener("DOMContentLoaded", function () { | ||||
|     function handleMouseMove(e) { | ||||
|       const target = e.target.closest('a'); | ||||
|       if (target) { | ||||
|         const active = resultsElement.querySelector('a.hextra-search-active'); | ||||
|         const active = resultsElement.querySelector('a.active'); | ||||
|         if (active) { | ||||
|           active.classList.remove('hextra-search-active'); | ||||
|           active.classList.remove('active'); | ||||
|         } | ||||
|         target.classList.add('hextra-search-active'); | ||||
|         target.classList.add('active'); | ||||
|       } | ||||
|     } | ||||
|  | ||||
| @@ -418,14 +406,14 @@ document.addEventListener("DOMContentLoaded", function () { | ||||
|       const result = results[i]; | ||||
|       if (result.prefix) { | ||||
|         fragment.appendChild(createElement(` | ||||
|           <div class="hextra-search-prefix">${result.prefix}</div>`)); | ||||
|           <div class="prefix">${result.prefix}</div>`)); | ||||
|       } | ||||
|       let li = createElement(` | ||||
|         <li> | ||||
|           <a data-index="${i}" href="${result.route}" class=${i === 0 ? "hextra-search-active" : ""}> | ||||
|             <div class="hextra-search-title">`+ highlightMatches(result.children.title, query) + `</div>` + | ||||
|           <a data-index="${i}" href="${result.route}" class=${i === 0 ? "active" : ""}> | ||||
|             <div class="title">`+ highlightMatches(result.children.title, query) + `</div>` + | ||||
|         (result.children.content ? | ||||
|             `<div class="hextra-search-excerpt">` + highlightMatches(result.children.content, query) + `</div>` : '') + ` | ||||
|           `<div class="excerpt">` + highlightMatches(result.children.content, query) + `</div>` : '') + ` | ||||
|           </a> | ||||
|         </li>`); | ||||
|       li.addEventListener('mousemove', handleMouseMove); | ||||
|   | ||||
| @@ -1,6 +0,0 @@ | ||||
| // The section must not be in the banner.js (body) file because it can create a quick flash. | ||||
|  | ||||
| if (localStorage.getItem('{{ site.Params.banner.key | default `banner-closed` }}')) { | ||||
|   document.documentElement.style.setProperty("--hextra-banner-height", "0px"); | ||||
|   document.documentElement.classList.add("hextra-banner-hidden"); | ||||
| } | ||||
| @@ -1,14 +0,0 @@ | ||||
| // The section must not be in the theme.js (body) file because it can create a quick flash (switch between light and dark). | ||||
|  | ||||
| function setTheme(theme) { | ||||
|   document.documentElement.classList.remove("light", "dark"); | ||||
|  | ||||
|   if (theme !== "light" && theme !== "dark") { | ||||
|     theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"; | ||||
|   } | ||||
|  | ||||
|   document.documentElement.classList.add(theme); | ||||
|   document.documentElement.style.colorScheme = theme; | ||||
| } | ||||
|  | ||||
| setTheme("color-theme" in localStorage ? localStorage.getItem("color-theme") : '{{ site.Params.theme.default | default `system`}}') | ||||
| @@ -1,508 +0,0 @@ | ||||
| (function () { | ||||
|   'use strict'; | ||||
|  | ||||
|   function createOverlayFromTarget(targetImg) { | ||||
|     const src = targetImg.currentSrc || targetImg.src; | ||||
|     const alt = targetImg.alt || ""; | ||||
|     if (!src) return; | ||||
|  | ||||
|     const rect = targetImg.getBoundingClientRect(); | ||||
|  | ||||
|     const overlay = document.createElement("div"); | ||||
|     overlay.className = "hextra-zoom-image-overlay"; | ||||
|     overlay.setAttribute("role", "dialog"); | ||||
|     overlay.setAttribute("aria-modal", "true"); | ||||
|     overlay.setAttribute("aria-label", alt || "Zoomed image"); | ||||
|  | ||||
|     const img = document.createElement("img"); | ||||
|     img.className = "hextra-zoom-image loading"; | ||||
|     img.src = src; | ||||
|     if (alt) img.alt = alt; | ||||
|  | ||||
|     // Center-origin positioning for cleaner transforms | ||||
|     const startCX = rect.left + rect.width / 2; | ||||
|     const startCY = rect.top + rect.height / 2; | ||||
|     img.style.position = "fixed"; | ||||
|     img.style.left = startCX + "px"; | ||||
|     img.style.top = startCY + "px"; | ||||
|     img.style.width = rect.width + "px"; | ||||
|     img.style.height = rect.height + "px"; | ||||
|     img.style.transformOrigin = "center center"; | ||||
|     img.style.transform = "translate3d(-50%, -50%, 0) scale(1)"; | ||||
|  | ||||
|     // Ensure overlay scales from center when zooming the whole overlay | ||||
|     overlay.style.transformOrigin = "center center"; | ||||
|     overlay.appendChild(img); | ||||
|  | ||||
|     // Image loaded handler | ||||
|     img.addEventListener('load', function () { | ||||
|       img.classList.remove('loading'); | ||||
|       img.classList.add('loaded'); | ||||
|     }); | ||||
|  | ||||
|     // Gesture state management | ||||
|     let isPinching = false; | ||||
|     let isDragging = false; | ||||
|     let isInteracting = false; | ||||
|     let pinchEndTimer = null; | ||||
|  | ||||
|     const pointers = new Map(); // pointerId -> {x, y, startX, startY} | ||||
|     const SCALE_MIN = 1; | ||||
|     const SCALE_MAX = 5; | ||||
|  | ||||
|     let gestureState = { | ||||
|       scale: 1, | ||||
|       panX: 0, | ||||
|       panY: 0, | ||||
|       startScale: 1, | ||||
|       startPanX: 0, | ||||
|       startPanY: 0, | ||||
|       initialDistance: 0, | ||||
|       initialMidpointX: 0, | ||||
|       initialMidpointY: 0, | ||||
|       dragStartX: 0, | ||||
|       dragStartY: 0, | ||||
|       dragPanX: 0, | ||||
|       dragPanY: 0 | ||||
|     }; | ||||
|  | ||||
|     // Utility functions | ||||
|     function getDistance(p1, p2) { | ||||
|       const dx = p2.x - p1.x; | ||||
|       const dy = p2.y - p1.y; | ||||
|       return Math.sqrt(dx * dx + dy * dy); | ||||
|     } | ||||
|  | ||||
|     function getMidpoint(p1, p2) { | ||||
|       return { | ||||
|         x: (p1.x + p2.x) / 2, | ||||
|         y: (p1.y + p2.y) / 2 | ||||
|       }; | ||||
|     } | ||||
|  | ||||
|     function setInteracting(value) { | ||||
|       isInteracting = value; | ||||
|       if (value) { | ||||
|         overlay.classList.add('interacting'); | ||||
|       } else { | ||||
|         overlay.classList.remove('interacting'); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     // Pointer event handlers | ||||
|     let tapCandidate = false; | ||||
|     let tapStartX = 0; | ||||
|     let tapStartY = 0; | ||||
|     let tapStartTime = 0; | ||||
|  | ||||
|     function onPointerDown(e) { | ||||
|       e.preventDefault(); | ||||
|  | ||||
|       if (typeof overlay.setPointerCapture === 'function') { | ||||
|         try { | ||||
|           overlay.setPointerCapture(e.pointerId); | ||||
|         } catch (err) { | ||||
|           // ignore pointer capture failures (e.g. Safari) | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       const pointerData = { | ||||
|         x: e.clientX, | ||||
|         y: e.clientY, | ||||
|         startX: e.clientX, | ||||
|         startY: e.clientY | ||||
|       }; | ||||
|  | ||||
|       pointers.set(e.pointerId, pointerData); | ||||
|  | ||||
|       if (pointers.size === 1) { | ||||
|         isDragging = false; | ||||
|         if (gestureState.scale > SCALE_MIN) { | ||||
|           setInteracting(true); | ||||
|         } | ||||
|  | ||||
|         // Set drag baseline so a single finger can pan when zoomed | ||||
|         gestureState.dragStartX = e.clientX; | ||||
|         gestureState.dragStartY = e.clientY; | ||||
|         gestureState.dragPanX = gestureState.panX; | ||||
|         gestureState.dragPanY = gestureState.panY; | ||||
|  | ||||
|         tapCandidate = true; | ||||
|         tapStartX = e.clientX; | ||||
|         tapStartY = e.clientY; | ||||
|         tapStartTime = (typeof performance !== 'undefined' ? performance.now() : Date.now()); | ||||
|       } else if (pointers.size === 2) { | ||||
|         isPinching = true; | ||||
|         isDragging = false; | ||||
|         setInteracting(true); | ||||
|         tapCandidate = false; | ||||
|  | ||||
|         const pts = Array.from(pointers.values()); | ||||
|         gestureState.initialDistance = getDistance(pts[0], pts[1]) || 1; | ||||
|         gestureState.startScale = gestureState.scale; | ||||
|         gestureState.startPanX = gestureState.panX; | ||||
|         gestureState.startPanY = gestureState.panY; | ||||
|  | ||||
|         const midpoint = getMidpoint(pts[0], pts[1]); | ||||
|         gestureState.initialMidpointX = midpoint.x; | ||||
|         gestureState.initialMidpointY = midpoint.y; | ||||
|  | ||||
|         if (pinchEndTimer) { | ||||
|           clearTimeout(pinchEndTimer); | ||||
|           pinchEndTimer = null; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     function onPointerMove(e) { | ||||
|       const pointer = pointers.get(e.pointerId); | ||||
|       if (!pointer) return; | ||||
|  | ||||
|       e.preventDefault(); | ||||
|  | ||||
|       pointer.x = e.clientX; | ||||
|       pointer.y = e.clientY; | ||||
|  | ||||
|       if (pointers.size === 2) { | ||||
|         const pts = Array.from(pointers.values()); | ||||
|         const currentDistance = getDistance(pts[0], pts[1]); | ||||
|         if (!currentDistance) return; | ||||
|  | ||||
|         const currentMidpoint = getMidpoint(pts[0], pts[1]); | ||||
|  | ||||
|         const distanceRatio = currentDistance / (gestureState.initialDistance || currentDistance); | ||||
|         let nextScale = gestureState.startScale * distanceRatio; | ||||
|         nextScale = Math.max(SCALE_MIN, Math.min(SCALE_MAX, nextScale)); | ||||
|  | ||||
|         const totalStart = baseScale * gestureState.startScale; | ||||
|         const totalNext = baseScale * nextScale; | ||||
|  | ||||
|         let nextPanX = gestureState.panX; | ||||
|         let nextPanY = gestureState.panY; | ||||
|  | ||||
|         if (totalStart > 0) { | ||||
|           const startOffsetX = gestureState.initialMidpointX - final.cx - gestureState.startPanX; | ||||
|           const startOffsetY = gestureState.initialMidpointY - final.cy - gestureState.startPanY; | ||||
|           const currentOffsetX = currentMidpoint.x - final.cx; | ||||
|           const currentOffsetY = currentMidpoint.y - final.cy; | ||||
|           const ratio = totalNext / totalStart; | ||||
|  | ||||
|           nextPanX = currentOffsetX - ratio * startOffsetX; | ||||
|           nextPanY = currentOffsetY - ratio * startOffsetY; | ||||
|         } | ||||
|  | ||||
|         gestureState.scale = nextScale; | ||||
|         gestureState.panX = nextPanX; | ||||
|         gestureState.panY = nextPanY; | ||||
|  | ||||
|         tapCandidate = false; | ||||
|         applyTransform(); | ||||
|       } else if (pointers.size === 1) { | ||||
|         const moveX = pointer.x - gestureState.dragStartX; | ||||
|         const moveY = pointer.y - gestureState.dragStartY; | ||||
|         const dragThreshold = 6; | ||||
|  | ||||
|         if (!isDragging) { | ||||
|           const distanceSq = moveX * moveX + moveY * moveY; | ||||
|           if (gestureState.scale > SCALE_MIN && distanceSq > dragThreshold * dragThreshold) { | ||||
|             isDragging = true; | ||||
|             tapCandidate = false; | ||||
|             setInteracting(true); | ||||
|             gestureState.dragPanX = gestureState.panX; | ||||
|             gestureState.dragPanY = gestureState.panY; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         if (isDragging) { | ||||
|           gestureState.panX = gestureState.dragPanX + moveX; | ||||
|           gestureState.panY = gestureState.dragPanY + moveY; | ||||
|           applyTransform(); | ||||
|         } else { | ||||
|           const cancelTapThreshold = 10; | ||||
|           if ( | ||||
|             Math.abs(pointer.x - tapStartX) > cancelTapThreshold || | ||||
|             Math.abs(pointer.y - tapStartY) > cancelTapThreshold | ||||
|           ) { | ||||
|             tapCandidate = false; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     function onPointerUp(e) { | ||||
|       if (typeof overlay.releasePointerCapture === 'function') { | ||||
|         try { | ||||
|           overlay.releasePointerCapture(e.pointerId); | ||||
|         } catch (err) { | ||||
|           // ignore release failures | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       pointers.delete(e.pointerId); | ||||
|  | ||||
|       if (pointers.size === 0) { | ||||
|         const now = (typeof performance !== 'undefined' ? performance.now() : Date.now()); | ||||
|         const duration = now - tapStartTime; | ||||
|         const shouldClose = tapCandidate && !isPinching && !isDragging && duration < 300; | ||||
|  | ||||
|         if (shouldClose) { | ||||
|           close(); | ||||
|         } | ||||
|  | ||||
|         tapCandidate = false; | ||||
|         isDragging = false; | ||||
|  | ||||
|         if (isPinching) { | ||||
|           pinchEndTimer = setTimeout(() => { | ||||
|             isPinching = false; | ||||
|           }, 180); | ||||
|         } else { | ||||
|           isPinching = false; | ||||
|         } | ||||
|  | ||||
|         gestureState.startScale = gestureState.scale; | ||||
|         gestureState.startPanX = gestureState.panX; | ||||
|         gestureState.startPanY = gestureState.panY; | ||||
|  | ||||
|         setTimeout(() => setInteracting(false), 120); | ||||
|       } else if (pointers.size === 1) { | ||||
|         isPinching = false; | ||||
|         isDragging = false; | ||||
|  | ||||
|         const remaining = Array.from(pointers.values())[0]; | ||||
|         remaining.startX = remaining.x; | ||||
|         remaining.startY = remaining.y; | ||||
|  | ||||
|         gestureState.dragStartX = remaining.x; | ||||
|         gestureState.dragStartY = remaining.y; | ||||
|         gestureState.dragPanX = gestureState.panX; | ||||
|         gestureState.dragPanY = gestureState.panY; | ||||
|  | ||||
|         if (gestureState.scale <= SCALE_MIN) { | ||||
|           setTimeout(() => setInteracting(false), 120); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     function onPointerCancel(e) { | ||||
|       onPointerUp(e); | ||||
|     } | ||||
|  | ||||
|     // Mouse wheel zoom and scroll handling | ||||
|     function onWheel(e) { | ||||
|       e.preventDefault(); | ||||
|  | ||||
|       // If it's a regular scroll (not pinch), dismiss the overlay | ||||
|       if (!e.ctrlKey && !e.metaKey) { | ||||
|         // Regular scroll - dismiss overlay gracefully | ||||
|         close(); | ||||
|         return; | ||||
|       } | ||||
|  | ||||
|       // Handle trackpad pinch (ctrl+wheel or cmd+wheel on Mac) | ||||
|       const delta = e.deltaY; | ||||
|       const scaleFactor = 0.01; | ||||
|       const zoomSpeed = Math.exp(-delta * scaleFactor); | ||||
|  | ||||
|       const prevScale = gestureState.scale; | ||||
|       const unclamped = prevScale * zoomSpeed; | ||||
|       const nextScale = Math.max(SCALE_MIN, Math.min(SCALE_MAX, unclamped)); | ||||
|  | ||||
|       if (Math.abs(nextScale - prevScale) > 0.0001) { | ||||
|         const totalPrev = baseScale * prevScale; | ||||
|         const totalNext = baseScale * nextScale; | ||||
|  | ||||
|         if (totalPrev > 0) { | ||||
|           const anchorOffsetX = e.clientX - final.cx; | ||||
|           const anchorOffsetY = e.clientY - final.cy; | ||||
|           const ratio = totalNext / totalPrev; | ||||
|  | ||||
|           gestureState.panX = anchorOffsetX + (gestureState.panX - anchorOffsetX) * ratio; | ||||
|           gestureState.panY = anchorOffsetY + (gestureState.panY - anchorOffsetY) * ratio; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       gestureState.scale = nextScale; | ||||
|       gestureState.startScale = nextScale; | ||||
|       gestureState.startPanX = gestureState.panX; | ||||
|       gestureState.startPanY = gestureState.panY; | ||||
|  | ||||
|       setInteracting(true); | ||||
|       applyTransform(); | ||||
|       setTimeout(() => setInteracting(false), 150); | ||||
|     } | ||||
|  | ||||
|     // Keyboard navigation | ||||
|     function onKeyDown(e) { | ||||
|       if (e.key === "Escape") { | ||||
|         close(); | ||||
|       } else if (e.key === "+" || e.key === "=") { | ||||
|         gestureState.scale = Math.min(SCALE_MAX, gestureState.scale * 1.2); | ||||
|         gestureState.startScale = gestureState.scale; | ||||
|         gestureState.startPanX = gestureState.panX; | ||||
|         gestureState.startPanY = gestureState.panY; | ||||
|         applyTransform(); | ||||
|       } else if (e.key === "-") { | ||||
|         gestureState.scale = Math.max(SCALE_MIN, gestureState.scale / 1.2); | ||||
|         gestureState.startScale = gestureState.scale; | ||||
|         gestureState.startPanX = gestureState.panX; | ||||
|         gestureState.startPanY = gestureState.panY; | ||||
|         applyTransform(); | ||||
|       } else if (e.key === "0") { | ||||
|         gestureState.scale = 1; | ||||
|         gestureState.panX = 0; | ||||
|         gestureState.panY = 0; | ||||
|         gestureState.startScale = gestureState.scale; | ||||
|         gestureState.startPanX = 0; | ||||
|         gestureState.startPanY = 0; | ||||
|         applyTransform(); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     // Apply transforms | ||||
|     let final = computeFinal(); | ||||
|     let baseScale = final.scale; | ||||
|  | ||||
|     function computeFinal() { | ||||
|       const vv = window.visualViewport; | ||||
|       const vw = vv ? vv.width : window.innerWidth; | ||||
|       const vh = vv ? vv.height : window.innerHeight; | ||||
|       const vx = vv ? vv.offsetLeft : 0; | ||||
|       const vy = vv ? vv.offsetTop : 0; | ||||
|  | ||||
|       const margin = 20; | ||||
|       const maxW = Math.min(vw - margin * 2, 1200); | ||||
|       const maxH = vh - margin * 2; | ||||
|  | ||||
|       const scale = Math.min(maxW / rect.width, maxH / rect.height, 2); | ||||
|       const centerX = vx + vw / 2; | ||||
|       const centerY = vy + vh / 2; | ||||
|  | ||||
|       return { cx: centerX, cy: centerY, scale }; | ||||
|     } | ||||
|  | ||||
|     function applyTransform() { | ||||
|       img.style.left = final.cx + "px"; | ||||
|       img.style.top = final.cy + "px"; | ||||
|  | ||||
|       overlay.style.transform = "none"; | ||||
|  | ||||
|       const totalScale = baseScale * gestureState.scale; | ||||
|       const transform = `translate3d(-50%, -50%, 0) translate3d(${gestureState.panX}px, ${gestureState.panY}px, 0) scale(${totalScale})`; | ||||
|       img.style.transform = transform; | ||||
|     } | ||||
|  | ||||
|     // Close function | ||||
|     function close(immediate = false) { | ||||
|       overlay.classList.add("closing"); | ||||
|  | ||||
|       // Animate back to original position | ||||
|       img.style.left = startCX + "px"; | ||||
|       img.style.top = startCY + "px"; | ||||
|       img.style.transform = `translate3d(-50%, -50%, 0) scale(1)`; | ||||
|  | ||||
|       // Cleanup event listeners | ||||
|       cleanup(); | ||||
|  | ||||
|       if (immediate) { | ||||
|         overlay.remove(); | ||||
|         return; | ||||
|       } | ||||
|  | ||||
|       // Remove after animation | ||||
|       const done = () => overlay.remove(); | ||||
|       overlay.addEventListener("transitionend", done, { once: true }); | ||||
|       img.addEventListener("transitionend", done, { once: true }); | ||||
|  | ||||
|       // Fallback removal | ||||
|       setTimeout(() => { | ||||
|         if (overlay.parentNode) { | ||||
|           overlay.remove(); | ||||
|         } | ||||
|       }, 400); | ||||
|     } | ||||
|  | ||||
|     function cleanup() { | ||||
|       window.removeEventListener("keydown", onKeyDown, true); | ||||
|       overlay.removeEventListener("wheel", onWheel); | ||||
|       overlay.removeEventListener("pointermove", onPointerMove); | ||||
|       overlay.removeEventListener("pointerdown", onPointerDown); | ||||
|       overlay.removeEventListener("pointerup", onPointerUp); | ||||
|       overlay.removeEventListener("pointercancel", onPointerCancel); | ||||
|       window.removeEventListener("resize", onResize); | ||||
|       if (window.visualViewport) { | ||||
|         window.visualViewport.removeEventListener("resize", onResize); | ||||
|         window.visualViewport.removeEventListener("scroll", onResize); | ||||
|       } | ||||
|       if (pinchEndTimer) { | ||||
|         clearTimeout(pinchEndTimer); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     // Handle viewport changes | ||||
|     function onResize() { | ||||
|       final = computeFinal(); | ||||
|       baseScale = final.scale; | ||||
|       gestureState.startScale = gestureState.scale; | ||||
|       gestureState.startPanX = gestureState.panX; | ||||
|       gestureState.startPanY = gestureState.panY; | ||||
|       applyTransform(); | ||||
|     } | ||||
|  | ||||
|     // Setup event listeners | ||||
|     overlay.addEventListener("wheel", onWheel, { passive: false }); | ||||
|     overlay.addEventListener("pointermove", onPointerMove); | ||||
|     overlay.addEventListener("pointerdown", onPointerDown); | ||||
|     overlay.addEventListener("pointerup", onPointerUp); | ||||
|     overlay.addEventListener("pointercancel", onPointerCancel); | ||||
|     window.addEventListener("keydown", onKeyDown, true); | ||||
|     window.addEventListener("resize", onResize, { passive: true }); | ||||
|  | ||||
|     if (window.visualViewport) { | ||||
|       window.visualViewport.addEventListener("resize", onResize, { passive: true }); | ||||
|       window.visualViewport.addEventListener("scroll", onResize, { passive: true }); | ||||
|     } | ||||
|  | ||||
|     // Add to DOM | ||||
|     document.body.appendChild(overlay); | ||||
|  | ||||
|     // Trigger opening animation | ||||
|     requestAnimationFrame(() => { | ||||
|       overlay.classList.add("show"); | ||||
|       applyTransform(); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   // Initialize after DOM ready | ||||
|   function init() { | ||||
|     const container = document.querySelector(".content"); | ||||
|     if (!container) return; | ||||
|  | ||||
|     container.addEventListener("click", function (e) { | ||||
|       const target = e.target; | ||||
|       if (!(target instanceof HTMLImageElement)) return; | ||||
|       // Only allow images inside `.content` that are NOT within a `.not-prose` block | ||||
|       if (target.closest('.not-prose')) return; | ||||
|       if (target.hasAttribute('data-no-zoom')) return; | ||||
|  | ||||
|       if (e.defaultPrevented) return; | ||||
|       if (typeof e.button === 'number' && e.button !== 0) return; | ||||
|       if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return; | ||||
|  | ||||
|       const interactiveParent = target.closest('a[href], button, [role="button"], summary, label'); | ||||
|       if (interactiveParent && interactiveParent !== target) { | ||||
|         return; | ||||
|       } | ||||
|  | ||||
|       e.preventDefault(); | ||||
|  | ||||
|       createOverlayFromTarget(target); | ||||
|     }, true); | ||||
|   } | ||||
|  | ||||
|   if (document.readyState === 'loading') { | ||||
|     document.addEventListener('DOMContentLoaded', init, { once: true }); | ||||
|   } else { | ||||
|     init(); | ||||
|   } | ||||
| })(); | ||||
							
								
								
									
										28
									
								
								assets/js/lang.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								assets/js/lang.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| (function () { | ||||
|   const languageSwitchers = document.querySelectorAll('.language-switcher'); | ||||
|   languageSwitchers.forEach((switcher) => { | ||||
|     switcher.addEventListener('click', (e) => { | ||||
|       e.preventDefault(); | ||||
|       switcher.dataset.state = switcher.dataset.state === 'open' ? 'closed' : 'open'; | ||||
|       const optionsElement = switcher.nextElementSibling; | ||||
|       optionsElement.classList.toggle('hx-hidden'); | ||||
|  | ||||
|       // Calculate position of language options element | ||||
|       const switcherRect = switcher.getBoundingClientRect(); | ||||
|       const translateY = switcherRect.top - window.innerHeight - 15; | ||||
|       optionsElement.style.transform = `translate3d(${switcherRect.left}px, ${translateY}px, 0)`; | ||||
|       optionsElement.style.minWidth = `${Math.max(switcherRect.width, 50)}px`; | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
|   // Dismiss language switcher when clicking outside | ||||
|   document.addEventListener('click', (e) => { | ||||
|     if (e.target.closest('.language-switcher') === null) { | ||||
|       languageSwitchers.forEach((switcher) => { | ||||
|         switcher.dataset.state = 'closed'; | ||||
|         const optionsElement = switcher.nextElementSibling; | ||||
|         optionsElement.classList.add('hx-hidden'); | ||||
|       }); | ||||
|     } | ||||
|   }); | ||||
| })(); | ||||
							
								
								
									
										49
									
								
								assets/js/menu.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								assets/js/menu.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| // Hamburger menu for mobile navigation | ||||
|  | ||||
| document.addEventListener('DOMContentLoaded', function () { | ||||
|   const menu = document.querySelector('.hamburger-menu'); | ||||
|   const overlay = document.querySelector('.mobile-menu-overlay'); | ||||
|   const sidebarContainer = document.querySelector('.hextra-sidebar-container'); | ||||
|  | ||||
|   // Initialize the overlay | ||||
|   const overlayClasses = ['hx-fixed', 'hx-inset-0', 'hx-z-10', 'hx-bg-black/80', 'dark:hx-bg-black/60']; | ||||
|   overlay.classList.add('hx-bg-transparent'); | ||||
|   overlay.classList.remove("hx-hidden", ...overlayClasses); | ||||
|  | ||||
|   function toggleMenu() { | ||||
|     // Toggle the hamburger menu | ||||
|     menu.querySelector('svg').classList.toggle('open'); | ||||
|  | ||||
|     // When the menu is open, we want to show the navigation sidebar | ||||
|     sidebarContainer.classList.toggle('max-md:[transform:translate3d(0,-100%,0)]'); | ||||
|     sidebarContainer.classList.toggle('max-md:[transform:translate3d(0,0,0)]'); | ||||
|  | ||||
|     // When the menu is open, we want to prevent the body from scrolling | ||||
|     document.body.classList.toggle('hx-overflow-hidden'); | ||||
|     document.body.classList.toggle('md:hx-overflow-auto'); | ||||
|   } | ||||
|  | ||||
|   menu.addEventListener('click', (e) => { | ||||
|     e.preventDefault(); | ||||
|     toggleMenu(); | ||||
|  | ||||
|     if (overlay.classList.contains('hx-bg-transparent')) { | ||||
|       // Show the overlay | ||||
|       overlay.classList.add(...overlayClasses); | ||||
|       overlay.classList.remove('hx-bg-transparent'); | ||||
|     } else { | ||||
|       // Hide the overlay | ||||
|       overlay.classList.remove(...overlayClasses); | ||||
|       overlay.classList.add('hx-bg-transparent'); | ||||
|     } | ||||
|   }); | ||||
|  | ||||
|   overlay.addEventListener('click', (e) => { | ||||
|     e.preventDefault(); | ||||
|     toggleMenu(); | ||||
|  | ||||
|     // Hide the overlay | ||||
|     overlay.classList.remove(...overlayClasses); | ||||
|     overlay.classList.add('hx-bg-transparent'); | ||||
|   }); | ||||
| }); | ||||
							
								
								
									
										78
									
								
								assets/js/sidebar.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								assets/js/sidebar.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| /** | ||||
|  * Check if the element is visible. | ||||
|  * @param {Element} element Dom element | ||||
|  * @returns boolean | ||||
|  */ | ||||
| function isVisible(element) { | ||||
|   return element.offsetWidth > 0 || element.offsetHeight > 0; | ||||
| } | ||||
|  | ||||
| document.addEventListener("DOMContentLoaded", function () { | ||||
|   scrollToActiveItem(); | ||||
|   enableCollapsibles(); | ||||
| }); | ||||
|  | ||||
| function enableCollapsibles() { | ||||
|   const buttons = document.querySelectorAll(".hextra-sidebar-collapsible-button"); | ||||
|   buttons.forEach(function (button) { | ||||
|     button.addEventListener("click", function (e) { | ||||
|       e.preventDefault(); | ||||
|       const list = button.parentElement.parentElement; | ||||
|       if (list) { | ||||
|         list.classList.toggle("open"); | ||||
|       } | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
|   const isCached = "{{- site.Params.page.sidebar.cache | default false -}}" === "true"; | ||||
|   const currentPagePath = window.location.href; | ||||
|  | ||||
|   if (isCached) { | ||||
|     // find the current page in the sidebar and open the parent lists | ||||
|     const sidebar = document.querySelector(".hextra-sidebar-container"); | ||||
|     if (sidebar) { | ||||
|       // find a tags and compare href with current page path | ||||
|       const links = sidebar.querySelectorAll("a"); | ||||
|       links.forEach(function (link) { | ||||
|         const linkPath = link.href; | ||||
|  | ||||
|         if (currentPagePath === linkPath) { | ||||
|           // add active class to the link | ||||
|           link.classList.add("active"); | ||||
|           link.classList.remove("inactive"); | ||||
|  | ||||
|           if (!isVisible(link)) { | ||||
|             return; | ||||
|           } | ||||
|           // recursively open parent lists | ||||
|           let parent = link.parentElement; | ||||
|           while (parent && !parent.classList.contains("hextra-sidebar-container")) { | ||||
|             if (parent.tagName === "LI" && parent.classList.contains("hextra-sidebar-item")) { | ||||
|               parent.classList.add("open"); | ||||
|             } | ||||
|             parent = parent.parentElement; | ||||
|           } | ||||
|         } | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| function scrollToActiveItem() { | ||||
|   const sidebarScrollbar = document.querySelector("aside.sidebar-container > .hextra-scrollbar"); | ||||
|   const activeItems = document.querySelectorAll(".sidebar-active-item"); | ||||
|   const visibleActiveItem = Array.from(activeItems).find(function (activeItem) { | ||||
|     return activeItem.getBoundingClientRect().height > 0; | ||||
|   }); | ||||
|  | ||||
|   if (!visibleActiveItem) { | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   const yOffset = visibleActiveItem.clientHeight; | ||||
|   const yDistance = visibleActiveItem.getBoundingClientRect().top - sidebarScrollbar.getBoundingClientRect().top; | ||||
|   sidebarScrollbar.scrollTo({ | ||||
|     behavior: "instant", | ||||
|     top: yDistance - yOffset, | ||||
|   }); | ||||
| } | ||||
							
								
								
									
										20
									
								
								assets/js/tabs.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								assets/js/tabs.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| document.querySelectorAll('.hextra-tabs-toggle').forEach(function (button) { | ||||
|   button.addEventListener('click', function (e) { | ||||
|     // set parent tabs to unselected | ||||
|     const tabs = Array.from(e.target.parentElement.querySelectorAll('.hextra-tabs-toggle')); | ||||
|     tabs.map(tab => tab.dataset.state = ''); | ||||
|  | ||||
|     // set current tab to selected | ||||
|     e.target.dataset.state = 'selected'; | ||||
|  | ||||
|     // set all panels to unselected | ||||
|     const panelsContainer = e.target.parentElement.parentElement.nextElementSibling; | ||||
|     Array.from(panelsContainer.children).forEach(function (panel) { | ||||
|       panel.dataset.state = ''; | ||||
|     }); | ||||
|  | ||||
|     const panelId = e.target.getAttribute('aria-controls'); | ||||
|     const panel = panelsContainer.querySelector(`#${panelId}`); | ||||
|     panel.dataset.state = 'selected'; | ||||
|   }); | ||||
| }); | ||||
							
								
								
									
										51
									
								
								assets/js/theme.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								assets/js/theme.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| // Light / Dark theme toggle | ||||
| (function () { | ||||
|   const defaultTheme = '{{ site.Params.theme.default | default `system`}}' | ||||
|  | ||||
|   const themeToggleButtons = document.querySelectorAll(".theme-toggle"); | ||||
|  | ||||
|   // Change the icons of the buttons based on previous settings or system theme | ||||
|   if ( | ||||
|     localStorage.getItem("color-theme") === "dark" || | ||||
|     (!("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 = "light"); | ||||
|   } | ||||
|  | ||||
|   // Add click event handler to the buttons | ||||
|   themeToggleButtons.forEach((el) => { | ||||
|     el.addEventListener("click", function () { | ||||
|       if (localStorage.getItem("color-theme")) { | ||||
|         if (localStorage.getItem("color-theme") === "light") { | ||||
|           setDarkTheme(); | ||||
|           localStorage.setItem("color-theme", "dark"); | ||||
|         } else { | ||||
|           setLightTheme(); | ||||
|           localStorage.setItem("color-theme", "light"); | ||||
|         } | ||||
|       } else { | ||||
|         if (document.documentElement.classList.contains("dark")) { | ||||
|           setLightTheme(); | ||||
|           localStorage.setItem("color-theme", "light"); | ||||
|         } else { | ||||
|           setDarkTheme(); | ||||
|           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" | ||||
|       ); | ||||
|     } | ||||
|   }); | ||||
| })(); | ||||
							
								
								
									
										39
									
								
								assets/lib/flexsearch/flexsearch.bundle.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								assets/lib/flexsearch/flexsearch.bundle.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| /** | ||||
|  * Skipped minification because the original files appears to be already minified. | ||||
|  * Original file: /npm/flexsearch@0.7.31/dist/flexsearch.bundle.js | ||||
|  * | ||||
|  * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files | ||||
|  */ | ||||
| /**! | ||||
|  * FlexSearch.js v0.7.31 (Bundle) | ||||
|  * Copyright 2018-2022 Nextapps GmbH | ||||
|  * Author: Thomas Wilkerling | ||||
|  * Licence: Apache-2.0 | ||||
|  * https://github.com/nextapps-de/flexsearch | ||||
|  */ | ||||
| (function _f(self){'use strict';try{if(module)self=module}catch(e){}self._factory=_f;var t;function u(a){return"undefined"!==typeof a?a:!0}function aa(a){const b=Array(a);for(let c=0;c<a;c++)b[c]=v();return b}function v(){return Object.create(null)}function ba(a,b){return b.length-a.length}function x(a){return"string"===typeof a}function C(a){return"object"===typeof a}function D(a){return"function"===typeof a};function ca(a,b){var c=da;if(a&&(b&&(a=E(a,b)),this.H&&(a=E(a,this.H)),this.J&&1<a.length&&(a=E(a,this.J)),c||""===c)){a=a.split(c);if(this.filter){b=this.filter;c=a.length;const d=[];for(let e=0,f=0;e<c;e++){const g=a[e];g&&!b[g]&&(d[f++]=g)}a=d}return a}return a}const da=/[\p{Z}\p{S}\p{P}\p{C}]+/u,ea=/[\u0300-\u036f]/g; | ||||
| function fa(a,b){const c=Object.keys(a),d=c.length,e=[];let f="",g=0;for(let h=0,k,m;h<d;h++)k=c[h],(m=a[k])?(e[g++]=F(b?"(?!\\b)"+k+"(\\b|_)":k),e[g++]=m):f+=(f?"|":"")+k;f&&(e[g++]=F(b?"(?!\\b)("+f+")(\\b|_)":"("+f+")"),e[g]="");return e}function E(a,b){for(let c=0,d=b.length;c<d&&(a=a.replace(b[c],b[c+1]),a);c+=2);return a}function F(a){return new RegExp(a,"g")}function ha(a){let b="",c="";for(let d=0,e=a.length,f;d<e;d++)(f=a[d])!==c&&(b+=c=f);return b};var ja={encode:ia,F:!1,G:""};function ia(a){return ca.call(this,(""+a).toLowerCase(),!1)};const ka={},G={};function la(a){I(a,"add");I(a,"append");I(a,"search");I(a,"update");I(a,"remove")}function I(a,b){a[b+"Async"]=function(){const c=this,d=arguments;var e=d[d.length-1];let f;D(e)&&(f=e,delete d[d.length-1]);e=new Promise(function(g){setTimeout(function(){c.async=!0;const h=c[b].apply(c,d);c.async=!1;g(h)})});return f?(e.then(f),this):e}};function ma(a,b,c,d){const e=a.length;let f=[],g,h,k=0;d&&(d=[]);for(let m=e-1;0<=m;m--){const n=a[m],w=n.length,q=v();let r=!g;for(let l=0;l<w;l++){const p=n[l],z=p.length;if(z)for(let B=0,A,y;B<z;B++)if(y=p[B],g){if(g[y]){if(!m)if(c)c--;else if(f[k++]=y,k===b)return f;if(m||d)q[y]=1;r=!0}if(d&&(A=(h[y]||0)+1,h[y]=A,A<e)){const H=d[A-2]||(d[A-2]=[]);H[H.length]=y}}else q[y]=1}if(d)g||(h=q);else if(!r)return[];g=q}if(d)for(let m=d.length-1,n,w;0<=m;m--){n=d[m];w=n.length;for(let q=0,r;q<w;q++)if(r= | ||||
| n[q],!g[r]){if(c)c--;else if(f[k++]=r,k===b)return f;g[r]=1}}return f}function na(a,b){const c=v(),d=v(),e=[];for(let f=0;f<a.length;f++)c[a[f]]=1;for(let f=0,g;f<b.length;f++){g=b[f];for(let h=0,k;h<g.length;h++)k=g[h],c[k]&&!d[k]&&(d[k]=1,e[e.length]=k)}return e};function J(a){this.l=!0!==a&&a;this.cache=v();this.h=[]}function oa(a,b,c){C(a)&&(a=a.query);let d=this.cache.get(a);d||(d=this.search(a,b,c),this.cache.set(a,d));return d}J.prototype.set=function(a,b){if(!this.cache[a]){var c=this.h.length;c===this.l?delete this.cache[this.h[c-1]]:c++;for(--c;0<c;c--)this.h[c]=this.h[c-1];this.h[0]=a}this.cache[a]=b};J.prototype.get=function(a){const b=this.cache[a];if(this.l&&b&&(a=this.h.indexOf(a))){const c=this.h[a-1];this.h[a-1]=this.h[a];this.h[a]=c}return b};const qa={memory:{charset:"latin:extra",D:3,B:4,m:!1},performance:{D:3,B:3,s:!1,context:{depth:2,D:1}},match:{charset:"latin:extra",G:"reverse"},score:{charset:"latin:advanced",D:20,B:3,context:{depth:3,D:9}},"default":{}};function ra(a,b,c,d,e,f,g){setTimeout(function(){const h=a(c?c+"."+d:d,JSON.stringify(g));h&&h.then?h.then(function(){b.export(a,b,c,e,f+1)}):b.export(a,b,c,e,f+1)})};function K(a,b){if(!(this instanceof K))return new K(a);var c;if(a){x(a)?a=qa[a]:(c=a.preset)&&(a=Object.assign({},c[c],a));c=a.charset;var d=a.lang;x(c)&&(-1===c.indexOf(":")&&(c+=":default"),c=G[c]);x(d)&&(d=ka[d])}else a={};let e,f,g=a.context||{};this.encode=a.encode||c&&c.encode||ia;this.register=b||v();this.D=e=a.resolution||9;this.G=b=c&&c.G||a.tokenize||"strict";this.depth="strict"===b&&g.depth;this.l=u(g.bidirectional);this.s=f=u(a.optimize);this.m=u(a.fastupdate);this.B=a.minlength||1;this.C= | ||||
| a.boost;this.map=f?aa(e):v();this.A=e=g.resolution||1;this.h=f?aa(e):v();this.F=c&&c.F||a.rtl;this.H=(b=a.matcher||d&&d.H)&&fa(b,!1);this.J=(b=a.stemmer||d&&d.J)&&fa(b,!0);if(c=b=a.filter||d&&d.filter){c=b;d=v();for(let h=0,k=c.length;h<k;h++)d[c[h]]=1;c=d}this.filter=c;this.cache=(b=a.cache)&&new J(b)}t=K.prototype;t.append=function(a,b){return this.add(a,b,!0)}; | ||||
| t.add=function(a,b,c,d){if(b&&(a||0===a)){if(!d&&!c&&this.register[a])return this.update(a,b);b=this.encode(b);if(d=b.length){const m=v(),n=v(),w=this.depth,q=this.D;for(let r=0;r<d;r++){let l=b[this.F?d-1-r:r];var e=l.length;if(l&&e>=this.B&&(w||!n[l])){var f=L(q,d,r),g="";switch(this.G){case "full":if(2<e){for(f=0;f<e;f++)for(var h=e;h>f;h--)if(h-f>=this.B){var k=L(q,d,r,e,f);g=l.substring(f,h);M(this,n,g,k,a,c)}break}case "reverse":if(1<e){for(h=e-1;0<h;h--)g=l[h]+g,g.length>=this.B&&M(this,n, | ||||
| g,L(q,d,r,e,h),a,c);g=""}case "forward":if(1<e){for(h=0;h<e;h++)g+=l[h],g.length>=this.B&&M(this,n,g,f,a,c);break}default:if(this.C&&(f=Math.min(f/this.C(b,l,r)|0,q-1)),M(this,n,l,f,a,c),w&&1<d&&r<d-1)for(e=v(),g=this.A,f=l,h=Math.min(w+1,d-r),e[f]=1,k=1;k<h;k++)if((l=b[this.F?d-1-r-k:r+k])&&l.length>=this.B&&!e[l]){e[l]=1;const p=this.l&&l>f;M(this,m,p?f:l,L(g+(d/2>g?0:1),d,r,h-1,k-1),a,c,p?l:f)}}}}this.m||(this.register[a]=1)}}return this}; | ||||
| function L(a,b,c,d,e){return c&&1<a?b+(d||0)<=a?c+(e||0):(a-1)/(b+(d||0))*(c+(e||0))+1|0:0}function M(a,b,c,d,e,f,g){let h=g?a.h:a.map;if(!b[c]||g&&!b[c][g])a.s&&(h=h[d]),g?(b=b[c]||(b[c]=v()),b[g]=1,h=h[g]||(h[g]=v())):b[c]=1,h=h[c]||(h[c]=[]),a.s||(h=h[d]||(h[d]=[])),f&&h.includes(e)||(h[h.length]=e,a.m&&(a=a.register[e]||(a.register[e]=[]),a[a.length]=h))} | ||||
| t.search=function(a,b,c){c||(!b&&C(a)?(c=a,a=c.query):C(b)&&(c=b));let d=[],e;let f,g=0;if(c){a=c.query||a;b=c.limit;g=c.offset||0;var h=c.context;f=c.suggest}if(a&&(a=this.encode(""+a),e=a.length,1<e)){c=v();var k=[];for(let n=0,w=0,q;n<e;n++)if((q=a[n])&&q.length>=this.B&&!c[q])if(this.s||f||this.map[q])k[w++]=q,c[q]=1;else return d;a=k;e=a.length}if(!e)return d;b||(b=100);h=this.depth&&1<e&&!1!==h;c=0;let m;h?(m=a[0],c=1):1<e&&a.sort(ba);for(let n,w;c<e;c++){w=a[c];h?(n=sa(this,d,f,b,g,2===e,w, | ||||
| m),f&&!1===n&&d.length||(m=w)):n=sa(this,d,f,b,g,1===e,w);if(n)return n;if(f&&c===e-1){k=d.length;if(!k){if(h){h=0;c=-1;continue}return d}if(1===k)return ta(d[0],b,g)}}return ma(d,b,g,f)}; | ||||
| function sa(a,b,c,d,e,f,g,h){let k=[],m=h?a.h:a.map;a.s||(m=ua(m,g,h,a.l));if(m){let n=0;const w=Math.min(m.length,h?a.A:a.D);for(let q=0,r=0,l,p;q<w;q++)if(l=m[q])if(a.s&&(l=ua(l,g,h,a.l)),e&&l&&f&&(p=l.length,p<=e?(e-=p,l=null):(l=l.slice(e),e=0)),l&&(k[n++]=l,f&&(r+=l.length,r>=d)))break;if(n){if(f)return ta(k,d,0);b[b.length]=k;return}}return!c&&k}function ta(a,b,c){a=1===a.length?a[0]:[].concat.apply([],a);return c||a.length>b?a.slice(c,c+b):a} | ||||
| function ua(a,b,c,d){c?(d=d&&b>c,a=(a=a[d?b:c])&&a[d?c:b]):a=a[b];return a}t.contain=function(a){return!!this.register[a]};t.update=function(a,b){return this.remove(a).add(a,b)}; | ||||
| t.remove=function(a,b){const c=this.register[a];if(c){if(this.m)for(let d=0,e;d<c.length;d++)e=c[d],e.splice(e.indexOf(a),1);else N(this.map,a,this.D,this.s),this.depth&&N(this.h,a,this.A,this.s);b||delete this.register[a];if(this.cache){b=this.cache;for(let d=0,e,f;d<b.h.length;d++)f=b.h[d],e=b.cache[f],e.includes(a)&&(b.h.splice(d--,1),delete b.cache[f])}}return this}; | ||||
| function N(a,b,c,d,e){let f=0;if(a.constructor===Array)if(e)b=a.indexOf(b),-1!==b?1<a.length&&(a.splice(b,1),f++):f++;else{e=Math.min(a.length,c);for(let g=0,h;g<e;g++)if(h=a[g])f=N(h,b,c,d,e),d||f||delete a[g]}else for(let g in a)(f=N(a[g],b,c,d,e))||delete a[g];return f}t.searchCache=oa; | ||||
| t.export=function(a,b,c,d,e){let f,g;switch(e||(e=0)){case 0:f="reg";if(this.m){g=v();for(let h in this.register)g[h]=1}else g=this.register;break;case 1:f="cfg";g={doc:0,opt:this.s?1:0};break;case 2:f="map";g=this.map;break;case 3:f="ctx";g=this.h;break;default:return}ra(a,b||this,c,f,d,e,g);return!0};t.import=function(a,b){if(b)switch(x(b)&&(b=JSON.parse(b)),a){case "cfg":this.s=!!b.opt;break;case "reg":this.m=!1;this.register=b;break;case "map":this.map=b;break;case "ctx":this.h=b}};la(K.prototype);function va(a){a=a.data;var b=self._index;const c=a.args;var d=a.task;switch(d){case "init":d=a.options||{};a=a.factory;b=d.encode;d.cache=!1;b&&0===b.indexOf("function")&&(d.encode=Function("return "+b)());a?(Function("return "+a)()(self),self._index=new self.FlexSearch.Index(d),delete self.FlexSearch):self._index=new K(d);break;default:a=a.id,b=b[d].apply(b,c),postMessage("search"===d?{id:a,msg:b}:{id:a})}};let wa=0;function O(a){if(!(this instanceof O))return new O(a);var b;a?D(b=a.encode)&&(a.encode=b.toString()):a={};(b=(self||window)._factory)&&(b=b.toString());const c="undefined"===typeof window&&self.exports,d=this;this.o=xa(b,c,a.worker);this.h=v();if(this.o){if(c)this.o.on("message",function(e){d.h[e.id](e.msg);delete d.h[e.id]});else this.o.onmessage=function(e){e=e.data;d.h[e.id](e.msg);delete d.h[e.id]};this.o.postMessage({task:"init",factory:b,options:a})}}P("add");P("append");P("search"); | ||||
| P("update");P("remove");function P(a){O.prototype[a]=O.prototype[a+"Async"]=function(){const b=this,c=[].slice.call(arguments);var d=c[c.length-1];let e;D(d)&&(e=d,c.splice(c.length-1,1));d=new Promise(function(f){setTimeout(function(){b.h[++wa]=f;b.o.postMessage({task:a,id:wa,args:c})})});return e?(d.then(e),this):d}} | ||||
| function xa(a,b,c){let d;try{d=b?eval('new (require("worker_threads")["Worker"])("../dist/node/node.js")'):a?new Worker(URL.createObjectURL(new Blob(["onmessage="+va.toString()],{type:"text/javascript"}))):new Worker(x(c)?c:"worker/worker.js",{type:"module"})}catch(e){}return d};function Q(a){if(!(this instanceof Q))return new Q(a);var b=a.document||a.doc||a,c;this.K=[];this.h=[];this.A=[];this.register=v();this.key=(c=b.key||b.id)&&S(c,this.A)||"id";this.m=u(a.fastupdate);this.C=(c=b.store)&&!0!==c&&[];this.store=c&&v();this.I=(c=b.tag)&&S(c,this.A);this.l=c&&v();this.cache=(c=a.cache)&&new J(c);a.cache=!1;this.o=a.worker;this.async=!1;c=v();let d=b.index||b.field||b;x(d)&&(d=[d]);for(let e=0,f,g;e<d.length;e++)f=d[e],x(f)||(g=f,f=f.field),g=C(g)?Object.assign({},a,g):a, | ||||
| this.o&&(c[f]=new O(g),c[f].o||(this.o=!1)),this.o||(c[f]=new K(g,this.register)),this.K[e]=S(f,this.A),this.h[e]=f;if(this.C)for(a=b.store,x(a)&&(a=[a]),b=0;b<a.length;b++)this.C[b]=S(a[b],this.A);this.index=c}function S(a,b){const c=a.split(":");let d=0;for(let e=0;e<c.length;e++)a=c[e],0<=a.indexOf("[]")&&(a=a.substring(0,a.length-2))&&(b[d]=!0),a&&(c[d++]=a);d<c.length&&(c.length=d);return 1<d?c:c[0]}function T(a,b){if(x(b))a=a[b];else for(let c=0;a&&c<b.length;c++)a=a[b[c]];return a} | ||||
| function U(a,b,c,d,e){a=a[e];if(d===c.length-1)b[e]=a;else if(a)if(a.constructor===Array)for(b=b[e]=Array(a.length),e=0;e<a.length;e++)U(a,b,c,d,e);else b=b[e]||(b[e]=v()),e=c[++d],U(a,b,c,d,e)}function V(a,b,c,d,e,f,g,h){if(a=a[g])if(d===b.length-1){if(a.constructor===Array){if(c[d]){for(b=0;b<a.length;b++)e.add(f,a[b],!0,!0);return}a=a.join(" ")}e.add(f,a,h,!0)}else if(a.constructor===Array)for(g=0;g<a.length;g++)V(a,b,c,d,e,f,g,h);else g=b[++d],V(a,b,c,d,e,f,g,h)}t=Q.prototype; | ||||
| t.add=function(a,b,c){C(a)&&(b=a,a=T(b,this.key));if(b&&(a||0===a)){if(!c&&this.register[a])return this.update(a,b);for(let d=0,e,f;d<this.h.length;d++)f=this.h[d],e=this.K[d],x(e)&&(e=[e]),V(b,e,this.A,0,this.index[f],a,e[0],c);if(this.I){let d=T(b,this.I),e=v();x(d)&&(d=[d]);for(let f=0,g,h;f<d.length;f++)if(g=d[f],!e[g]&&(e[g]=1,h=this.l[g]||(this.l[g]=[]),!c||!h.includes(a)))if(h[h.length]=a,this.m){const k=this.register[a]||(this.register[a]=[]);k[k.length]=h}}if(this.store&&(!c||!this.store[a])){let d; | ||||
| if(this.C){d=v();for(let e=0,f;e<this.C.length;e++)f=this.C[e],x(f)?d[f]=b[f]:U(b,d,f,0,f[0])}this.store[a]=d||b}}return this};t.append=function(a,b){return this.add(a,b,!0)};t.update=function(a,b){return this.remove(a).add(a,b)}; | ||||
| t.remove=function(a){C(a)&&(a=T(a,this.key));if(this.register[a]){for(var b=0;b<this.h.length&&(this.index[this.h[b]].remove(a,!this.o),!this.m);b++);if(this.I&&!this.m)for(let c in this.l){b=this.l[c];const d=b.indexOf(a);-1!==d&&(1<b.length?b.splice(d,1):delete this.l[c])}this.store&&delete this.store[a];delete this.register[a]}return this}; | ||||
| t.search=function(a,b,c,d){c||(!b&&C(a)?(c=a,a=""):C(b)&&(c=b,b=0));let e=[],f=[],g,h,k,m,n,w,q=0;if(c)if(c.constructor===Array)k=c,c=null;else{a=c.query||a;k=(g=c.pluck)||c.index||c.field;m=c.tag;h=this.store&&c.enrich;n="and"===c.bool;b=c.limit||b||100;w=c.offset||0;if(m&&(x(m)&&(m=[m]),!a)){for(let l=0,p;l<m.length;l++)if(p=ya.call(this,m[l],b,w,h))e[e.length]=p,q++;return q?e:[]}x(k)&&(k=[k])}k||(k=this.h);n=n&&(1<k.length||m&&1<m.length);const r=!d&&(this.o||this.async)&&[];for(let l=0,p,z,B;l< | ||||
| k.length;l++){let A;z=k[l];x(z)||(A=z,z=A.field,a=A.query||a,b=A.limit||b);if(r)r[l]=this.index[z].searchAsync(a,b,A||c);else{d?p=d[l]:p=this.index[z].search(a,b,A||c);B=p&&p.length;if(m&&B){const y=[];let H=0;n&&(y[0]=[p]);for(let X=0,pa,R;X<m.length;X++)if(pa=m[X],B=(R=this.l[pa])&&R.length)H++,y[y.length]=n?[R]:R;H&&(p=n?ma(y,b||100,w||0):na(p,y),B=p.length)}if(B)f[q]=z,e[q++]=p;else if(n)return[]}}if(r){const l=this;return new Promise(function(p){Promise.all(r).then(function(z){p(l.search(a,b, | ||||
| c,z))})})}if(!q)return[];if(g&&(!h||!this.store))return e[0];for(let l=0,p;l<f.length;l++){p=e[l];p.length&&h&&(p=za.call(this,p));if(g)return p;e[l]={field:f[l],result:p}}return e};function ya(a,b,c,d){let e=this.l[a],f=e&&e.length-c;if(f&&0<f){if(f>b||c)e=e.slice(c,c+b);d&&(e=za.call(this,e));return{tag:a,result:e}}}function za(a){const b=Array(a.length);for(let c=0,d;c<a.length;c++)d=a[c],b[c]={id:d,doc:this.store[d]};return b}t.contain=function(a){return!!this.register[a]};t.get=function(a){return this.store[a]}; | ||||
| t.set=function(a,b){this.store[a]=b;return this};t.searchCache=oa;t.export=function(a,b,c,d,e){e||(e=0);d||(d=0);if(d<this.h.length){const f=this.h[d],g=this.index[f];b=this;setTimeout(function(){g.export(a,b,e?f:"",d,e++)||(d++,e=1,b.export(a,b,f,d,e))})}else{let f,g;switch(e){case 1:f="tag";g=this.l;break;case 2:f="store";g=this.store;break;default:return}ra(a,this,c,f,d,e,g)}}; | ||||
| t.import=function(a,b){if(b)switch(x(b)&&(b=JSON.parse(b)),a){case "tag":this.l=b;break;case "reg":this.m=!1;this.register=b;for(let d=0,e;d<this.h.length;d++)e=this.index[this.h[d]],e.register=b,e.m=!1;break;case "store":this.store=b;break;default:a=a.split(".");const c=a[0];a=a[1];c&&a&&this.index[c].import(a,b)}};la(Q.prototype);var Ba={encode:Aa,F:!1,G:""};const Ca=[F("[\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5]"),"a",F("[\u00e8\u00e9\u00ea\u00eb]"),"e",F("[\u00ec\u00ed\u00ee\u00ef]"),"i",F("[\u00f2\u00f3\u00f4\u00f5\u00f6\u0151]"),"o",F("[\u00f9\u00fa\u00fb\u00fc\u0171]"),"u",F("[\u00fd\u0177\u00ff]"),"y",F("\u00f1"),"n",F("[\u00e7c]"),"k",F("\u00df"),"s",F(" & ")," and "];function Aa(a){var b=a=""+a;b.normalize&&(b=b.normalize("NFD").replace(ea,""));return ca.call(this,b.toLowerCase(),!a.normalize&&Ca)};var Ea={encode:Da,F:!1,G:"strict"};const Fa=/[^a-z0-9]+/,Ga={b:"p",v:"f",w:"f",z:"s",x:"s","\u00df":"s",d:"t",n:"m",c:"k",g:"k",j:"k",q:"k",i:"e",y:"e",u:"o"};function Da(a){a=Aa.call(this,a).join(" ");const b=[];if(a){const c=a.split(Fa),d=c.length;for(let e=0,f,g=0;e<d;e++)if((a=c[e])&&(!this.filter||!this.filter[a])){f=a[0];let h=Ga[f]||f,k=h;for(let m=1;m<a.length;m++){f=a[m];const n=Ga[f]||f;n&&n!==k&&(h+=n,k=n)}b[g++]=h}}return b};var Ia={encode:Ha,F:!1,G:""};const Ja=[F("ae"),"a",F("oe"),"o",F("sh"),"s",F("th"),"t",F("ph"),"f",F("pf"),"f",F("(?![aeo])h(?![aeo])"),"",F("(?!^[aeo])h(?!^[aeo])"),""];function Ha(a,b){a&&(a=Da.call(this,a).join(" "),2<a.length&&(a=E(a,Ja)),b||(1<a.length&&(a=ha(a)),a&&(a=a.split(" "))));return a||[]};var La={encode:Ka,F:!1,G:""};const Ma=F("(?!\\b)[aeo]");function Ka(a){a&&(a=Ha.call(this,a,!0),1<a.length&&(a=a.replace(Ma,"")),1<a.length&&(a=ha(a)),a&&(a=a.split(" ")));return a||[]};G["latin:default"]=ja;G["latin:simple"]=Ba;G["latin:balance"]=Ea;G["latin:advanced"]=Ia;G["latin:extra"]=La;const W=self;let Y;const Z={Index:K,Document:Q,Worker:O,registerCharset:function(a,b){G[a]=b},registerLanguage:function(a,b){ka[a]=b}};(Y=W.define)&&Y.amd?Y([],function(){return Z}):W.exports?W.exports=Z:W.FlexSearch=Z;}(this)); | ||||
							
								
								
									
										1
									
								
								assets/lib/katex/auto-render.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/lib/katex/auto-render.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={771:function(t){t.exports=e}},n={};function r(e){var o=n[e];if(void 0!==o)return o.exports;var i=n[e]={exports:{}};return t[e](i,i.exports,r),i.exports}r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,{a:t}),t},r.d=function(e,t){for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var o={};return function(){r.d(o,{default:function(){return d}});var e=r(771),t=r.n(e);const n=function(e,t,n){let r=n,o=0;const i=e.length;for(;r<t.length;){const n=t[r];if(o<=0&&t.slice(r,r+i)===e)return r;"\\"===n?r++:"{"===n?o++:"}"===n&&o--,r++}return-1},i=/^\\begin{/;var a=function(e,t){let r;const o=[],a=new RegExp("("+t.map((e=>e.left.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"))).join("|")+")");for(;r=e.search(a),-1!==r;){r>0&&(o.push({type:"text",data:e.slice(0,r)}),e=e.slice(r));const a=t.findIndex((t=>e.startsWith(t.left)));if(r=n(t[a].right,e,t[a].left.length),-1===r)break;const l=e.slice(0,r+t[a].right.length),s=i.test(l)?l:e.slice(t[a].left.length,r);o.push({type:"math",data:s,rawData:l,display:t[a].display}),e=e.slice(r+t[a].right.length)}return""!==e&&o.push({type:"text",data:e}),o};const l=function(e,n){const r=a(e,n.delimiters);if(1===r.length&&"text"===r[0].type)return null;const o=document.createDocumentFragment();for(let e=0;e<r.length;e++)if("text"===r[e].type)o.appendChild(document.createTextNode(r[e].data));else{const i=document.createElement("span");let a=r[e].data;n.displayMode=r[e].display;try{n.preProcess&&(a=n.preProcess(a)),t().render(a,i,n)}catch(i){if(!(i instanceof t().ParseError))throw i;n.errorCallback("KaTeX auto-render: Failed to parse `"+r[e].data+"` with ",i),o.appendChild(document.createTextNode(r[e].rawData));continue}o.appendChild(i)}return o},s=function(e,t){for(let n=0;n<e.childNodes.length;n++){const r=e.childNodes[n];if(3===r.nodeType){let o=r.textContent,i=r.nextSibling,a=0;for(;i&&i.nodeType===Node.TEXT_NODE;)o+=i.textContent,i=i.nextSibling,a++;const s=l(o,t);if(s){for(let e=0;e<a;e++)r.nextSibling.remove();n+=s.childNodes.length-1,e.replaceChild(s,r)}else n+=a}else if(1===r.nodeType){const e=" "+r.className+" ";-1===t.ignoredTags.indexOf(r.nodeName.toLowerCase())&&t.ignoredClasses.every((t=>-1===e.indexOf(" "+t+" ")))&&s(r,t)}}};var d=function(e,t){if(!e)throw new Error("No element provided to render");const n={};for(const e in t)t.hasOwnProperty(e)&&(n[e]=t[e]);n.delimiters=n.delimiters||[{left:"$$",right:"$$",display:!0},{left:"\\(",right:"\\)",display:!1},{left:"\\begin{equation}",right:"\\end{equation}",display:!0},{left:"\\begin{align}",right:"\\end{align}",display:!0},{left:"\\begin{alignat}",right:"\\end{alignat}",display:!0},{left:"\\begin{gather}",right:"\\end{gather}",display:!0},{left:"\\begin{CD}",right:"\\end{CD}",display:!0},{left:"\\[",right:"\\]",display:!0}],n.ignoredTags=n.ignoredTags||["script","noscript","style","textarea","pre","code","option"],n.ignoredClasses=n.ignoredClasses||[],n.errorCallback=n.errorCallback||console.error,n.macros=n.macros||{},s(e,n)}}(),o=o.default}()})); | ||||
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_AMS-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_AMS-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_AMS-Regular.woff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_AMS-Regular.woff
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_AMS-Regular.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_AMS-Regular.woff2
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Caligraphic-Bold.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Caligraphic-Bold.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Caligraphic-Bold.woff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Caligraphic-Bold.woff
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Caligraphic-Bold.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Caligraphic-Bold.woff2
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Caligraphic-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Caligraphic-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Caligraphic-Regular.woff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Caligraphic-Regular.woff
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Caligraphic-Regular.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Caligraphic-Regular.woff2
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Fraktur-Bold.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Fraktur-Bold.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Fraktur-Bold.woff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Fraktur-Bold.woff
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Fraktur-Bold.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Fraktur-Bold.woff2
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Fraktur-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Fraktur-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Fraktur-Regular.woff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Fraktur-Regular.woff
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Fraktur-Regular.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Fraktur-Regular.woff2
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-Bold.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-Bold.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-Bold.woff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-Bold.woff
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-Bold.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-Bold.woff2
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-BoldItalic.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-BoldItalic.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-BoldItalic.woff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-BoldItalic.woff
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-BoldItalic.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-BoldItalic.woff2
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-Italic.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-Italic.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-Italic.woff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-Italic.woff
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-Italic.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-Italic.woff2
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-Regular.woff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-Regular.woff
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-Regular.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Main-Regular.woff2
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Math-BoldItalic.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Math-BoldItalic.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Math-BoldItalic.woff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Math-BoldItalic.woff
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Math-BoldItalic.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Math-BoldItalic.woff2
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Math-Italic.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Math-Italic.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Math-Italic.woff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Math-Italic.woff
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Math-Italic.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Math-Italic.woff2
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_SansSerif-Bold.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_SansSerif-Bold.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_SansSerif-Bold.woff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_SansSerif-Bold.woff
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_SansSerif-Bold.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_SansSerif-Bold.woff2
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_SansSerif-Italic.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_SansSerif-Italic.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_SansSerif-Italic.woff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_SansSerif-Italic.woff
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_SansSerif-Italic.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_SansSerif-Italic.woff2
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_SansSerif-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_SansSerif-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_SansSerif-Regular.woff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_SansSerif-Regular.woff
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_SansSerif-Regular.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_SansSerif-Regular.woff2
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Script-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Script-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Script-Regular.woff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Script-Regular.woff
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Script-Regular.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Script-Regular.woff2
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Size1-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Size1-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Size1-Regular.woff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Size1-Regular.woff
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Size1-Regular.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Size1-Regular.woff2
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Size2-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Size2-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Size2-Regular.woff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Size2-Regular.woff
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Size2-Regular.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Size2-Regular.woff2
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Size3-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Size3-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Size3-Regular.woff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/lib/katex/fonts/KaTeX_Size3-Regular.woff
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user