docs | sidebar

This commit is contained in:
babayaga 2025-12-30 00:14:53 +01:00
parent f422f77f0a
commit a0132a7bf1
37 changed files with 2912 additions and 71 deletions

View File

@ -23,7 +23,7 @@
"format": "unix-time"
}
],
"default": "2025-12-29T22:44:15.028Z"
"default": "2025-12-29T23:12:02.959Z"
},
"description": {
"type": "string",

View File

@ -1,4 +1,10 @@
export default new Map([
["src/content/resources/astro-development.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fresources%2Fastro-development.mdx&astroContentModuleFlag=true")],
["src/content/resources/collections.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fresources%2Fcollections.mdx&astroContentModuleFlag=true")],
["src/content/resources/FileTree.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fresources%2FFileTree.mdx&astroContentModuleFlag=true")],
["src/content/resources/Masonry.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fresources%2FMasonry.mdx&astroContentModuleFlag=true")],
["src/content/resources/sidebar.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fresources%2Fsidebar.mdx&astroContentModuleFlag=true")],
["src/content/resources/test.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fresources%2Ftest.mdx&astroContentModuleFlag=true")],
["src/content/resources/workflow.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fresources%2Fworkflow.mdx&astroContentModuleFlag=true")]]);

File diff suppressed because one or more lines are too long

21
app.log
View File

