diff --git a/ET/Web/Models/NoteInfo.cs b/ET/Web/Models/NoteInfo.cs
index 5bddc7f..d9c5558 100644
--- a/ET/Web/Models/NoteInfo.cs
+++ b/ET/Web/Models/NoteInfo.cs
@@ -4,6 +4,7 @@ public class NoteInfo
{
public string Slug { get; set; } = "";
public string Title { get; set; } = "";
+ public string? Category { get; set; }
}
public class NotesIndex
@@ -15,6 +16,7 @@ public class NoteDocument
{
public string Slug { get; set; } = "";
public string Title { get; set; } = "";
+ public string? Category { get; set; }
public string FrontmatterHtml { get; set; } = "";
public string HtmlContent { get; set; } = "";
}
diff --git a/ET/Web/Pages/DocViewer.razor b/ET/Web/Pages/DocViewer.razor
index 1c2f364..c18289b 100644
--- a/ET/Web/Pages/DocViewer.razor
+++ b/ET/Web/Pages/DocViewer.razor
@@ -15,7 +15,13 @@ else if (doc == null)
}
else
{
-
@doc.Title
+
+ @doc.Title
+ @if (!string.IsNullOrEmpty(doc.Category))
+ {
+ @doc.Category
+ }
+
@if (!string.IsNullOrEmpty(doc.FrontmatterHtml))
{
diff --git a/ET/Web/Pages/Docs.razor b/ET/Web/Pages/Docs.razor
index 59dda5c..a4133fc 100644
--- a/ET/Web/Pages/Docs.razor
+++ b/ET/Web/Pages/Docs.razor
@@ -15,7 +15,13 @@ else
@foreach (var note in notes.OrderBy(n => n.Title))
{
- @note.Title
+
+ @note.Title
+ @if (!string.IsNullOrEmpty(note.Category))
+ {
+ @note.Category
+ }
+
}
diff --git a/ET/Web/Services/DocsService.cs b/ET/Web/Services/DocsService.cs
index 5bd1a4d..535efd0 100644
--- a/ET/Web/Services/DocsService.cs
+++ b/ET/Web/Services/DocsService.cs
@@ -82,6 +82,19 @@ public class DocsService
if (frontmatterLines.Count > 0)
{
+ foreach (var line in frontmatterLines)
+ {
+ var colonIdx = line.IndexOf(':');
+ if (colonIdx > 0)
+ {
+ var key = line[..colonIdx].Trim();
+ if (string.Equals(key, "category", StringComparison.OrdinalIgnoreCase))
+ {
+ doc.Category = line[(colonIdx + 1)..].Trim().Trim('"');
+ }
+ }
+ }
+
var fmHtml = new System.Text.StringBuilder();
fmHtml.Append("");
foreach (var line in frontmatterLines)
diff --git a/ET/Web/SyncDocs.ps1 b/ET/Web/SyncDocs.ps1
index 89a7baf..580f59e 100644
--- a/ET/Web/SyncDocs.ps1
+++ b/ET/Web/SyncDocs.ps1
@@ -16,7 +16,18 @@ Get-ChildItem -Path $src -Filter "*.md" | ForEach-Object {
Copy-Item $_.FullName (Join-Path $dst "$slug.md")
- $entries += @{ slug = $slug; title = $base }
+ $category = $null
+ $content = Get-Content $_.FullName -Raw
+ if ($content -match '(?s)^---\s*\n(.*?)\n---') {
+ $frontmatter = $Matches[1]
+ if ($frontmatter -match '(?m)^category:\s*(.+)$') {
+ $category = $Matches[1].Trim().Trim('"')
+ }
+ }
+
+ $entry = @{ slug = $slug; title = $base }
+ if ($category) { $entry.category = $category }
+ $entries += $entry
}
$indexPath = "$PSScriptRoot\wwwroot\docs\notes-index.json"
diff --git a/ET/Web/wwwroot/css/app.css b/ET/Web/wwwroot/css/app.css
index 1f93b02..3353d89 100644
--- a/ET/Web/wwwroot/css/app.css
+++ b/ET/Web/wwwroot/css/app.css
@@ -198,4 +198,19 @@ table.frontmatter td.fm-key {
.markdown-body th { background: #f8f9fa; }
.markdown-body code { background: #f0f0f0; padding: 0.15rem 0.3rem; border-radius: 3px; font-size: 0.9em; }
.markdown-body pre code { background: none; padding: 0; }
-.markdown-body blockquote { border-left: 3px solid #dee2e6; padding-left: 1rem; color: #6c757d; margin: 0.75rem 0; }
\ No newline at end of file
+.markdown-body blockquote { border-left: 3px solid #dee2e6; padding-left: 1rem; color: #6c757d; margin: 0.75rem 0; }
+
+.category-badge {
+ display: inline-block;
+ font-size: 0.7rem;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+ padding: 0.2em 0.6em;
+ border-radius: 4px;
+ vertical-align: middle;
+ margin-left: 0.5rem;
+ background: #e8f4fd;
+ color: #1b6ec2;
+ border: 1px solid #b8daff;
+}
\ No newline at end of file
diff --git a/ET/Web/wwwroot/docs/notes-index.json b/ET/Web/wwwroot/docs/notes-index.json
index 58c9e87..2fe084d 100644
--- a/ET/Web/wwwroot/docs/notes-index.json
+++ b/ET/Web/wwwroot/docs/notes-index.json
@@ -1,24 +1,27 @@
{
"notes": [
{
- "slug": "artificer",
- "title": "Artificer"
+ "title": "Artificer",
+ "category": "Role",
+ "slug": "artificer"
},
{
"slug": "awareness",
"title": "Awareness"
},
{
- "slug": "cache-map",
- "title": "Cache Map"
+ "title": "Cache Map",
+ "category": "Gear",
+ "slug": "cache-map"
},
{
"slug": "card-library",
"title": "Card Library"
},
{
- "slug": "concoliator",
- "title": "Concoliator"
+ "title": "Concoliator",
+ "category": "Role",
+ "slug": "concoliator"
},
{
"slug": "contents",
@@ -41,12 +44,14 @@
"title": "Dirt Roads"
},
{
- "slug": "dolewood-canoe",
- "title": "Dolewood Canoe"
+ "title": "Dolewood Canoe",
+ "category": "Gear",
+ "slug": "dolewood-canoe"
},
{
- "slug": "e03",
- "title": "E.03"
+ "title": "E.03",
+ "category": "Event",
+ "slug": "e03"
},
{
"slug": "ecology",
@@ -73,80 +78,95 @@
"title": "Explore Phase"
},
{
- "slug": "explorer",
- "title": "Explorer"
+ "title": "Explorer",
+ "category": "Role",
+ "slug": "explorer"
},
{
- "slug": "ferinodex",
- "title": "Ferinodex"
+ "title": "Ferinodex",
+ "category": "Gear",
+ "slug": "ferinodex"
},
{
"slug": "flora-meeples",
"title": "Flora Meeples"
},
{
- "slug": "forest-1",
- "title": "Forest 1"
+ "title": "Forest 1",
+ "category": "Region",
+ "slug": "forest-1"
},
{
- "slug": "forest-2",
- "title": "Forest 2"
+ "title": "Forest 2",
+ "category": "Region",
+ "slug": "forest-2"
},
{
- "slug": "forest-3",
- "title": "Forest 3"
+ "title": "Forest 3",
+ "category": "Region",
+ "slug": "forest-3"
},
{
- "slug": "forest-4",
- "title": "Forest 4"
+ "title": "Forest 4",
+ "category": "Region",
+ "slug": "forest-4"
},
{
- "slug": "forest-5",
- "title": "Forest 5"
+ "title": "Forest 5",
+ "category": "Region",
+ "slug": "forest-5"
},
{
"slug": "forest",
"title": "Forest"
},
{
- "slug": "gauzeblade",
- "title": "Gauzeblade"
+ "title": "Gauzeblade",
+ "category": "Gear",
+ "slug": "gauzeblade"
},
{
"slug": "gear-cards",
"title": "Gear Cards"
},
{
- "slug": "grass-1",
- "title": "Grass 1"
+ "title": "Grass 1",
+ "category": "Region",
+ "slug": "grass-1"
},
{
- "slug": "grass-2",
- "title": "Grass 2"
+ "title": "Grass 2",
+ "category": "Region",
+ "slug": "grass-2"
},
{
- "slug": "grass-3",
- "title": "Grass 3"
+ "title": "Grass 3",
+ "category": "Region",
+ "slug": "grass-3"
},
{
- "slug": "grass-4",
- "title": "Grass 4"
+ "title": "Grass 4",
+ "category": "Region",
+ "slug": "grass-4"
},
{
- "slug": "grass-5",
- "title": "Grass 5"
+ "title": "Grass 5",
+ "category": "Region",
+ "slug": "grass-5"
},
{
"slug": "grasslands",
"title": "Grasslands"
},
{
- "slug": "guide",
- "title": "Guide"
+ "title": "Guide",
+ "category": "Role",
+ "slug": "guide"
},
{
- "slug": "hidden-trail-map",
- "title": "Hidden Trail Map"
+ "title": "Hidden Trail Map",
+ "category": "Gear",
+ "slug": "hidden-trail-map"
},
{
"slug": "injury-cards",
@@ -165,44 +185,52 @@
"title": "Market"
},
{
- "slug": "mountain-1",
- "title": "Mountain 1"
+ "title": "Mountain 1",
+ "category": "Region",
+ "slug": "mountain-1"
},
{
- "slug": "mountain-2",
- "title": "Mountain 2"
+ "title": "Mountain 2",
+ "category": "Region",
+ "slug": "mountain-2"
},
{
- "slug": "mountain-3",
- "title": "Mountain 3"
+ "title": "Mountain 3",
+ "category": "Region",
+ "slug": "mountain-3"
},
{
- "slug": "mountain-4",
- "title": "Mountain 4"
+ "title": "Mountain 4",
+ "category": "Region",
+ "slug": "mountain-4"
},
{
- "slug": "mountain-5",
- "title": "Mountain 5"
+ "title": "Mountain 5",
+ "category": "Region",
+ "slug": "mountain-5"
},
{
"slug": "mountain",
"title": "Mountain"
},
{
- "slug": "paratrepsis-whistle",
- "title": "Paratrepsis Whistle"
+ "title": "Paratrepsis Whistle",
+ "category": "Gear",
+ "slug": "paratrepsis-whistle"
},
{
"slug": "paved-roads",
"title": "Paved Roads"
},
{
- "slug": "perfect-day-1",
- "title": "Perfect Day 1"
+ "title": "Perfect Day 1",
+ "category": "Event",
+ "slug": "perfect-day-1"
},
{
- "slug": "phonoscopic-headset",
- "title": "Phonoscopic Headset"
+ "title": "Phonoscopic Headset",
+ "category": "Gear",
+ "slug": "phonoscopic-headset"
},
{
"slug": "player-boards",
@@ -257,20 +285,23 @@
"title": "Round"
},
{
- "slug": "ruins-map",
- "title": "Ruins Map"
+ "title": "Ruins Map",
+ "category": "Gear",
+ "slug": "ruins-map"
},
{
"slug": "scout",
"title": "Scout"
},
{
- "slug": "shaper",
- "title": "Shaper"
+ "title": "Shaper",
+ "category": "Role",
+ "slug": "shaper"
},
{
- "slug": "shepard",
- "title": "Shepard"
+ "title": "Shepard",
+ "category": "Role",
+ "slug": "shepard"
},
{
"slug": "story",
@@ -281,32 +312,37 @@
"title": "Supply"
},
{
- "slug": "terrain-2",
- "title": "Terrain 2"
+ "title": "Terrain 2",
+ "category": "Terrain",
+ "slug": "terrain-2"
},
{
- "slug": "terrain-3",
- "title": "Terrain 3"
+ "title": "Terrain 3",
+ "category": "Terrain",
+ "slug": "terrain-3"
},
{
"slug": "terrain-cards",
"title": "Terrain Cards"
},
{
- "slug": "terrain",
- "title": "Terrain"
+ "title": "Terrain",
+ "category": "Terrain",
+ "slug": "terrain"
},
{
- "slug": "totem-of-the-irix",
- "title": "Totem of the Irix"
+ "title": "Totem of the Irix",
+ "category": "Gear",
+ "slug": "totem-of-the-irix"
},
{
"slug": "trade",
"title": "Trade"
},
{
- "slug": "trader",
- "title": "Trader"
+ "title": "Trader",
+ "category": "Role",
+ "slug": "trader"
},
{
"slug": "trail-markers",
@@ -333,32 +369,38 @@
"title": "Victory Condition"
},
{
- "slug": "wasteland-1",
- "title": "Wasteland 1"
+ "title": "Wasteland 1",
+ "category": "Region",
+ "slug": "wasteland-1"
},
{
"slug": "wasteland",
"title": "Wasteland"
},
{
- "slug": "water-1",
- "title": "Water 1"
+ "title": "Water 1",
+ "category": "Region",
+ "slug": "water-1"
},
{
- "slug": "water-2",
- "title": "Water 2"
+ "title": "Water 2",
+ "category": "Region",
+ "slug": "water-2"
},
{
- "slug": "water-3",
- "title": "Water 3"
+ "title": "Water 3",
+ "category": "Region",
+ "slug": "water-3"
},
{
- "slug": "water-4",
- "title": "Water 4"
+ "title": "Water 4",
+ "category": "Region",
+ "slug": "water-4"
},
{
- "slug": "water-5",
- "title": "Water 5"
+ "title": "Water 5",
+ "category": "Region",
+ "slug": "water-5"
},
{
"slug": "weather",