feat(docs): create sukr documentation site with fixes
Self-documenting docs site built with sukr itself (dogfooding): Core changes: - Rename package from nrd-sh to sukr - Move personal site to sites/nrd.sh/ - Update AGENTS.md and README.md Documentation site (docs/): - Add site.toml with sukr.io base URL - Create docs-specific templates with sidebar navigation - Add dark theme CSS with syntax highlighting colors - Document all features: templates, sections, syntax highlighting, mermaid diagrams, and LaTeX math rendering Bug fixes: - Render individual pages for all sections (not just blog type) - Add #[source] error chaining for Tera template errors - Print full error chain in main() for better debugging
This commit is contained in:
81
docs/content/features/math.md
Normal file
81
docs/content/features/math.md
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
---
|
||||||
|
title: Math Rendering
|
||||||
|
description: Build-time LaTeX math with KaTeX
|
||||||
|
weight: 5
|
||||||
|
---
|
||||||
|
|
||||||
|
# Math Rendering
|
||||||
|
|
||||||
|
sukr renders LaTeX math expressions at build time using KaTeX, producing static HTML and CSS. No client-side JavaScript required.
|
||||||
|
|
||||||
|
## Inline Math
|
||||||
|
|
||||||
|
Use single dollar signs for inline math:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
The quadratic formula is $x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}$.
|
||||||
|
```
|
||||||
|
|
||||||
|
Renders as: The quadratic formula is $x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}$.
|
||||||
|
|
||||||
|
## Display Math
|
||||||
|
|
||||||
|
Use double dollar signs for display (block) math:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
$$
|
||||||
|
E = mc^2
|
||||||
|
$$
|
||||||
|
```
|
||||||
|
|
||||||
|
Or fence with `math` language:
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
```math
|
||||||
|
\int_0^\infty e^{-x^2} dx = \frac{\sqrt{\pi}}{2}
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
## Supported Features
|
||||||
|
|
||||||
|
KaTeX supports a large subset of LaTeX math:
|
||||||
|
|
||||||
|
- Greek letters: `$\alpha, \beta, \gamma$`
|
||||||
|
- Fractions: `$\frac{a}{b}$`
|
||||||
|
- Subscripts/superscripts: `$x_i^2$`
|
||||||
|
- Summations: `$\sum_{i=1}^{n} i$`
|
||||||
|
- Integrals: `$\int_a^b f(x)\,dx$`
|
||||||
|
- Matrices: `$\begin{pmatrix} a & b \\ c & d \end{pmatrix}$`
|
||||||
|
- And much more...
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
1. Math delimiters (`$...$`, `$$...$$`) are detected during parsing
|
||||||
|
2. KaTeX renders the expression to HTML + CSS
|
||||||
|
3. Required fonts are embedded inline
|
||||||
|
4. Output is pure HTML—no JavaScript
|
||||||
|
|
||||||
|
## Styling
|
||||||
|
|
||||||
|
KaTeX output uses semantic classes. Customize appearance:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.katex {
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.katex-display {
|
||||||
|
margin: 1.5em 0;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
Invalid LaTeX produces an error message inline rather than breaking the build:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
$\invalid{command}$
|
||||||
|
```
|
||||||
|
|
||||||
|
Renders with a red error indicator showing what went wrong.
|
||||||
70
docs/content/features/mermaid.md
Normal file
70
docs/content/features/mermaid.md
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
---
|
||||||
|
title: Mermaid Diagrams
|
||||||
|
description: Build-time diagram rendering with Mermaid
|
||||||
|
weight: 4
|
||||||
|
---
|
||||||
|
|
||||||
|
# Mermaid Diagrams
|
||||||
|
|
||||||
|
sukr renders Mermaid diagrams at build time, producing inline SVG. No client-side JavaScript required.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Use fenced code blocks with `mermaid` language:
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
```mermaid
|
||||||
|
graph LR
|
||||||
|
A[Input] --> B[Process]
|
||||||
|
B --> C[Output]
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
## Supported Diagram Types
|
||||||
|
|
||||||
|
| Type | Status | Description |
|
||||||
|
| --------- | --------------- | ----------------------------------------- |
|
||||||
|
| Flowchart | ✅ Full support | Flow diagrams with nodes and edges |
|
||||||
|
| Graph | ✅ Full support | Directed/undirected graphs |
|
||||||
|
| Sequence | ⚠️ Partial | Sequence diagrams (some layouts may vary) |
|
||||||
|
| State | ⚠️ Partial | State machine diagrams |
|
||||||
|
| Class | ⚠️ Partial | UML class diagrams |
|
||||||
|
|
||||||
|
> **Note:** Some complex diagram types may have layout differences compared to the JavaScript renderer. Flowcharts and basic graphs work reliably.
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
1. During Markdown parsing, `mermaid` code blocks are intercepted
|
||||||
|
2. The Mermaid definition is parsed and rendered to SVG
|
||||||
|
3. The SVG is inlined directly in the HTML output
|
||||||
|
4. No JavaScript or external resources needed
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph TD
|
||||||
|
A[Markdown] --> B{sukr}
|
||||||
|
B --> C[HTML]
|
||||||
|
B --> D[SVG Diagrams]
|
||||||
|
B --> E[Highlighted Code]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Styling
|
||||||
|
|
||||||
|
Mermaid SVGs inherit your CSS variables. Customize the look by targeting SVG elements:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.mermaid svg {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mermaid .node rect {
|
||||||
|
fill: var(--bg-sidebar);
|
||||||
|
stroke: var(--accent);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Fallback
|
||||||
|
|
||||||
|
If a diagram fails to render (complex diagrams, syntax errors), the original code block is preserved with an error comment.
|
||||||
@@ -12,7 +12,7 @@ sukr automatically discovers sections from your content directory structure.
|
|||||||
|
|
||||||
A section is any directory under `content/` that contains an `_index.md` file:
|
A section is any directory under `content/` that contains an `_index.md` file:
|
||||||
|
|
||||||
```
|
```text
|
||||||
content/
|
content/
|
||||||
├── _index.md # Homepage (not a section)
|
├── _index.md # Homepage (not a section)
|
||||||
├── about.md # Standalone page
|
├── about.md # Standalone page
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ sukr uses [Tera](https://tera.netlify.app/), a Jinja2-like templating engine. Te
|
|||||||
|
|
||||||
## Template Directory Structure
|
## Template Directory Structure
|
||||||
|
|
||||||
```
|
```text
|
||||||
templates/
|
templates/
|
||||||
├── base.html # Shared layout (required)
|
├── base.html # Shared layout (required)
|
||||||
├── page.html # Standalone pages
|
├── page.html # Standalone pages
|
||||||
|
|||||||
64
docs/static/style.css
vendored
64
docs/static/style.css
vendored
@@ -150,6 +150,64 @@ pre code {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Syntax highlighting (tree-sitter classes) */
|
||||||
|
.hl-keyword {
|
||||||
|
color: #ff79c6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-string {
|
||||||
|
color: #f1fa8c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-function {
|
||||||
|
color: #50fa7b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-comment {
|
||||||
|
color: #6272a4;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-number {
|
||||||
|
color: #bd93f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-operator {
|
||||||
|
color: #ff79c6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-punctuation {
|
||||||
|
color: var(--fg-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-punctuation-bracket {
|
||||||
|
color: var(--fg-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-variable {
|
||||||
|
color: var(--fg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-type {
|
||||||
|
color: #8be9fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-constant {
|
||||||
|
color: #bd93f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-attribute {
|
||||||
|
color: #50fa7b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-property {
|
||||||
|
color: #66d9ef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hl-tag {
|
||||||
|
color: #ff79c6;
|
||||||
|
}
|
||||||
|
|
||||||
/* Section navigation */
|
/* Section navigation */
|
||||||
.section-nav {
|
.section-nav {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -184,7 +242,8 @@ pre code {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Lists */
|
/* Lists */
|
||||||
ul, ol {
|
ul,
|
||||||
|
ol {
|
||||||
margin: 1rem 0;
|
margin: 1rem 0;
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
}
|
}
|
||||||
@@ -200,7 +259,8 @@ table {
|
|||||||
margin: 1rem 0;
|
margin: 1rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
th, td {
|
th,
|
||||||
|
td {
|
||||||
padding: 0.75rem;
|
padding: 0.75rem;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
|
|||||||
19
docs/templates/base.html
vendored
19
docs/templates/base.html
vendored
@@ -1,5 +1,6 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
@@ -15,23 +16,11 @@
|
|||||||
<span class="tagline">suckless static sites</span>
|
<span class="tagline">suckless static sites</span>
|
||||||
</header>
|
</header>
|
||||||
<nav>
|
<nav>
|
||||||
{% for item in nav %}
|
{% for item in nav %}<a href="{{ prefix }}{{ item.path }}" {% if page_path==item.path %} class="active" {% endif
|
||||||
<a
|
%}>{{ item.label }}</a>{% endfor %}
|
||||||
href="{{ prefix }}{{ item.path }}"
|
|
||||||
{%
|
|
||||||
if
|
|
||||||
page_path=""
|
|
||||||
="item.path"
|
|
||||||
%}
|
|
||||||
class="active"
|
|
||||||
{%
|
|
||||||
endif
|
|
||||||
%}
|
|
||||||
>{{ item.label }}</a
|
|
||||||
>
|
|
||||||
{% endfor %}
|
|
||||||
</nav>
|
</nav>
|
||||||
</aside>
|
</aside>
|
||||||
<main>{% block content %}{% endblock content %}</main>
|
<main>{% block content %}{% endblock content %}</main>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@@ -142,8 +142,7 @@ fn run(config_path: &Path) -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render individual content pages (for blog posts)
|
// Render individual content pages for all sections
|
||||||
if section.section_type == "blog" {
|
|
||||||
for item in &items {
|
for item in &items {
|
||||||
eprintln!(" processing: {}", item.slug);
|
eprintln!(" processing: {}", item.slug);
|
||||||
let html_body = render::markdown_to_html(&item.body);
|
let html_body = render::markdown_to_html(&item.body);
|
||||||
@@ -151,7 +150,6 @@ fn run(config_path: &Path) -> Result<()> {
|
|||||||
let html = engine.render_content(item, &html_body, &page_path, &config, &nav)?;
|
let html = engine.render_content(item, &html_body, &page_path, &config, &nav)?;
|
||||||
write_output(&output_dir, &content_dir, item, html)?;
|
write_output(&output_dir, &content_dir, item, html)?;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Render section index
|
// Render section index
|
||||||
let page_path = format!("/{}/index.html", section.name);
|
let page_path = format!("/{}/index.html", section.name);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ options = ["fmt", "-o", "align_entries=true", "-o", "reorder_keys=true"]
|
|||||||
[formatter.prettier]
|
[formatter.prettier]
|
||||||
command = "prettier"
|
command = "prettier"
|
||||||
excludes = ["*/sources.json"]
|
excludes = ["*/sources.json"]
|
||||||
includes = ["*.json", "*.md", "*.yaml", "*.yml", "*.html"]
|
includes = ["*.json", "*.md", "*.yaml", "*.yml"]
|
||||||
options = ["--write"]
|
options = ["--write"]
|
||||||
|
|
||||||
[formatter.rustfmt]
|
[formatter.rustfmt]
|
||||||
|
|||||||
Reference in New Issue
Block a user