@ -199,3 +199,24 @@
{"level":"INFO","time":"2025-12-29T22:44:14.393Z","pid":27608,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from C:\\Users\\zx\\Desktop\\polymech\\library.polymech\\app-config.json for locale en"}
{"level":"INFO","time":"2025-12-29T22:44:14.403Z","pid":27608,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from ./app-config.json for locale en"}
{"level":"INFO","time":"2025-12-29T22:45:26.156Z","pid":27608,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from C:\\Users\\zx\\Desktop\\polymech\\library.polymech\\app-config.json for locale es"}
{"level":"INFO","time":"2025-12-29T22:50:59.233Z","pid":18260,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from C:\\Users\\zx\\Desktop\\polymech\\library.polymech\\app-config.json for locale en"}
{"level":"INFO","time":"2025-12-29T22:50:59.811Z","pid":18260,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from ./app-config.json for locale en"}
{"level":"INFO","time":"2025-12-29T22:51:10.198Z","pid":22516,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from C:\\Users\\zx\\Desktop\\polymech\\library.polymech\\app-config.json for locale en"}
{"level":"INFO","time":"2025-12-29T22:51:12.520Z","pid":22516,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from C:\\Users\\zx\\Desktop\\polymech\\library.polymech\\app-config.json for locale en"}
{"level":"INFO","time":"2025-12-29T22:51:13.551Z","pid":22516,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from C:\\Users\\zx\\Desktop\\polymech\\library.polymech\\app-config.json for locale en"}
{"level":"INFO","time":"2025-12-29T22:51:13.563Z","pid":22516,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from ./app-config.json for locale en"}
{"level":"INFO","time":"2025-12-29T22:51:30.288Z","pid":22516,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from C:\\Users\\zx\\Desktop\\polymech\\library.polymech\\app-config.json for locale es"}
{"level":"INFO","time":"2025-12-29T22:53:59.973Z","pid":24864,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from C:\\Users\\zx\\Desktop\\polymech\\library.polymech\\app-config.json for locale en"}
{"level":"INFO","time":"2025-12-29T22:54:00.942Z","pid":24864,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from ./app-config.json for locale en"}
{"level":"INFO","time":"2025-12-29T22:54:16.178Z","pid":27916,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from C:\\Users\\zx\\Desktop\\polymech\\library.polymech\\app-config.json for locale en"}
{"level":"INFO","time":"2025-12-29T22:54:20.530Z","pid":27916,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from C:\\Users\\zx\\Desktop\\polymech\\library.polymech\\app-config.json for locale en"}
{"level":"INFO","time":"2025-12-29T22:54:22.605Z","pid":27916,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from C:\\Users\\zx\\Desktop\\polymech\\library.polymech\\app-config.json for locale en"}
{"level":"INFO","time":"2025-12-29T22:54:22.627Z","pid":27916,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from ./app-config.json for locale en"}
{"level":"INFO","time":"2025-12-29T22:56:14.003Z","pid":27916,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from C:\\Users\\zx\\Desktop\\polymech\\library.polymech\\app-config.json for locale es"}
{"level":"INFO","time":"2025-12-29T23:03:57.474Z","pid":27916,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from C:\\Users\\zx\\Desktop\\polymech\\library.polymech\\app-config.json for locale en"}
{"level":"INFO","time":"2025-12-29T23:11:40.022Z","pid":18684,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from C:\\Users\\zx\\Desktop\\polymech\\library.polymech\\app-config.json for locale en"}
{"level":"INFO","time":"2025-12-29T23:11:40.915Z","pid":18684,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from ./app-config.json for locale en"}
{"level":"INFO","time":"2025-12-29T23:11:55.964Z","pid":28160,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from C:\\Users\\zx\\Desktop\\polymech\\library.polymech\\app-config.json for locale en"}
{"level":"INFO","time":"2025-12-29T23:11:59.947Z","pid":28160,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from C:\\Users\\zx\\Desktop\\polymech\\library.polymech\\app-config.json for locale en"}
{"level":"INFO","time":"2025-12-29T23:12:01.708Z","pid":28160,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from C:\\Users\\zx\\Desktop\\polymech\\library.polymech\\app-config.json for locale en"}
{"level":"INFO","time":"2025-12-29T23:12:01.728Z","pid":28160,"hostname":"DESKTOP-OL563U1","msg":"Loading library config from ./app-config.json for locale en"}

View File

@ -1,24 +0,0 @@
{
"main": [
{
"name": "facebook",
"icon": "FaFacebookF",
"link": "https://www.facebook.com/themefisher"
},
{
"name": "twitter",
"icon": "FaXTwitter",
"link": "https://x.com/themefisher"
},
{
"name": "linkedin",
"icon": "FaLinkedinIn",
"link": "https://bd.linkedin.com/company/themefisher"
},
{
"name": "github",
"icon": "FaGithub",
"link": "https://github.com/themefisher/astrofront"
}
]
}

View File

@ -1,44 +0,0 @@
{
"colors": {
"default": {
"theme_color": {
"primary": "#121212",
"body": "#fff",
"border": "#eaeaea",
"theme_light": "#f2f2f2",
"theme_dark": "#000"
},
"text_color": {
"default": "#444",
"dark": "#000",
"light": "#666"
}
},
"darkmode": {
"theme_color": {
"primary": "#fff",
"body": "#252525",
"border": "#3E3E3E",
"theme_light": "#222222",
"theme_dark": "#000"
},
"text_color": {
"default": "#DDD",
"dark": "#fff",
"light": "#DDD"
}
}
},
"fonts": {
"font_family": {
"primary": "Karla:wght@400;500;700",
"primary_type": "sans-serif",
"secondary": "",
"secondary_type": ""
},
"font_size": {
"base": "16",
"scale": "1.2"
}
}
}

View File

@ -0,0 +1,552 @@
---
pubDate: 2024-12-19
title: FileTree Component
author: PolyMech Team
description: "Complete documentation for the FileTree component with glob patterns and clickable file links"
image:
url: "https://fastly.picsum.photos/id/972/200/300.jpg?hmac=UMf5f6BV9GkLiz0Xz9kMwm1riiTtlpIG2jt0WrxZ51Q?grayscale"
alt: "FileTree component documentation"
tags: ["component", "filetree", "documentation", "glob", "navigation"]
sidebar:
label: "FileTree Guide"
items:
- label: "Overview"
href: "#filetree-component"
- label: "Basic Usage"
href: "#basic-usage"
- label: "Glob Patterns"
href: "#glob-pattern-support"
- label: "Clickable Links"
href: "#clickable-file-links"
- label: "Configuration"
href: "#configuration-options"
- label: "Examples"
href: "#comprehensive-examples"
- label: "Integration"
href: "#integration-examples"
---
import FileTree from "@polymech/astro-base/components/FileTree.astro";
# FileTree Component
The FileTree component displays hierarchical file and directory structures with automatic discovery via glob patterns and clickable file links. It's perfect for documentation, code exploration, and project navigation.
## Key Features
- 🔍 **Auto-Discovery**: Use glob patterns to automatically generate file trees
- 🔗 **Clickable Links**: Files link to editors, repositories, or file system
- 🖼️ **Thumbnail View**: Windows Explorer-style grid with image previews
- 🎯 **Smart Filtering**: Control depth, hidden files, and exclusions
- 🎨 **Icon Support**: Automatic file type icons
- 📱 **Responsive**: Works on all screen sizes
- ⚡ **Fast**: Efficient file system scanning
## Basic Usage
### Manual File Tree
The traditional way to create file trees by manually typing the structure:
<FileTree>
- src/
- components/
- **Header.astro** Main header component
- Footer.astro
- Navigation.astro
- layouts/
- Layout.astro
- pages/
- index.astro
- about.astro
- package.json
- README.md
</FileTree>
```jsx
<FileTree>
- src/
- components/
- **Header.astro** Main header component
- Footer.astro
- layouts/
- Layout.astro
- package.json
</FileTree>
```
## Glob Pattern Support
### Auto-Generated Trees
Instead of manually typing file structures, use glob patterns to automatically discover and display files:
<FileTree glob="../**/*.{md,mdx}" maxDepth={2} />
```jsx
<FileTree glob="../**/*.{md,mdx}" maxDepth={2} />
```
### Current Directory Files
<FileTree glob="./*" />
```jsx
<FileTree glob="./*" />
```
### TypeScript Files Only
<FileTree glob="../**/*.ts" maxDepth={3} exclude={["node_modules", "dist"]} />
```jsx
<FileTree glob="../**/*.ts" maxDepth={3} exclude={["node_modules", "dist"]} />
```
## Thumbnail View
### Windows Explorer Style
Perfect for browsing images and visual content:
<FileTree
glob="../public/images/**/*.{jpg,jpeg,png,gif,webp,svg}"
view="thumbs"
thumbSize="medium"
maxDepth={2}
/>
```jsx
<FileTree
glob="../public/images/**/*.{jpg,jpeg,png,gif,webp,svg}"
view="thumbs"
thumbSize="medium"
maxDepth={2}
/>
```
### Different Thumbnail Sizes
Small thumbnails with mixed file types:
<FileTree
glob="../src/**/*.{ts,astro,json}"
view="thumbs"
thumbSize="small"
maxDepth={2}
/>
Large thumbnails for detailed preview:
<FileTree
glob="../public/images/**/*.{jpg,jpeg,png}"
view="thumbs"
thumbSize="large"
maxDepth={1}
/>
### File Type Icons in Thumbnails
Shows different icons for different file types with **imagetools integration**:
<FileTree
glob="../**/*.{md,ts,js,json,astro,vue,jsx}"
view="thumbs"
thumbSize="medium"
maxDepth={1}
/>
### Image Optimization Features
Thanks to imagetools integration, thumbnails include:
- **AVIF Format**: Modern, efficient image format
- **Blurred Placeholders**: Smooth loading experience
- **Responsive Sizing**: Automatic width generation
- **Lazy Loading**: Performance optimization
- **Aspect Ratio**: Consistent square thumbnails
```jsx
// Small thumbnails (80px)
<FileTree view="thumbs" thumbSize="small" />
// Medium thumbnails (120px) - default
<FileTree view="thumbs" thumbSize="medium" />
// Large thumbnails (160px)
<FileTree view="thumbs" thumbSize="large" />
```
## Clickable File Links
Files in auto-generated trees are clickable by default, supporting multiple link types:
### Default (File System)
<FileTree glob="../src/components/polymech/**/*.{ts,astro}" maxDepth={2} />
### VS Code Integration
Click files to open directly in VS Code:
<FileTree
glob="../src/components/polymech/**/*.astro"
maxDepth={1}
urlPrefix="vscode://file"
/>
```jsx
<FileTree
glob="../src/components/polymech/**/*.astro"
urlPrefix="vscode://file"
/>
```
### GitHub Repository Links
<FileTree
glob="../**/*.json"
maxDepth={1}
urlPrefix="https://github.com/username/repo/blob/main"
/>
```jsx
<FileTree
glob="../**/*.json"
urlPrefix="https://github.com/username/repo/blob/main"
/>
```
### Links Disabled
<FileTree
glob="../src/components/polymech/**/*.ts"
maxDepth={1}
linkFiles={false}
/>
```jsx
<FileTree
glob="../src/components/polymech/**/*.ts"
linkFiles={false}
/>
```
## Configuration Options
### Props Interface
```typescript
interface Props {
glob?: string; // Glob pattern to auto-generate file tree
maxDepth?: number; // Maximum directory depth (default: 5)
showHidden?: boolean; // Show hidden files starting with . (default: false)
exclude?: string[]; // Patterns to exclude (default: [])
urlPrefix?: string; // URL prefix for file links (auto-detected)
linkFiles?: boolean; // Whether to make files clickable (default: true)
view?: 'tree' | 'thumbs'; // Display mode (default: 'tree')
thumbSize?: 'small' | 'medium' | 'large'; // Thumbnail size (default: 'medium')
}
```
### Glob Patterns
| Pattern | Description | Example |
|---------|-------------|---------|
| `**/*` | All files recursively | `../src/**/*` |
| `*.ext` | Files with specific extension | `../**/*.ts` |
| `{a,b}` | Multiple extensions | `../**/*.{js,ts}` |
| `**/dir/**` | Files in specific directory | `**/components/**/*` |
| `!pattern` | Exclude pattern | Use `exclude` prop instead |
### URL Prefix Types
| Type | Prefix | Description |
|------|--------|-------------|
| **VS Code** | `vscode://file` | Opens files in VS Code editor |
| **GitHub** | `https://github.com/user/repo/blob/main` | Links to GitHub repository |
| **GitLab** | `https://gitlab.com/user/repo/-/blob/main` | Links to GitLab repository |
| **File System** | `file://` | Opens local files in system |
| **Custom** | `https://your-viewer.com` | Custom file viewer |
| **Default** | Auto-detected | Uses current dev server |
## Comprehensive Examples
### Development Workflow
Show project structure with VS Code integration:
<FileTree
glob="../src/**/*.{astro,ts,js}"
maxDepth={3}
exclude={["node_modules", ".git", "dist", "build"]}
urlPrefix="vscode://file"
/>
```jsx
<FileTree
glob="../src/**/*.{astro,ts,js}"
maxDepth={3}
exclude={["node_modules", ".git", "dist", "build"]}
urlPrefix="vscode://file"
/>
```
### Documentation Files
<FileTree
glob="../**/*.{md,mdx}"
maxDepth={2}
urlPrefix="https://github.com/yourorg/yourrepo/blob/main"
/>
```jsx
<FileTree
glob="../**/*.{md,mdx}"
maxDepth={2}
urlPrefix="https://github.com/yourorg/yourrepo/blob/main"
/>
```
### Configuration Files
<FileTree
glob="../**/*.{json,yaml,yml,toml,config.js,config.ts}"
maxDepth={2}
/>
```jsx
<FileTree
glob="../**/*.{json,yaml,yml,toml,config.js,config.ts}"
maxDepth={2}
/>
```
### Show Hidden Files
<FileTree
glob="../**/*"
maxDepth={2}
showHidden={true}
exclude={["node_modules"]}
/>
```jsx
<FileTree
glob="../**/*"
maxDepth={2}
showHidden={true}
exclude={["node_modules"]}
/>
```
## Integration Examples
### With Astro Projects
```jsx
// Show Astro project structure
<FileTree
glob="../src/**/*.astro"
maxDepth={3}
urlPrefix="vscode://file"
/>
// Show content collections
<FileTree
glob="../src/content/**/*.{md,mdx}"
maxDepth={2}
/>
```
### With React/Vue Projects
```jsx
// Show component files
<FileTree
glob="../src/**/*.{jsx,tsx,vue}"
maxDepth={3}
exclude={["node_modules", "dist"]}
/>
```
### With Documentation Sites
```jsx
// Link to GitHub for editing
<FileTree
glob="../docs/**/*.md"
urlPrefix="https://github.com/yourorg/docs/edit/main"
maxDepth={2}
/>
```
### Custom File Viewer
```jsx
// Link to custom file viewer API
<FileTree
glob="../**/*.log"
urlPrefix="https://yourapp.com/file-viewer"
maxDepth={1}
/>
```
## Advanced Features
### File Type Icons & Modern Link Styling
The FileTree automatically displays appropriate icons and uses subtle, modern link styling:
**File Icons:**
- 📄 `.md`, `.mdx` - Markdown files
- 🟦 `.ts`, `.tsx` - TypeScript files
- 🟨 `.js`, `.jsx` - JavaScript files
- 🎨 `.astro` - Astro components
- ⚙️ `.json`, `.yaml` - Configuration files
- 📁 Directories with gold folder icons
**Link Styling Best Practices:**
- **Subtle Colors**: No aggressive blue links - uses content text color
- **Background Hover**: Gentle background highlight on hover instead of color change
- **Subtle Underline**: Thin, muted underline appears on hover
- **Clickable Indicators**: Small dots on thumbnails indicate clickable items
- **Accessibility**: Proper focus states and keyboard navigation
- **Consistent**: Same styling approach across tree and thumbnail views
### Responsive Design
The FileTree adapts to different screen sizes:
- Desktop: Full tree with hover effects
- Mobile: Collapsible directories
- Touch-friendly click targets
### Performance Optimized
- Efficient file system scanning
- Lazy directory expansion
- Cached glob results
- Minimal DOM updates
## Best Practices
### 1. Use Appropriate Depth Limits
```jsx
// Good - reasonable depth
<FileTree glob="../src/**/*" maxDepth={3} />
// Avoid - too deep, slow performance
<FileTree glob="../**/*" maxDepth={10} />
```
### 2. Exclude Unnecessary Directories
```jsx
// Good - exclude build artifacts
<FileTree
glob="../**/*"
exclude={["node_modules", ".git", "dist", "build", ".cache"]}
/>
```
### 3. Use Specific Patterns
```jsx
// Good - specific file types
<FileTree glob="../src/**/*.{astro,ts}" />
// Less efficient - too broad
<FileTree glob="../**/*" />
```
### 4. Choose Appropriate URL Prefixes
```jsx
// Development - VS Code
<FileTree urlPrefix="vscode://file" />
// Documentation - GitHub
<FileTree urlPrefix="https://github.com/user/repo/blob/main" />
// Local browsing - file system
<FileTree urlPrefix="file://" />
```
## Troubleshooting
### No Files Found
If your FileTree shows "No files found", the error message now includes debugging information:
```
No files found matching pattern: ./gallery/*.jpg
Searched in: /full/path/to/src/content/resources
```
This helps you verify:
1. **Pattern Syntax**: Check if your glob pattern is correct
2. **Search Location**: Verify the absolute path is where you expect
3. **File Existence**: Confirm files actually exist in the searched directory
4. **Exclude Patterns**: Check if exclude patterns aren't too broad
### Debug Examples
<FileTree
glob="./non-existent/*.jpg"
view="thumbs"
thumbSize="small"
/>
<FileTree
glob="./missing-dir/**/*.png"
view="tree"
maxDepth={2}
/>
### Links Not Working
If file links don't work:
1. Check the `urlPrefix` is correct for your environment
2. Verify the protocol is supported by your system
3. For VS Code links, ensure VS Code is installed
4. For repository links, check the URL format
### Performance Issues
If FileTree is slow:
1. Reduce `maxDepth` value
2. Use more specific glob patterns
3. Add more items to `exclude` array
4. Consider using `linkFiles={false}` for display-only trees
## Migration Guide
### From Manual Trees
Replace manual file listings:
```jsx
// Old way
<FileTree>
- src/
- components/
- Header.astro
- Footer.astro
</FileTree>
// New way
<FileTree glob="../src/components/**/*.astro" />
```
### From Other File Tree Components
The FileTree component is compatible with standard markdown file tree syntax, making migration straightforward.
---
The FileTree component transforms static file documentation into interactive, always-up-to-date navigation tools. Perfect for project documentation, code exploration, and development workflows!

View File

@ -0,0 +1,492 @@
---
pubDate: 2024-12-19
title: MasonryGallery Component
author: Development Team
description: "Complete guide to the MasonryGallery component - a Pinterest-style masonry layout with lightbox functionality, glob support, and responsive design."
image:
url: "https://fastly.picsum.photos/id/972/200/300.jpg?hmac=UMf5f6BV9GkLiz0Xz9kMwm1riiTtlpIG2jt0WrxZ51Q?nature"
alt: "Masonry gallery preview"
tags: ["masonry", "gallery", "images", "component", "responsive"]
sidebar:
label: "Navigation"
items:
- label: "Overview"
href: "#masonrygallery-component"
- label: "Live Examples"
href: "#live-examples"
- label: "Basic Usage"
href: "#basic-usage"
- label: "Advanced Features"
href: "#advanced-configuration"
- label: "API Reference"
href: "#api-reference"
- label: "Best Practices"
href: "#best-practices"
---
import MasonryGallery from "@polymech/astro-base/components/MasonryGallery.astro";
# MasonryGallery Component
A beautiful Pinterest-style masonry gallery component with lightbox functionality, glob pattern support, and configurable constraints. Perfect for showcasing image collections with natural, flowing layouts.
## Key Features
- **📐 Masonry Layout**: CSS Grid-based masonry with no fixed height - images flow naturally
- **🖼️ Lightbox**: Full lightbox with swipe support and keyboard navigation
- **🔍 Glob Support**: Auto-load images using patterns like `*.jpg`, `**/*.{jpg,png}`
- **📏 Size Constraints**: Configure `maxItems`, `maxWidth`, and `maxHeight`
- **📱 Responsive**: Adapts seamlessly to mobile, tablet, and desktop screens
- **🏷️ Metadata Support**: Companion `.json` and `.md` files for rich image metadata
- **⚡ Performance**: Lazy loading and optimized image formats (AVIF, WebP)
- **🎨 Customizable**: Full control over gallery and lightbox settings
- **📅 Flexible Grouping**: Optional grouping by year, month, or custom functions with EXIF date extraction
## Live Examples
### Default Masonry Layout
Auto-loads images from the gallery directory with balanced sizing:
<MasonryGallery
glob="./gallery/*.jpg"
maxItems={10}
maxWidth="150px"
maxHeight="500px"
groupBy="groupByYear"
gallerySettings={{
SHOW_TITLE: false,
SHOW_DESCRIPTION: false,
SIZES_REGULAR: "(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
}}
lightboxSettings={{
SHOW_TITLE: true,
SHOW_DESCRIPTION: true,
SIZES_LARGE: "90vw"
}}
/>
### Compact Grid
Perfect for thumbnails and preview galleries:
<MasonryGallery
glob="./gallery/*.jpg"
maxItems={10}
maxWidth="250px"
maxHeight="300px"
gallerySettings={{
SHOW_TITLE: false,
SHOW_DESCRIPTION: false
}}
/>
### Large Format Display
Ideal for portfolio and showcase galleries:
<MasonryGallery
glob="./gallery/*.jpg"
maxItems={10}
maxWidth="450px"
maxHeight="600px"
gallerySettings={{
SHOW_TITLE: true,
SHOW_DESCRIPTION: true
}}
/>
### Mobile-Optimized
Responsive design that works beautifully on all devices:
<MasonryGallery
glob="./gallery/*.jpg"
maxItems={10}
maxWidth="280px"
maxHeight="350px"
gallerySettings={{
SHOW_TITLE: false,
SHOW_DESCRIPTION: false,
SIZES_REGULAR: "(max-width: 480px) 100vw, (max-width: 768px) 50vw, 33vw"
}}
/>
## Basic Usage
### Simple Glob Pattern
```jsx
// Auto-load all JPG images with default settings
<MasonryGallery
glob="./gallery/*.jpg"
maxItems={10}
/>
```
### With Size Constraints
```jsx
// Control maximum dimensions and item count
<MasonryGallery
glob="./images/*.{jpg,png,webp}"
maxItems={10}
maxWidth="300px"
maxHeight="400px"
/>
```
### No Grouping (Default)
```jsx
// Simple masonry layout without any grouping
<MasonryGallery
glob="./gallery/*.jpg"
maxItems={10}
maxWidth="280px"
maxHeight="350px"
/>
```
### Group by Year
```jsx
// Group images by year with year headers
<MasonryGallery
glob="./gallery/*.jpg"
maxItems={10}
groupBy="groupByYear"
maxWidth="280px"
maxHeight="350px"
/>
```
### Group by Month
```jsx
// Group images by month with month/year headers
<MasonryGallery
glob="./gallery/*.jpg"
maxItems={10}
groupBy="groupByMonth"
maxWidth="280px"
maxHeight="350px"
/>
```
### Subdirectory Patterns
```jsx
// Load from nested directories
<MasonryGallery
glob="./portfolio/**/*.jpg"
maxItems={10}
maxWidth="350px"
maxHeight="500px"
/>
```
## Advanced Configuration
### Custom Gallery Settings
```jsx
<MasonryGallery
glob="./showcase/*.jpg"
maxItems={10}
maxWidth="400px"
maxHeight="600px"
gallerySettings={{
SHOW_TITLE: true,
SHOW_DESCRIPTION: true,
SIZES_REGULAR: "(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw",
SIZES_THUMB: "200px",
SIZES_LARGE: "800px"
}}
/>
```
### Lightbox Customization
```jsx
<MasonryGallery
glob="./photos/*.jpg"
maxItems={10}
lightboxSettings={{
SHOW_TITLE: true,
SHOW_DESCRIPTION: false,
SIZES_LARGE: "95vw"
}}
/>
```
### Custom Grouping Function
```jsx
// Create a custom grouping function
const groupByFileSize = (image) => {
// This would need to be implemented to get actual file size
// For demonstration purposes, we'll group by a mock size category
const mockSize = Math.random() > 0.5 ? 'large' : 'small';
return {
key: mockSize,
label: mockSize === 'large' ? 'Large Images' : 'Small Images',
sortOrder: mockSize === 'large' ? 1 : 0
};
};
<MasonryGallery
glob="./portfolio/*.jpg"
maxItems={10}
groupBy={groupByFileSize}
maxWidth="320px"
maxHeight="400px"
gallerySettings={{
SHOW_TITLE: true,
SHOW_DESCRIPTION: false
}}
/>
```
### No Grouping for Clean Layout
```jsx
// For a clean, simple layout without any organization headers
<MasonryGallery
glob="./portfolio/*.jpg"
maxItems={10}
maxWidth="320px"
maxHeight="400px"
gallerySettings={{
SHOW_TITLE: true,
SHOW_DESCRIPTION: false
}}
/>
```
### Manual Images with Glob
```jsx
// Combine manual images with auto-loaded ones
const featuredImages = [
{
src: "./featured/hero.jpg",
alt: "Hero image",
title: "Featured Photo",
description: "Our most popular image"
}
];
<MasonryGallery
images={featuredImages}
glob="./gallery/*.jpg"
maxItems={10}
maxWidth="350px"
maxHeight="500px"
/>
```
## Grouping Options
The `groupBy` prop provides flexible ways to organize your images:
### Predefined Grouping Functions
- **`null` (default)**: No grouping - displays images in a simple masonry layout
- **`"groupByYear"`**: Groups images by year based on EXIF date or file modification time
- **`"groupByMonth"`**: Groups images by month and year (e.g., "January 2024", "February 2024")
### Custom Grouping Functions
You can also provide a custom function that takes an image and returns a `GroupInfo` object:
```jsx
const customGroupFunction = (image) => ({
key: 'unique-group-key', // Used for internal grouping
label: 'Display Label', // Shown as the group header
sortOrder: 123 // Numeric value for sorting (higher = shown first)
});
```
## API Reference
### Props
```typescript
type GroupByFunction = (image: Image) => GroupInfo;
interface Props {
images?: Image[]; // Manual image array
glob?: string; // Glob pattern for auto-loading
maxItems?: number; // Maximum number of images (default: 50)
maxWidth?: string; // Max width per image (default: "300px")
maxHeight?: string; // Max height per image (default: "400px")
entryPath?: string; // Content entry path for resolving relative images
groupBy?: GroupByFunction | 'groupByYear' | 'groupByMonth' | null; // Grouping strategy (default: null = no grouping)
gallerySettings?: {
SIZES_REGULAR?: string; // Responsive sizes for main images
SIZES_THUMB?: string; // Responsive sizes for thumbnails
SIZES_LARGE?: string; // Responsive sizes for lightbox
SHOW_TITLE?: boolean; // Show image titles
SHOW_DESCRIPTION?: boolean; // Show image descriptions
};
lightboxSettings?: {
SIZES_REGULAR?: string;
SIZES_THUMB?: string;
SIZES_LARGE?: string;
SHOW_TITLE?: boolean;
SHOW_DESCRIPTION?: boolean;
};
}
interface GroupInfo {
key: string; // Unique identifier for the group
label: string; // Display label for the group
sortOrder: number; // Numeric value for sorting groups
}
```
### Image Interface
```typescript
interface Image {
src: string; // Image source URL
alt: string; // Alt text for accessibility
title?: string; // Optional title
description?: string; // Optional description
}
```
## Metadata Support
Enhance your images with companion metadata files:
### JSON Metadata (`image.json`)
```json
{
"alt": "Beautiful mountain landscape at sunset",
"title": "Mountain Sunset",
"description": "A breathtaking view of mountains during golden hour"
}
```
### Markdown Metadata (`image.md`)
```markdown
A detailed description of the image that can include **markdown formatting**.
This will be used as the description if no JSON description is provided.
```
## Responsive Behavior
The MasonryGallery automatically adapts to different screen sizes:
- **Desktop (1024px+)**: Minimum 250px columns with auto-fill
- **Tablet (768px-1023px)**: Minimum 200px columns
- **Mobile (480px-767px)**: Minimum 150px columns
- **Small Mobile (&lt;480px)**: Single column layout
## Interactive Controls
### Keyboard Navigation (Lightbox)
- **Escape**: Close lightbox
- **Arrow Left**: Previous image
- **Arrow Right**: Next image
### Touch Controls (Lightbox)
- **Swipe Left**: Next image
- **Swipe Right**: Previous image
- **Tap**: Close lightbox (outside image)
## Best Practices
### Performance Optimization
```jsx
// Use appropriate sizing for your use case
<MasonryGallery
glob="./thumbnails/*.jpg"
maxItems={10} // Limit items for performance
maxWidth="250px" // Smaller for faster loading
maxHeight="300px"
gallerySettings={{
SIZES_REGULAR: "(max-width: 640px) 250px, (max-width: 1024px) 300px, 350px"
}}
/>
```
### Accessibility
```jsx
// Always provide meaningful alt text
const images = [
{
src: "./photo.jpg",
alt: "Person hiking on mountain trail during sunrise",
title: "Morning Hike"
}
];
```
### Content Organization
```jsx
// Organize images in logical directories
<MasonryGallery glob="./projects/web-design/*.jpg" /> // Web projects
<MasonryGallery glob="./projects/photography/*.jpg" /> // Photography
<MasonryGallery glob="./projects/illustrations/*.jpg" /> // Illustrations
```
### Loading Strategy
```jsx
// For above-the-fold galleries, consider smaller maxItems
<MasonryGallery
glob="./hero-gallery/*.jpg"
maxItems={10} // Load fewer images initially
maxWidth="400px"
maxHeight="500px"
/>
```
## CSS Classes
The component uses these CSS classes for styling customization:
- `.masonry-gallery`: Main container
- `.masonry-container`: Grid container
- `.masonry-item`: Individual image container
- `.line-clamp-2`: Text truncation utility
## Browser Support
- **Modern browsers**: Full CSS Grid masonry support
- **Fallback**: Graceful degradation for older browsers
- **Progressive enhancement**: Touch and swipe support where available
- **Accessibility**: Full ARIA support and keyboard navigation
## Troubleshooting
### Images Not Loading
1. Check that your glob pattern matches actual files
2. Ensure images are in the correct directory relative to the MDX file
3. Verify file extensions match your glob pattern
### Performance Issues
1. Reduce `maxItems` for better initial load times
2. Use appropriate `maxWidth` and `maxHeight` values
3. Consider using smaller image formats (WebP, AVIF)
### Layout Issues
1. Ensure your images have reasonable aspect ratios
2. Check that `maxWidth` and `maxHeight` values work well together
3. Test on different screen sizes for responsive behavior

View File

@ -0,0 +1,148 @@
---
pubDate: 2024-12-18
title: Building Modern Websites with Astro
author: Jane Developer
description: "Learn how to create fast, content-focused websites using Astro's innovative approach to web development."
url_0: "https://images.unsplash.com/photo-1555066931-4365d14bab8c?w=800&h=400&fit=crop"
image:
url: "https://fastly.picsum.photos/id/972/200/300.jpg?hmac=UMf5f6BV9GkLiz0Xz9kMwm1riiTtlpIG2jt0WrxZ51Q?grayscale"
alt: "Astro development workspace"
tags: ["astro", "javascript", "ssr", "web-development"]
---
import { Code } from 'astro:components';
# Building Modern Websites with Astro
Astro is revolutionizing how we build websites by combining the best of static site generation with modern web development practices. Let's explore what makes Astro special and how you can leverage it for your next project.
## What Makes Astro Different?
### Zero JS by Default
Astro ships **zero JavaScript** to the browser by default. Components are rendered to HTML at build time, resulting in incredibly fast loading pages.
```astro
---
// This JavaScript runs at build time
const greeting = "Hello, Astro!"
const items = ['Fast', 'Flexible', 'Developer-friendly']
---
<h1>{greeting}</h1>
<ul>
{items.map(item => <li>{item}</li>)}
</ul>
```
### Component Islands
When you do need interactivity, Astro's "Islands Architecture" lets you selectively hydrate components:
<Code code={`---
// ButtonCounter.tsx (React component)
import { useState } from 'react';
export default function ButtonCounter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}
---
<!-- In your .astro file -->
<ButtonCounter client:load />
`} lang="astro" title="Interactive Component" />
## Key Features
### 🚀 Performance First
- **Partial Hydration**: Only interactive components load JavaScript
- **Optimized Builds**: Tree-shaking, bundling, and minification out of the box
- **Image Optimization**: Built-in image processing and optimization
### 🧩 Framework Agnostic
Use your favorite framework - or mix and match:
```astro
---
import ReactComponent from './ReactComponent.tsx';
import VueComponent from './VueComponent.vue';
import SvelteComponent from './SvelteComponent.svelte';
---
<div>
<ReactComponent client:visible />
<VueComponent client:idle />
<SvelteComponent client:media="(max-width: 768px)" />
</div>
```
### 📝 Content Collections
Organize your content with type-safe collections:
```typescript
// content.config.ts
import { defineCollection, z } from 'astro:content';
const blog = defineCollection({
schema: z.object({
title: z.string(),
pubDate: z.date(),
author: z.string(),
tags: z.array(z.string()),
}),
});
export const collections = { blog };
```
## Advanced Patterns
### Dynamic Routing
Create dynamic pages with ease:
```astro
---
// pages/blog/[...slug].astro
export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map(post => ({
params: { slug: post.slug },
props: { post },
}));
}
---
```
### API Routes
Build full-stack applications:
```typescript
// pages/api/posts.ts
export async function GET() {
const posts = await getCollection('blog');
return new Response(JSON.stringify(posts), {
headers: { 'Content-Type': 'application/json' }
});
}
```
## Best Practices
1. **Start Static**: Begin with static content and add interactivity where needed
2. **Use Content Collections**: Organize your content with schemas for type safety
3. **Optimize Images**: Leverage Astro's built-in image optimization
4. **Progressive Enhancement**: Add JavaScript only when necessary
## Conclusion
Astro represents a paradigm shift towards **content-first web development**. By shipping less JavaScript and focusing on performance, it enables developers to create fast, accessible websites without sacrificing developer experience.
Whether you're building a blog, documentation site, or e-commerce platform, Astro provides the tools and performance you need to succeed in the modern web landscape.
---
**Ready to get started?** Check out the [official Astro documentation](https://docs.astro.build) and start building today!

View File

@ -0,0 +1,468 @@
---
title: "Collection Filter System"
description: "Complete guide to the generic collection filtering system for Astro content collections"
author: "Polymech Team"
pubDate: 2024-01-15
tags: ["internal", "documentation", "astro", "collections", "filters"]
---
# Collection Filter System
This document describes the generic collection filtering system implemented for Astro content collections. The system provides a unified way to filter collection entries across the application, ensuring consistency between pages and sidebar generation.
## Overview
The collection filter system replaces manual filtering in `getStaticPaths` functions with a configurable, reusable approach. It automatically excludes invalid entries like those with "Untitled" titles, draft content, folders, and other unwanted items.
## Core Components
### 1. Filter Functions (`polymech/src/base/collections.ts`)
#### Basic Filters
```typescript
// Default filters applied automatically
export const hasValidFrontMatter: CollectionFilter
export const isNotFolder: CollectionFilter
export const isNotDraft: CollectionFilter
export const hasTitle: CollectionFilter // Excludes "Untitled" entries
// Content validation filters
export const hasBody: CollectionFilter
export const hasDescription: CollectionFilter
export const hasImage: CollectionFilter
export const hasAuthor: CollectionFilter // Excludes "Unknown" authors
export const hasPubDate: CollectionFilter
export const hasTags: CollectionFilter
export const hasValidFileExtension: CollectionFilter // .md/.mdx only
```
#### Advanced Filters
```typescript
// Date-based filtering
export const isNotFuture: CollectionFilter
export const createDateFilter(beforeDate?: Date, afterDate?: Date): CollectionFilter
export const createOldPostFilter(cutoffDays: number): CollectionFilter
// Tag-based filtering
export const createTagFilter(requiredTags: string[], matchAll?: boolean): CollectionFilter
export const createExcludeTagsFilter(excludeTags: string[]): CollectionFilter
// Field validation
export const createRequiredFieldsFilter(requiredFields: string[]): CollectionFilter
export const createFrontmatterValidator(validator: (data: any) => boolean): CollectionFilter
```
### 2. Main Filter Functions
```typescript
// Apply filters to a collection
export function filterCollection<T>(
collection: CollectionEntry<T>[],
filters: CollectionFilter<T>[] = defaultFilters,
astroConfig?: any
): CollectionEntry<T>[]
// Apply filters based on configuration
export function filterCollectionWithConfig<T>(
collection: CollectionEntry<T>[],
config: CollectionFilterConfig,
astroConfig?: any
): CollectionEntry<T>[]
```
### 3. Central Configuration (`site2/src/app/config.ts`)
The collection filter system is centrally configured in `site2/src/app/config.ts`. This is the main configuration file where you control all filtering behavior across your application.
**Key Configuration Location: `site2/src/app/config.ts`**
```typescript
/////////////////////////////////////////////
//
// Collection Filters
// Collection filter configuration
export const COLLECTION_FILTERS = {
// Core filters (enabled by default)
ENABLE_VALID_FRONTMATTER_CHECK: true,
ENABLE_FOLDER_FILTER: true,
ENABLE_DRAFT_FILTER: true,
ENABLE_TITLE_FILTER: true, // Filters out "Untitled" entries
// Content validation filters (disabled by default)
ENABLE_BODY_FILTER: false, // Require entries to have body content
ENABLE_DESCRIPTION_FILTER: false, // Require entries to have descriptions
ENABLE_IMAGE_FILTER: false, // Require entries to have images
ENABLE_AUTHOR_FILTER: false, // Require entries to have real authors (not "Unknown")
ENABLE_PUBDATE_FILTER: false, // Require entries to have valid publication dates
ENABLE_TAGS_FILTER: false, // Require entries to have tags
ENABLE_FILE_EXTENSION_FILTER: true, // Require valid .md/.mdx extensions
// Advanced filtering
REQUIRED_FIELDS: [], // Array of required frontmatter fields
REQUIRED_TAGS: [], // Array of required tags
EXCLUDE_TAGS: [], // Array of tags to exclude
// Date filtering
FILTER_FUTURE_POSTS: false, // Filter out posts with future publication dates
FILTER_OLD_POSTS: false, // Filter out posts older than a certain date
OLD_POST_CUTOFF_DAYS: 365, // Days to consider a post "old"
}
```
**Why config.ts?**
- **Centralized Control**: All filter settings in one place
- **Environment Consistency**: Same filtering rules across all pages and sidebar
- **Easy Maintenance**: Change behavior without touching individual page files
- **Type Safety**: Imported with full TypeScript support
## Configuring Filters in config.ts
### Modifying Collection Filters
To change filtering behavior across your entire application, edit the `COLLECTION_FILTERS` object in `site2/src/app/config.ts`:
```typescript
// site2/src/app/config.ts
// Example: Enable stricter content validation
export const COLLECTION_FILTERS = {
// Core filters (keep these enabled)
ENABLE_VALID_FRONTMATTER_CHECK: true,
ENABLE_FOLDER_FILTER: true,
ENABLE_DRAFT_FILTER: true,
ENABLE_TITLE_FILTER: true,
// Enable content validation
ENABLE_BODY_FILTER: true, // Require body content
ENABLE_DESCRIPTION_FILTER: true, // Require descriptions
ENABLE_AUTHOR_FILTER: true, // Require real authors
ENABLE_TAGS_FILTER: true, // Require tags
// Require specific fields
REQUIRED_FIELDS: ['title', 'description', 'pubDate'],
// Exclude test content
EXCLUDE_TAGS: ['draft', 'test', 'internal'],
// Filter future posts in production
FILTER_FUTURE_POSTS: true,
}
```
### Configuration Import
The configuration is imported in pages and components like this:
```typescript
import { COLLECTION_FILTERS } from "config/config.js"
import { filterCollectionWithConfig } from '@polymech/astro-base/base/collections';
// Apply the configured filters
const entries = filterCollectionWithConfig(allEntries, COLLECTION_FILTERS);
```
**Note**: The import path `"config/config.js"` refers to `site2/src/app/config.ts` due to Astro's import resolution.
## Usage Examples
### 1. Basic Usage in Pages
Replace manual filtering in `getStaticPaths`:
```typescript
// Before
export async function getStaticPaths() {
const resourceEntries = (await getCollection("resources")).filter(entry => {
const entryPath = `src/content/resources/${entry.id}`;
return !isFolder(entryPath);
});
}
// After
import { filterCollectionWithConfig } from '@polymech/astro-base/base/collections';
import { COLLECTION_FILTERS } from 'config/config.js';
export async function getStaticPaths() {
const allResourceEntries = await getCollection("resources");
const resourceEntries = filterCollectionWithConfig(allResourceEntries, COLLECTION_FILTERS);
}
```
### 2. Custom Filtering
```typescript
import { filterCollection, hasTitle, isNotDraft, createTagFilter } from '@polymech/astro-base/base/collections';
// Custom filter combination
const customFilters = [
hasTitle,
isNotDraft,
createTagFilter(['published'], true), // Must have 'published' tag
];
const filteredEntries = filterCollection(allEntries, customFilters);
```
### 3. Configuration-Based Filtering
```typescript
// Enable stricter content validation
const strictConfig = {
...COLLECTION_FILTERS,
ENABLE_DESCRIPTION_FILTER: true,
ENABLE_AUTHOR_FILTER: true,
ENABLE_TAGS_FILTER: true,
REQUIRED_FIELDS: ['title', 'description', 'pubDate'],
EXCLUDE_TAGS: ['draft', 'internal', 'test']
};
const entries = filterCollectionWithConfig(allEntries, strictConfig);
```
### 4. Sidebar Integration
The sidebar automatically uses the filter system:
```typescript
// Sidebar configuration in polymech/src/config/sidebar.ts
export const sidebarConfig: SidebarGroup[] = [
{
label: 'Resources',
autogenerate: {
directory: 'resources',
collapsed: true,
sortBy: 'alphabetical'
},
}
];
```
#### Advanced Sidebar Options
```typescript
import { generateLinksFromDirectoryWithConfig, createSidebarOptions } from '@polymech/astro-base/components/sidebar/utils';
// Using the new options object API
const links = await generateLinksFromDirectoryWithConfig('resources', {
maxDepth: 3,
collapsedByDefault: true,
sortBy: 'date',
filters: [hasTitle, isNotDraft, hasDescription]
});
// Using the helper function
const options = createSidebarOptions({
maxDepth: 4,
sortBy: 'custom',
customSort: (a, b) => a.label.localeCompare(b.label),
filters: customFilters
});
const links = await generateLinksFromDirectoryWithConfig('resources', options);
```
## Filter Details
### Default Filters
These filters are applied automatically unless disabled:
1. **`hasValidFrontMatter`** - Ensures entries have valid frontmatter data
2. **`isNotFolder`** - Excludes directory entries using `entry.filePath`
3. **`isNotDraft`** - Excludes entries with `draft: true`
4. **`hasTitle`** - Excludes entries with empty titles or "Untitled"
### Content Validation Filters
Enable these for stricter content requirements:
- **`hasBody`** - Requires non-empty body content
- **`hasDescription`** - Requires non-empty descriptions
- **`hasImage`** - Requires `image.url` in frontmatter
- **`hasAuthor`** - Requires real authors (not "Unknown")
- **`hasPubDate`** - Requires valid publication dates
- **`hasTags`** - Requires non-empty tags array
- **`hasValidFileExtension`** - Ensures `.md` or `.mdx` extensions
### Advanced Filtering
#### Date Filtering
```typescript
// Filter future posts
FILTER_FUTURE_POSTS: true
// Filter old posts
FILTER_OLD_POSTS: true,
OLD_POST_CUTOFF_DAYS: 365
// Custom date ranges
const recentFilter = createDateFilter(
new Date('2024-12-31'), // Before this date
new Date('2024-01-01') // After this date
);
```
#### Tag Filtering
```typescript
// Require specific tags (all must be present)
REQUIRED_TAGS: ['published', 'reviewed']
// Exclude specific tags
EXCLUDE_TAGS: ['draft', 'internal', 'test']
// Custom tag filtering
const tutorialFilter = createTagFilter(['tutorial', 'guide'], false); // At least one
const excludeTestFilter = createExcludeTagsFilter(['test', 'draft']);
```
#### Field Validation
```typescript
// Require specific frontmatter fields
REQUIRED_FIELDS: ['title', 'description', 'pubDate', 'author']
// Custom field validation
const customValidator = createFrontmatterValidator((data) => {
return data.title &&
data.description &&
data.description.length > 50 && // Min description length
Array.isArray(data.tags) &&
data.tags.length > 0;
});
```
## Frontmatter Validation
The system includes advanced frontmatter validation using Astro's `parseFrontmatter`:
```typescript
import { parseFrontmatter } from '@astrojs/markdown-remark';
// Advanced validation for raw markdown content
const rawValidator = createRawFrontmatterValidator(
(entry) => fs.readFileSync(entry.filePath, 'utf-8'),
(frontmatter) => frontmatter.published === true
);
// File-based validation using entry.filePath
const fileValidator = createFileBasedFrontmatterValidator(
(data) => data.status === 'published'
);
```
## Error Handling
The filter system includes comprehensive error handling:
```typescript
// Individual filter errors are logged but don't break the entire filtering
try {
return filter(entry, astroConfig);
} catch (error) {
console.warn(`Filter failed for entry ${entry.id}:`, error);
return false; // Exclude entry on filter error
}
```
## Performance Considerations
- **Caching**: Collection entries are cached by Astro in production
- **Early Filtering**: Apply filters as early as possible in `getStaticPaths`
- **Filter Order**: More selective filters should come first
- **Lazy Evaluation**: Filters use short-circuit evaluation
## Migration Guide
### From Manual Filtering
```typescript
// Old approach
const entries = (await getCollection("resources")).filter(entry => {
const entryPath = `src/content/resources/${entry.id}`;
return !isFolder(entryPath) && !entry.data?.draft && entry.data?.title !== 'Untitled';
});
// New approach
const entries = filterCollectionWithConfig(
await getCollection("resources"),
COLLECTION_FILTERS
);
```
### Sidebar Updates
The sidebar automatically uses the new filter system. No migration needed for basic usage.
## Best Practices
1. **Use Configuration**: Prefer `COLLECTION_FILTERS` over custom filter arrays
2. **Test Thoroughly**: Verify filtering works across all content types
3. **Document Custom Filters**: Add JSDoc comments to custom filter functions
4. **Handle Errors**: Always wrap filter logic in try-catch blocks
5. **Performance**: Use selective filters first to reduce processing
## Troubleshooting
### Common Issues
**Entries Still Showing in Sidebar**
- Ensure sidebar is using the updated `generateLinksFromDirectoryWithConfig`
- Check that filters are properly imported and configured
**Filter Not Working**
- Verify the filter function returns a boolean
- Check that the entry structure matches expected format
- Look for console warnings about filter failures
**Type Errors**
- Ensure proper imports from `@polymech/astro-base/base/collections`
- Check that custom filters match the `CollectionFilter<T>` type
### Debugging
Enable debug logging by adding console logs to custom filters:
```typescript
const debugFilter: CollectionFilter = (entry) => {
const result = hasTitle(entry);
console.log(`Filter result for ${entry.id}:`, result, entry.data?.title);
return result;
};
```
## API Reference
### Types
```typescript
export type CollectionFilter<T = any> = (entry: CollectionEntry<T>, astroConfig?: any) => boolean;
export interface CollectionFilterConfig {
ENABLE_VALID_FRONTMATTER_CHECK?: boolean;
ENABLE_FOLDER_FILTER?: boolean;
ENABLE_DRAFT_FILTER?: boolean;
ENABLE_TITLE_FILTER?: boolean;
// ... additional options
}
```
### Functions
```typescript
export function filterCollection<T>(collection, filters?, astroConfig?): CollectionEntry<T>[]
export function filterCollectionWithConfig<T>(collection, config, astroConfig?): CollectionEntry<T>[]
export function buildFiltersFromConfig<T>(config): CollectionFilter<T>[]
export function combineFilters<T>(baseFilters?, additionalFilters?): CollectionFilter<T>[]
```
## Examples Repository
For more examples and use cases, see:
- `site2/src/pages/[locale]/resources/[...slug].astro`
- `site2/src/pages/resources/[...slug].astro`
- `polymech/src/components/sidebar/utils.ts`

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 KiB

View File

@ -0,0 +1,2 @@
boops

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 480 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 KiB

View File

@ -0,0 +1,4 @@
boops md

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

View File

@ -0,0 +1,561 @@
---
pubDate: 2024-12-19
title: Sidebar Navigation System
author: System Documentation
description: "Complete guide to the custom sidebar navigation system with autogeneration, nested menus, page-level navigation, and hiding functionality."
tags: ["documentation", "sidebar", "navigation", "astro"]
sidebar:
label: "Sidebar Guide"
items:
- label: "Quick Start"
href: "#quick-start"
- label: "Configuration"
href: "#configuration"
- label: "Features"
href: "#features"
- label: "Examples"
href: "#examples"
- label: "Troubleshooting"
href: "#troubleshooting"
---
# Sidebar Navigation System
A comprehensive, lightweight sidebar navigation system built for Astro with support for autogeneration from content collections, nested menus, page-level navigation, and visibility controls.
## Quick Start
### 1. Basic Setup
The sidebar is automatically configured in `astro.config.mjs`:
```javascript
export default defineConfig({
// ... other config
sidebar: [
{
label: 'Resources',
autogenerate: { directory: 'resources' },
}
],
// ... rest of config
});
```
### 2. Using in Layouts
Apply the sidebar to any layout:
```astro
---
import Sidebar from '@/components/sidebar/Sidebar.astro';
import { getSidebarConfig } from '@/config/sidebar';
const sidebarConfig = getSidebarConfig();
const pageNavigation = frontmatter.sidebar ? [frontmatter.sidebar].flat() : [];
---
<div class="layout-with-sidebar">
<div class="sidebar-wrapper">
<Sidebar
config={sidebarConfig}
currentUrl={Astro.url}
headings={headings}
pageNavigation={pageNavigation}
/>
</div>
<main class="main-content-with-sidebar">
<slot />
</main>
</div>
```
## Configuration
### Global Sidebar Configuration
Configure the main navigation structure in `astro.config.mjs`:
```javascript
sidebar: [
// Manual navigation group
{
label: 'Guides',
items: [
{ label: 'Getting Started', slug: 'guides/getting-started' },
{ label: 'Advanced Topics', slug: 'guides/advanced' },
],
},
// Autogenerated navigation group
{
label: 'Resources',
autogenerate: {
directory: 'resources',
collapsed: false, // Subgroups open by default
maxDepth: 2 // Maximum nesting levels
},
},
]
```
### Autogeneration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `directory` | `string` | - | Content collection directory to scan |
| `collapsed` | `boolean` | `false` | Whether subgroups are collapsed by default |
| `maxDepth` | `number` | `2` | Maximum nesting levels (1-2 supported) |
## Features
### 1. Multilingual Support (i18n)
The sidebar now supports internationalization using the same i18n system as other components:
**Features:**
- All sidebar labels are translatable
- Uses the existing `Translate` component
- Supports translation keys in configuration
- Automatically adapts to current locale
**Usage:**
```javascript
// Configuration with i18n keys
export const sidebarConfig = [
{
label: 'sidebar.guides', // Translation key instead of hardcoded text
items: [
{ label: 'sidebar.example-guide', slug: 'guides/example' },
],
},
{
label: 'sidebar.resources',
autogenerate: { directory: 'resources' },
},
];
```
**Components automatically wrap labels with `<Translate>`:**
- Group titles: `<Translate>{group.label}</Translate>`
- Link labels: `<Translate>{item.label}</Translate>`
- Table of Contents: `<Translate>{title}</Translate>`
**TOC Translation Examples:**
```astro
<!-- Using default translatable title -->
<TableOfContentsWithScroll headings={headings} />
<!-- Using custom translation key -->
<TableOfContentsWithScroll
headings={headings}
title="toc.custom-title"
/>
<!-- Using hardcoded text (still works but not recommended) -->
<TableOfContentsWithScroll
headings={headings}
title="Page Contents"
/>
```
### 2. Autogenerated Navigation
Automatically creates navigation from your content collections:
```
src/content/resources/
├── getting-started.md → /resources/getting-started/
├── advanced/
│ ├── deployment.md → /resources/advanced/deployment/
│ └── optimization.md → /resources/advanced/optimization/
└── tutorials/
├── basic.mdx → /resources/tutorials/basic/
└── advanced.mdx → /resources/tutorials/advanced/
```
**Result in sidebar:**
- Resources
- Getting Started
- Advanced (collapsible group)
- Deployment
- Optimization
- Tutorials (collapsible group)
- Basic
- Advanced
### 2. Page-Level Navigation
Add custom navigation to specific pages via frontmatter:
```yaml
---
title: My Page
sidebar:
label: "Page Navigation"
items:
- label: "Quick Start"
href: "#quick-start"
- label: "Configuration"
href: "#configuration"
- label: "Examples"
href: "#examples"
---
```
**Features:**
- Appears first in the sidebar
- Visually distinguished with blue styling
- Perfect for page-specific jump links
- Supports internal anchors and external URLs
- Page-level labels are also translatable when using translation keys
### 3. Hide Pages from Navigation
Hide specific pages from autogenerated navigation:
```yaml
---
title: Hidden Page
sidebar:
hide: true
---
```
**Use cases:**
- Draft pages under development
- Landing pages accessed via specific links
- Admin or utility pages
- Pages not ready for public navigation
### 4. Table of Contents (TOC)
Automatic TOC generation with scroll-based active highlighting:
**Features:**
- Auto-generated from markdown headings
- Scroll-based active state indication
- Nested heading support
- Sticky positioning
- Mobile responsive
- Fully translatable title using translation keys
- Default title: `"toc.on-this-page"` (translatable)
- Title wrapped with `<Translate>{title}</Translate>`
### 5. Nested Directory Support
Supports up to 2 levels of nesting:
```
content/
├── page1.md → Level 1 (root)
└── category/
├── page2.md → Level 2 (in collapsible group)
└── subcategory/
└── page3.md → Level 2 (flattened with category)
```
**Notes:**
- Maximum 2 levels supported for UI clarity
- Subdirectories become collapsible groups
- Files deeper than 2 levels are flattened to level 2
- Directory names are automatically formatted and translatable
### 6. Responsive Design
**Desktop (768px+):**
- Sticky positioning
- 288px width (`w-72`)
- Always visible
**Mobile:**
- Slide-out overlay
- Backdrop blur effect
- Touch-friendly toggle button
## Examples
### Example 1: Basic Autogenerated Section
```javascript
// astro.config.mjs
{
label: 'Documentation',
autogenerate: { directory: 'docs' }
}
```
### Example 2: Collapsed Subgroups by Default
```javascript
// astro.config.mjs
{
label: 'API Reference',
autogenerate: {
directory: 'api',
collapsed: true,
maxDepth: 2
}
}
```
### Example 3: Mixed Manual and Auto Navigation
```javascript
// astro.config.mjs
sidebar: [
// Manual section
{
label: 'Getting Started',
items: [
{ label: 'Installation', slug: 'install' },
{ label: 'Quick Start', slug: 'quickstart' },
]
},
// Auto section
{
label: 'Guides',
autogenerate: { directory: 'guides' }
}
]
```
### Example 4: Page with Custom Navigation
```yaml
---
title: Complete Tutorial
description: Step-by-step guide
sidebar:
label: "Tutorial Steps"
items:
- label: "1. Setup"
href: "#setup"
- label: "2. Configuration"
href: "#configuration"
- label: "3. Deployment"
href: "#deployment"
- label: "4. Troubleshooting"
href: "#troubleshooting"
---
# Complete Tutorial
Your tutorial content here...
```
### Example 5: Hidden Development Page
```yaml
---
title: Work in Progress
description: This page is still being written
sidebar:
hide: true
---
# Work in Progress
This page won't appear in navigation but is accessible via direct URL.
```
## File Naming and URL Generation
### Clean URLs
The system automatically generates clean URLs:
| File | Generated URL |
|------|---------------|
| `getting-started.md` | `/resources/getting-started/` |
| `api/endpoints.mdx` | `/resources/api/endpoints/` |
| `tutorials/basic.md` | `/resources/tutorials/basic/` |
### Label Generation Priority
For link labels, the system checks (in order):
1. `frontmatter.title`
2. `frontmatter.page`
3. `frontmatter.name`
4. Filename (as fallback)
```yaml
---
title: "This Will Be Used" # ← Highest priority
page: "This Is Ignored"
name: "This Is Also Ignored"
---
```
## Styling and Theming
### Light Theme Design
The sidebar uses a light theme optimized for readability:
**Colors:**
- Background: `bg-gray-50`
- Borders: `border-gray-200`
- Text: `text-gray-800`
- Active links: `text-blue-700` with `bg-blue-50`
- Hover states: `hover:bg-gray-100`
### Page-Level Navigation Styling
Page-level navigation has distinct styling:
```css
.page-level {
border-bottom: 2px solid #e5e7eb;
padding-bottom: 1rem;
margin-bottom: 1.5rem;
}
.page-level .sidebar-link {
color: #1e40af;
font-weight: 500;
background-color: #f0f9ff;
border-radius: 0.375rem;
}
```
### Customization
All styles are in `src/styles/global.css` under the `@layer components` section. Key classes:
- `.sidebar-wrapper` - Main container
- `.sidebar-nav` - Navigation wrapper
- `.sidebar-group` - Group containers
- `.sidebar-link` - Individual links
- `.sidebar-link.current` - Active page styling
## Troubleshooting
### Common Issues
**1. Pages not appearing in sidebar**
- Check if the content collection exists
- Verify the directory name matches the config
- Ensure frontmatter doesn't have `sidebar.hide: true`
**2. URLs not working**
- Verify the content collection is properly configured in `src/content/config.ts`
- Check that the dynamic route file exists (e.g., `[...slug].astro`)
- Ensure clean URLs are being generated correctly
**3. Sidebar not showing**
- Check that the layout includes the sidebar components
- Verify the `getSidebarConfig()` function is imported
- Ensure proper CSS classes are applied
**4. Mobile sidebar not working**
- Check that `MobileToggle` component is included
- Verify JavaScript for mobile toggle is working
- Ensure proper z-index stacking
**5. TOC not highlighting correctly**
- Verify headings have proper `id` attributes
- Check that the `IntersectionObserver` script is loaded
- Ensure headings are being passed to the component
### Debug Tips
**1. Check console for errors:**
```javascript
// Browser dev tools console
console.log('Sidebar config:', sidebarConfig);
```
**2. Verify content collection:**
```javascript
// In Astro component
const entries = await getCollection('resources');
console.log('Found entries:', entries.length);
```
**3. Check CSS loading:**
```css
/* Add temporary styles to verify CSS is loading */
.sidebar-wrapper {
border: 2px solid red !important;
}
```
## Architecture
### File Structure
```
src/
├── components/sidebar/
│ ├── Sidebar.astro # Main sidebar component
│ ├── SidebarGroup.astro # Group/section component
│ ├── MobileToggle.astro # Mobile hamburger menu
│ ├── TableOfContents.astro # TOC component
│ ├── TableOfContentsWithScroll.astro # TOC with scroll tracking
│ ├── types.ts # TypeScript interfaces
│ └── utils.ts # Core logic and utilities
├── config/
│ └── sidebar.ts # Configuration management
├── layouts/
│ └── Resources.astro # Example layout using sidebar
└── styles/
└── global.css # All sidebar styles
```
### Key Components
**`utils.ts`** - Core functionality:
- `generateLinksFromDirectoryWithConfig()` - Autogeneration logic
- `processSidebarGroup()` - Configuration processing
- `isPageHidden()` - Hide functionality
- `createSidebarLink()` - URL and label generation
**`types.ts`** - Type definitions:
- `SidebarLink` - Individual navigation links
- `SidebarGroup` - Navigation groups/sections
- `SidebarConfig` - Overall configuration structure
**`Sidebar.astro`** - Main component orchestrating:
- Global navigation rendering
- Page-level navigation integration
- Table of contents inclusion
- Mobile responsiveness
## Performance Considerations
### Build Time
- Autogeneration happens at build time
- Content collections are cached by Astro
- Minimal impact on build performance
### Runtime
- Static navigation structure
- No client-side JavaScript for basic navigation
- TOC scroll tracking uses efficient `IntersectionObserver`
- Mobile toggle uses minimal JavaScript
### Memory Usage
- Sidebar configuration loaded once per page
- Content collection entries processed efficiently
- No large client-side bundles
## Future Enhancements
### Planned Features
- [ ] Search functionality within sidebar
- [ ] Collapsible state persistence
- [ ] Custom ordering for autogenerated items
- [ ] Multi-language support
- [ ] Custom icons for navigation items
### Extension Points
- Custom link processors in `utils.ts`
- Additional styling hooks in `global.css`
- Plugin system for custom autogeneration logic
- Integration with external navigation systems
---
*This documentation covers version 1.0 of the sidebar system. For updates and additional features, check the latest codebase.*

View File

@ -0,0 +1,587 @@
---
pubDate: 2024-12-19
title: Test MDX File
author: Test Author
description: "This is a test MDX file to verify the resources collection is working properly."
image:
url: "https://fastly.picsum.photos/id/972/200/300.jpg?hmac=UMf5f6BV9GkLiz0Xz9kMwm1riiTtlpIG2jt0WrxZ51Q?grayscale"
alt: "Test placeholder image"
tags: ["test", "mdx", "resources"]
# breadcrumb: false # Uncomment to disable breadcrumb navigation
sidebar:
label: "Page Navigation"
items:
- label: "Quick Start"
href: "#test-mdx-content"
- label: "Image Solutions"
href: "#🎯-relative-path-solution-for-imagetools"
- label: "Gallery Examples"
href: "#interactive-image-gallery"
- label: "Code Examples"
href: "#manual-usage"
- label: "Breadcrumb Info"
href: "#breadcrumb-navigation"
---
import { Img, Picture } from "imagetools/components";
import LGallery from "@polymech/astro-base/components/GalleryK.astro";
import RelativeImage from "@polymech/astro-base/components/RelativeImage.astro";
import RelativePicture from "@polymech/astro-base/components/RelativePicture.astro";
import RelativeGallery from "@polymech/astro-base/components/RelativeGallery.astro";
import FileTree from "@polymech/astro-base/components/FileTree.astro";
# Test MDX Content
This is a test MDX file with proper frontmatter. It should now appear in your resources collection.
## 🎯 Relative Path Solution for Imagetools
### ✅ NEW: Relative Paths with Custom Wrappers
<RelativeImage src="./test.jpg" alt="Test image with relative path" width={300} />
<RelativePicture src="./test.jpg" alt="Responsive relative image" widths={[600]} />
### 🔄 Two Images Side by Side (50% each)
<div class="image-row">
<RelativeImage src="./test.jpg" alt="First image" class="floating-image" />
<RelativeImage src="./test.jpg" alt="Second image" class="floating-image" />
</div>
### 🔄 Original: Public Paths (Still Work)
<Img src="/images/test.jpg" alt="Test Image from Public" width={300} />
<Picture src="/images/test.jpg" alt="Responsive Test Image" widths={[600]} />
### Different Format Generation
<Picture src="/images/test.jpg" alt="Multi-format Test Image" width={400} format={["avif", "webp", "jpg"]} />
### Quality Optimization
<Img src="/images/test.jpg" alt="Optimized Test Image" width={350} quality={85} />
## Interactive Image Gallery
### 🆕 Glob Pattern Gallery - Auto-load from Directory!
<RelativeGallery
glob="./gallery/*.jpg"
gallerySettings={{
SHOW_TITLE: true,
SHOW_DESCRIPTION: true
}}
/>
### Manual Images (Original Method)
export const galleryImages = [
{
src: "./test.jpg",
alt: "First test image",
title: "Test Image 1 (Relative)",
description: "This image uses relative path ./test.jpg"
},
{
src: "./test.jpg",
alt: "Second test image",
title: "Test Image 2 (Relative)",
description: "This image uses relative path ./test.jpg"
}
];
<RelativeGallery
images={galleryImages}
gallerySettings={{
SHOW_TITLE: true,
SHOW_DESCRIPTION: true,
SIZES_REGULAR: "w-full h-auto",
SIZES_THUMB: "w-32 h-32"
}}
lightboxSettings={{
SHOW_TITLE: true,
SHOW_DESCRIPTION: true,
SIZES_LARGE: "w-auto h-auto"
}}
/>
### 🆕 Glob Pattern Support:
<RelativeGallery
glob="./gallery/*.jpg"
gallerySettings={{ SHOW_TITLE: true }}
/>
### Manual Usage:
```jsx
import RelativeImage from "@polymech/astro-base/components/RelativeImage.astro";
<RelativeImage src="./my-image.jpg" alt="My image" width={400} />
```
## FileTree Component Example
### 🆕 Auto-Generated FileTree with Glob Patterns!
No more manually typing out file structures! Just like RelativeGallery, FileTree now supports glob patterns with **clickable file links**:
<FileTree glob="../**/*.{md,mdx,astro,ts,js,json}" maxDepth={3} />
### Specific Directory Structure (with custom URL prefix)
<FileTree
glob="../components/**/*"
maxDepth={2}
exclude={["node_modules", ".git"]}
urlPrefix="https://github.com/yourrepo/blob/main"
/>
### VS Code Integration Example
<FileTree
glob="../src/components/polymech/**/*.{ts,astro}"
maxDepth={2}
urlPrefix="vscode://file"
/>
### 🆕 Thumbnail View (Windows Explorer Style)
Perfect for browsing images and visual files with **modern, subtle link styling** (no more aggressive blue!):
<FileTree
glob="../public/images/**/*.{jpg,jpeg,png,gif,webp,svg}"
view="thumbs"
thumbSize="medium"
maxDepth={2}
/>
### Large Thumbnails for Detailed Preview
<FileTree
glob="../public/products/**/*.{jpg,jpeg,png}"
view="thumbs"
thumbSize="large"
maxDepth={1}
/>
### Small Thumbnails for Compact View
Debug example with current directory images and proper icons:
<FileTree
glob="./gallery/*"
view="thumbs"
thumbSize="medium"
linkFiles={true}
/>
Mixed content with folders and files:
<FileTree
glob="../**/*.{md,ts,json}"
view="thumbs"
thumbSize="small"
maxDepth={2}
/>
For comparison, here's a tree view of the same files:
<FileTree
glob="./*.jpg"
view="tree"
linkFiles={true}
/>
### Debug Example - Non-existent Path
This will show the "No files found" message with absolute path:
<FileTree
glob="./non-existent/*.jpg"
view="thumbs"
thumbSize="small"
/>
<FileTree
glob="./another-missing-dir/**/*.png"
view="tree"
maxDepth={2}
/>
### Manual FileTree (Original Method)
Here's an example of the FileTree component with manual structure:
<FileTree>
- public/
- images/
- logo.svg
- hero.jpg
- favicon.ico
- src/
- components/
- **Header.astro** Important component
- Footer.astro
- Navigation.astro
- layouts/
- Layout.astro
- pages/
- index.astro
- about.astro
- blog/
- [...slug].astro
- styles/
- global.css
- astro.config.mjs
- package.json
- README.md
</FileTree>
### Advanced FileTree Features
<FileTree>
- src/
- components/
- ui/
- Button.tsx React component
- Input.vue Vue component
- Modal.svelte Svelte component
- **layouts/**
- BaseLayout.astro
- BlogLayout.astro
- utils/
- helpers.ts
- constants.js
- types/
- index.d.ts TypeScript definitions
- ...
- tests/
- unit/
- components.test.ts
- e2e/
- homepage.spec.ts
- docs/
- **getting-started.md** Start here!
- api-reference.md
- .github/
- workflows/
- ci.yml
- package.json
- tsconfig.json
</FileTree>
### More Glob Examples
Show just the current directory:
<FileTree glob="./*" />
Show all TypeScript files in the project:
<FileTree glob="../**/*.ts" maxDepth={4} />
Show configuration files only:
<FileTree glob="../**/*.{json,yaml,yml,toml,config.js,config.ts}" maxDepth={2} />
### FileTree Usage Examples
```jsx
// Tree view (default) - hierarchical structure
<FileTree glob="../src/**/*.astro" maxDepth={3} />
// Thumbnail view - Windows Explorer style grid
<FileTree
glob="../public/images/**/*.{jpg,png,gif}"
view="thumbs"
thumbSize="medium"
/>
// Large thumbnails for detailed preview
<FileTree
glob="../assets/**/*.{jpg,png}"
view="thumbs"
thumbSize="large"
maxDepth={2}
/>
// Small thumbnails for compact display
<FileTree
glob="../gallery/**/*"
view="thumbs"
thumbSize="small"
linkFiles={false}
/>
// Custom URL prefix for GitHub integration
<FileTree
glob="../**/*.ts"
urlPrefix="https://github.com/username/repo/blob/main"
maxDepth={3}
/>
// VS Code integration - files open in editor
<FileTree
glob="../**/*.astro"
urlPrefix="vscode://file"
maxDepth={2}
/>
// Disable links if you just want display
<FileTree
glob="../**/*"
linkFiles={false}
maxDepth={2}
/>
// Show hidden files with custom dev server URL
<FileTree
glob="../**/*"
showHidden={true}
urlPrefix="http://localhost:3000"
maxDepth={2}
/>
// Manual structure (original way - no links)
<FileTree>
- src/
- components/
- Header.astro
</FileTree>
```
### View Modes:
- **Tree View** (`view="tree"`): Traditional hierarchical file tree with folders and files
- **Thumbnail View** (`view="thumbs"`): Grid layout like Windows Explorer with image previews
### Thumbnail Sizes:
- **Small** (`thumbSize="small"`): 80px thumbnails for compact display
- **Medium** (`thumbSize="medium"`): 120px thumbnails (default)
- **Large** (`thumbSize="large"`): 160px thumbnails for detailed preview
### Link Types Supported:
- **Default**: `file://` protocol for local file system
- **VS Code**: `vscode://file/` for opening in VS Code
- **GitHub**: `https://github.com/user/repo/blob/main/` for web viewing
- **Custom**: Any URL prefix you provide
- **Disabled**: Set `linkFiles={false}` for display only
## Breadcrumb Navigation
The Resources collection now includes automatic breadcrumb navigation!
### Features:
- **Auto-generated**: Breadcrumbs are automatically created based on your URL path
- **Smart labeling**: Uses your page title for the current page, formatted directory names for paths
- **Accessible**: Full ARIA support with proper labels and navigation structure
- **Responsive**: Mobile-friendly design that adapts to smaller screens
- **Customizable**: Easy to disable per page or customize styling
### Usage:
**Enable breadcrumbs (default behavior):**
```yaml
---
title: "My Page Title"
# Breadcrumbs will show automatically
---
```
**Disable breadcrumbs for a specific page:**
```yaml
---
title: "My Page Title"
breadcrumb: false
---
```
### Example Breadcrumb Path:
For a page at `/resources/guides/getting-started/`, the breadcrumb would show:
```
Home / Resources / Guides / Getting Started
```
The breadcrumb component is reusable and can be easily integrated into other collection layouts as needed.
## 🆕 Sidebar Autogenerated Nodes with Sorting
The sidebar now supports configurable sorting for autogenerated nodes! By default, all autogenerated sidebar sections use **alphabetical sorting**.
### Available Sort Functions:
1. **`'alphabetical'`** (Default): Sorts items alphabetically by label, with files before groups
2. **`'date'`**: Sorts by `pubDate` frontmatter field (newest first), fallback to alphabetical
3. **`'custom'`**: Use your own custom sorting function
### Configuration Examples:
#### Basic Alphabetical Sorting (Default)
```typescript
// src/config/sidebar.ts
export const sidebarConfig: SidebarGroup[] = [
{
label: 'Resources',
autogenerate: {
directory: 'resources',
collapsed: false,
sortBy: 'alphabetical' // This is the default
},
},
];
```
#### Date-based Sorting (Newest First)
```typescript
{
label: 'Blog Posts',
autogenerate: {
directory: 'blog',
collapsed: false,
sortBy: 'date' // Requires pubDate in frontmatter
},
}
```
#### Custom Sorting Function
```typescript
{
label: 'Custom Sorted',
autogenerate: {
directory: 'docs',
collapsed: false,
sortBy: 'custom',
customSort: (a, b) => {
// Custom logic here - example: prioritize certain files
if (a.label.startsWith('Getting Started')) return -1;
if (b.label.startsWith('Getting Started')) return 1;
return a.label.localeCompare(b.label);
}
},
}
```
### Features:
- **Hierarchical sorting**: Applies to both files and subdirectories
- **Files before groups**: Files always appear before subdirectory groups in alphabetical mode
- **Fallback support**: Date sorting falls back to alphabetical when no dates are available
- **Deep nesting**: Sorting applies recursively to all nested levels
- **Type safety**: Full TypeScript support with proper type definitions
### Migration:
Existing configurations will continue to work unchanged - alphabetical sorting is now the explicit default instead of being hardcoded.
## Mermaid Diagrams
Now we have full support for Mermaid diagrams in MDX! Here are some examples:
### Flowchart Example
```mermaid
graph TD
A[Start] --> B{Is it working?}
B -->|Yes| C[Great!]
B -->|No| D[Debug]
D --> B
C --> E[Deploy to Production]
```
### Sequence Diagram
```mermaid
sequenceDiagram
participant User
participant Browser
participant Server
participant Database
User->>Browser: Open website
Browser->>Server: Request page
Server->>Database: Query data
Database-->>Server: Return data
Server-->>Browser: Send HTML
Browser-->>User: Display page
```
### Git Flow Diagram
```mermaid
graph TD
A[main branch] --> B[develop branch]
B --> C[feature branch]
C --> D[commit 1]
D --> E[commit 2]
E --> F[merge to develop]
F --> B
B --> G[merge to main]
G --> A
style A fill:#e1f5fe
style B fill:#f3e5f5
style C fill:#e8f5e8
```
### Class Diagram
```mermaid
classDiagram
class FileTree {
+String glob
+Number maxDepth
+Boolean showHidden
+String[] exclude
+String urlPrefix
+Boolean linkFiles
+generateFileUrl()
+buildFileTreeFromPaths()
}
class RelativeGallery {
+String glob
+Object[] images
+Object gallerySettings
+Object lightboxSettings
+renderGallery()
}
FileTree --> RelativeGallery : uses similar patterns
```
### State Diagram
```mermaid
stateDiagram-v2
[*] --> Loading
Loading --> Success: Data loaded
Loading --> Error: Failed to load
Success --> [*]
Error --> Retry: User clicks retry
Retry --> Loading
Error --> [*]: User gives up
```
### Project Timeline
```mermaid
gantt
title Development Timeline
dateFormat YYYY-MM-DD
section Setup
Project Start :2024-01-01, 2024-01-31
Astro Setup :2024-01-15, 2024-01-31
section Features
ImageTools :2024-02-01, 2024-02-15
FileTree :2024-02-10, 2024-02-28
RelativeGallery :2024-03-01, 2024-03-15
Breadcrumbs :2024-03-10, 2024-03-20
section Recent
Mermaid Support :2024-12-01, 2024-12-19
Enhanced Links :2024-12-15, 2024-12-19
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

View File

@ -0,0 +1,69 @@
---
pubDate: 2024-12-15
title: Web Performance Optimization Guide
author: Sarah Johnson
description: "Learn how to optimize your website's performance with these proven techniques and best practices."
image0:
url: "https://images.unsplash.com/photo-1460925895917-afdab827c52f?w=800&h=400&fit=crop"
alt: "Performance optimization dashboard"
tags: ["performance", "optimization", "web-development", "speed"]
---
# Web Performance Optimization Guide
In today's fast-paced digital world, website performance is crucial for user experience and SEO rankings. This comprehensive guide will walk you through the essential techniques to optimize your website's performance.
## Key Performance Metrics
### Core Web Vitals
- **Largest Contentful Paint (LCP)**: Measures loading performance
- **First Input Delay (FID)**: Measures interactivity
- **Cumulative Layout Shift (CLS)**: Measures visual stability
### Additional Metrics
- **First Contentful Paint (FCP)**
- **Time to Interactive (TTI)**
- **Total Blocking Time (TBT)**
## Optimization Techniques
### 1. Image Optimization
```html
<!-- Use modern image formats -->
<picture>
<source srcset="image.webp" type="image/webp">
<source srcset="image.avif" type="image/avif">
<img src="image.jpg" alt="Optimized image" loading="lazy">
</picture>
```
### 2. Code Splitting
```javascript
// Dynamic imports for better performance
const LazyComponent = React.lazy(() => import('./LazyComponent'));
// Webpack code splitting
import('./module').then(module => {
// Use the module
});
```
### 3. Resource Preloading
```html
<!-- Preload critical resources -->
<link rel="preload" href="critical.css" as="style">
<link rel="preload" href="hero-image.jpg" as="image">
<link rel="prefetch" href="next-page.html">
```
## Performance Monitoring
Use tools like:
- Google PageSpeed Insights
- Lighthouse
- WebPageTest
- Core Web Vitals extension
## Conclusion
Web performance optimization is an ongoing process. Regular monitoring and continuous improvement are key to maintaining a fast, user-friendly website.

View File

@ -16,7 +16,6 @@ import Translate from "@polymech/astro-base/components/i18n.astro";
import { getSidebarConfig } from "@polymech/astro-base/config/sidebar";
import { generateToC } from "@polymech/astro-base/components/sidebar/utils/generateToC.js";
import RelativeImage from "@polymech/astro-base/components/RelativeImage.astro";
import type { MarkdownHeading } from "astro";
import { getCollection } from "astro:content";