Server MD with Rust
This commit is contained in:
commit
3899ecce2f
14 changed files with 2823 additions and 0 deletions
229
TEMPLATE_FEATURE.md
Normal file
229
TEMPLATE_FEATURE.md
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
# Template/Layout Feature Implementation
|
||||
|
||||
## Overview
|
||||
|
||||
Successfully implemented a flexible template/layout system that allows loading custom HTML templates from the working directory's `./layout` folder.
|
||||
|
||||
## Key Features
|
||||
|
||||
### ✅ **Template Loading from Filesystem**
|
||||
- **Custom Template Support**: Loads templates from `./layout/{template_name}.hbs`
|
||||
- **Handlebars Integration**: Uses the `handlebars` crate for powerful templating
|
||||
- **Fallback Mechanism**: Gracefully falls back to built-in default template if custom template not found
|
||||
- **Runtime Configuration**: Template name configurable via `--template` flag (default: "default")
|
||||
|
||||
### ✅ **Template Variables**
|
||||
- `{{title}}` - Page title derived from Markdown filename
|
||||
- `{{content}}` - Rendered HTML content from Markdown
|
||||
- `{{path}}` - Current URL path
|
||||
|
||||
### ✅ **Error Handling**
|
||||
- **File Not Found**: Falls back to built-in template if custom template doesn't exist
|
||||
- **Parse Errors**: Falls back to simple HTML if template rendering fails
|
||||
- **Directory Creation**: Automatically handles missing layout directories
|
||||
|
||||
### ✅ **User Experience**
|
||||
- **Clear Logging**: Shows which template is being used on startup
|
||||
- **Help Documentation**: Updated `--help` shows template option
|
||||
- **Flexible Configuration**: Easy to switch between different templates
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Template Loading Logic
|
||||
|
||||
```rust
|
||||
fn load_template(workdir: &PathBuf, template_name: &str) -> Handlebars<'static> {
|
||||
// 1. Try to load from ./layout/{template_name}.hbs
|
||||
// 2. If found and valid, use it
|
||||
// 3. Otherwise, use built-in default template
|
||||
}
|
||||
```
|
||||
|
||||
### Template Rendering
|
||||
|
||||
```rust
|
||||
let template_data = json!({
|
||||
"title": title,
|
||||
"content": html_output,
|
||||
"path": path.into_inner(),
|
||||
});
|
||||
|
||||
match data.template_engine.render("layout", &template_data) {
|
||||
Ok(rendered) => /* Use rendered template */,
|
||||
Err(_) => /* Fallback to simple HTML */
|
||||
}
|
||||
```
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
mhmmcontent/
|
||||
├── layout/ # Template directory
|
||||
│ ├── default.hbs # Custom default template
|
||||
│ ├── minimal.hbs # Minimal template example
|
||||
│ └── *.hbs # Additional custom templates
|
||||
├── content/ # Markdown content
|
||||
│ └── *.md # Markdown files
|
||||
└── src/main.rs # Server implementation
|
||||
```
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Default Template (Built-in)
|
||||
```bash
|
||||
./mhmmcontent
|
||||
# Uses built-in default template
|
||||
```
|
||||
|
||||
### Custom Template from Filesystem
|
||||
```bash
|
||||
./mhmmcontent --template default
|
||||
# Loads from ./layout/default.hbs if it exists
|
||||
```
|
||||
|
||||
### Different Custom Template
|
||||
```bash
|
||||
./mhmmcontent --template minimal
|
||||
# Loads from ./layout/minimal.hbs
|
||||
```
|
||||
|
||||
### Non-existent Template (Error)
|
||||
```bash
|
||||
./mhmmcontent --template nonexistent
|
||||
# Fails with clear error message indicating missing template file
|
||||
```
|
||||
|
||||
## Template Examples
|
||||
|
||||
### Basic Template (`layout/basic.hbs`)
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{title}}</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
|
||||
pre { background: #f0f0f0; padding: 10px; overflow-x: auto; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>{{title}}</h1>
|
||||
<div>{{{content}}}</div>
|
||||
<footer><small>Path: {{path}}</small></footer>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
### Advanced Template (`layout/advanced.hbs`)
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{title}} | My Site</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<style>
|
||||
:root {
|
||||
--primary: #2c3e50;
|
||||
--secondary: #3498db;
|
||||
}
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
max-width: 1000px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
}
|
||||
header {
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
padding: 1rem;
|
||||
margin-bottom: 2rem;
|
||||
border-radius: 5px;
|
||||
}
|
||||
nav {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
nav a {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
}
|
||||
main {
|
||||
min-height: 300px;
|
||||
}
|
||||
footer {
|
||||
margin-top: 2rem;
|
||||
padding-top: 1rem;
|
||||
border-top: 1px solid #eee;
|
||||
color: #666;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>My Site</h1>
|
||||
<nav>
|
||||
<a href="/">Home</a>
|
||||
<a href="/about">About</a>
|
||||
<a href="/contact">Contact</a>
|
||||
</nav>
|
||||
<div style="font-size: 0.9rem; opacity: 0.8;">
|
||||
Current page: {{path}}
|
||||
</div>
|
||||
</header>
|
||||
<main>
|
||||
<h2>{{title}}</h2>
|
||||
{{{content}}}
|
||||
</main>
|
||||
<footer>
|
||||
© 2023 My Site. Powered by Rust Markdown Server.
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
### For Users
|
||||
- **Custom Branding**: Easy to add logos, colors, and branding
|
||||
- **Consistent Layout**: Maintain consistent header/footer across all pages
|
||||
- **Navigation**: Add navigation menus to all pages automatically
|
||||
- **Responsive Design**: Create mobile-friendly layouts
|
||||
|
||||
### For Developers
|
||||
- **Separation of Concerns**: Content (Markdown) separate from presentation (HTML)
|
||||
- **Easy Customization**: No need to modify server code to change appearance
|
||||
- **Multiple Themes**: Support different templates for different use cases
|
||||
- **Fallback Safety**: Server continues to work even if templates are missing
|
||||
|
||||
## Technical Implementation
|
||||
|
||||
### Dependencies Added
|
||||
```toml
|
||||
[dependencies]
|
||||
handlebars = "4.0" # Templating engine
|
||||
```
|
||||
|
||||
### Key Functions
|
||||
- `load_template()`: Loads and registers templates
|
||||
- `serve_markdown()`: Renders content using templates
|
||||
- Template fallback mechanism for robustness
|
||||
|
||||
### Error Handling
|
||||
- **File system errors**: Clear error messages for missing template files
|
||||
- **Template parsing errors**: Detailed error messages for invalid template syntax
|
||||
- **Rendering errors**: Fallback to simple HTML if template rendering fails
|
||||
- **Strict Requirements**: Server fails fast if required template is missing
|
||||
|
||||
## Performance
|
||||
|
||||
- **Fast Template Loading**: Templates loaded once at startup
|
||||
- **Efficient Rendering**: Handlebars provides fast template rendering
|
||||
- **Minimal Overhead**: Template processing adds negligible latency
|
||||
- **Memory Efficient**: Templates stored in memory after initial load
|
||||
|
||||
The template feature makes the Markdown server highly customizable while maintaining robustness and ease of use.
|
||||
Loading…
Add table
Add a link
Reference in a new issue