...
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,92 @@
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
var exeDir = AppContext.BaseDirectory;
|
||||
|
||||
var solutionDir = FindContainingDir(exeDir, "ET.sln")
|
||||
?? throw new InvalidOperationException("Cannot find ET.sln");
|
||||
|
||||
var srcDir = Path.GetFullPath(Path.Combine(solutionDir, "..", "docs", "Notes"));
|
||||
var dstDir = Path.GetFullPath(Path.Combine(solutionDir, "Web", "wwwroot", "docs", "notes"));
|
||||
|
||||
Console.WriteLine($"Source: {srcDir}");
|
||||
Console.WriteLine($"Destination: {dstDir}");
|
||||
|
||||
if (!Directory.Exists(srcDir))
|
||||
{
|
||||
Console.Error.WriteLine($"Source directory not found: {srcDir}");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(dstDir);
|
||||
|
||||
foreach (var file in Directory.GetFiles(dstDir))
|
||||
File.Delete(file);
|
||||
|
||||
var entries = new List<object>();
|
||||
|
||||
foreach (var file in Directory.EnumerateFiles(srcDir, "*.md"))
|
||||
{
|
||||
var name = Path.GetFileNameWithoutExtension(file);
|
||||
var slug = Slugify(name);
|
||||
|
||||
File.Copy(file, Path.Combine(dstDir, $"{slug}.md"), overwrite: true);
|
||||
|
||||
string? category = null;
|
||||
var content = File.ReadAllText(file);
|
||||
var fmMatch = Regex.Match(content, @"^---\s*\n(.*?)\n---", RegexOptions.Singleline);
|
||||
if (fmMatch.Success)
|
||||
{
|
||||
var catMatch = Regex.Match(fmMatch.Groups[1].Value, @"(?m)^category:\s*(.+)$");
|
||||
if (catMatch.Success)
|
||||
category = catMatch.Groups[1].Value.Trim().Trim('"');
|
||||
}
|
||||
|
||||
var entry = new Dictionary<string, object?>
|
||||
{
|
||||
["slug"] = slug,
|
||||
["title"] = name
|
||||
};
|
||||
if (category != null)
|
||||
entry["category"] = category;
|
||||
|
||||
entries.Add(entry);
|
||||
}
|
||||
|
||||
var index = new Dictionary<string, object> { ["notes"] = entries };
|
||||
var json = System.Text.Json.JsonSerializer.Serialize(index, new System.Text.Json.JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true
|
||||
});
|
||||
|
||||
var indexPath = Path.Combine(Path.GetDirectoryName(dstDir)!, "notes-index.json");
|
||||
File.WriteAllText(indexPath, json);
|
||||
|
||||
Console.WriteLine($"Copied {entries.Count} notes.");
|
||||
Console.WriteLine($"Index written to: {indexPath}");
|
||||
return 0;
|
||||
|
||||
static string Slugify(string name)
|
||||
{
|
||||
var slug = name.ToLowerInvariant()
|
||||
.Replace("'", "")
|
||||
.Replace(".", "")
|
||||
.Replace("(", "")
|
||||
.Replace(")", "");
|
||||
slug = Regex.Replace(slug, @"[^a-z0-9 -]", "");
|
||||
slug = Regex.Replace(slug, @"\s+", "-");
|
||||
slug = Regex.Replace(slug, @"-+", "-");
|
||||
return slug.Trim('-');
|
||||
}
|
||||
|
||||
static string? FindContainingDir(string startDir, string markerFile)
|
||||
{
|
||||
var dir = new DirectoryInfo(startDir);
|
||||
while (dir != null)
|
||||
{
|
||||
if (File.Exists(Path.Combine(dir.FullName, markerFile)))
|
||||
return dir.FullName;
|
||||
dir = dir.Parent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Web", "Web\Web.csproj", "{6E375519-4DF8-455B-9AEC-0C84C31106E9}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Console", "Console\Console.csproj", "{A5946F7D-E8CE-4ACE-8D79-0F5FF0CB11C0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -12,5 +14,9 @@ Global
|
||||
{6E375519-4DF8-455B-9AEC-0C84C31106E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6E375519-4DF8-455B-9AEC-0C84C31106E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6E375519-4DF8-455B-9AEC-0C84C31106E9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A5946F7D-E8CE-4ACE-8D79-0F5FF0CB11C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A5946F7D-E8CE-4ACE-8D79-0F5FF0CB11C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A5946F7D-E8CE-4ACE-8D79-0F5FF0CB11C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A5946F7D-E8CE-4ACE-8D79-0F5FF0CB11C0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -2,14 +2,8 @@
|
||||
<div class="page">
|
||||
<div class="sidebar">
|
||||
<NavMenu/>
|
||||
|
||||
</div>
|
||||
|
||||
<main>
|
||||
<div class="top-row px-4">
|
||||
<a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
|
||||
</div>
|
||||
|
||||
<article class="content px-4">
|
||||
@Body
|
||||
</article>
|
||||
|
||||
@@ -16,16 +16,6 @@
|
||||
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="counter">
|
||||
<span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span> Counter
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="weather">
|
||||
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Weather
|
||||
</NavLink>
|
||||
</div>
|
||||
|
||||
@if (groupedNotes == null)
|
||||
{
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
@page "/counter"
|
||||
|
||||
<PageTitle>Counter</PageTitle>
|
||||
|
||||
<h1>Counter</h1>
|
||||
|
||||
<p role="status">Current count: @currentCount</p>
|
||||
|
||||
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
|
||||
|
||||
@code {
|
||||
private int currentCount = 0;
|
||||
|
||||
private void IncrementCount()
|
||||
{
|
||||
currentCount++;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
@page "/weather"
|
||||
@inject HttpClient Http
|
||||
|
||||
<PageTitle>Weather</PageTitle>
|
||||
|
||||
<h1>Weather</h1>
|
||||
|
||||
<p>This component demonstrates fetching data from the server.</p>
|
||||
|
||||
@if (forecasts == null)
|
||||
{
|
||||
<p>
|
||||
<em>Loading...</em>
|
||||
</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th aria-label="Temperature in Celsius">Temp. (C)</th>
|
||||
<th aria-label="Temperature in Fahrenheit">Temp. (F)</th>
|
||||
<th>Summary</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var forecast in forecasts)
|
||||
{
|
||||
<tr>
|
||||
<td>@forecast.Date.ToShortDateString()</td>
|
||||
<td>@forecast.TemperatureC</td>
|
||||
<td>@forecast.TemperatureF</td>
|
||||
<td>@forecast.Summary</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
|
||||
@code {
|
||||
private WeatherForecast[]? forecasts;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/weather.json");
|
||||
}
|
||||
|
||||
public class WeatherForecast
|
||||
{
|
||||
public DateOnly Date { get; set; }
|
||||
|
||||
public int TemperatureC { get; set; }
|
||||
|
||||
public string? Summary { get; set; }
|
||||
|
||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
$src = Resolve-Path "$PSScriptRoot\..\..\docs\Notes"
|
||||
$dst = "$PSScriptRoot\wwwroot\docs\notes"
|
||||
if (Test-Path $dst) { Remove-Item "$dst\*" -Force -ErrorAction SilentlyContinue }
|
||||
New-Item -ItemType Directory -Path $dst -Force | Out-Null
|
||||
|
||||
$entries = @()
|
||||
Get-ChildItem -Path $src -Filter "*.md" | ForEach-Object {
|
||||
$base = $_.BaseName
|
||||
$slug = $base.ToLowerInvariant()
|
||||
$slug = $slug -replace "'", ""
|
||||
$slug = $slug -replace "\.", ""
|
||||
$slug = $slug -replace "[^a-z0-9 -]", ""
|
||||
$slug = $slug -replace "\s+", "-"
|
||||
$slug = $slug -replace "-+", "-"
|
||||
$slug = $slug.Trim('-')
|
||||
|
||||
Copy-Item $_.FullName (Join-Path $dst "$slug.md")
|
||||
|
||||
$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"
|
||||
$index = @{ notes = $entries } | ConvertTo-Json
|
||||
Set-Content -Path $indexPath -Value $index -Encoding UTF8
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="SyncDocsNotes" BeforeTargets="BeforeBuild">
|
||||
<Exec Command="powershell -NoProfile -ExecutionPolicy Bypass -File "$(MSBuildProjectDirectory)\SyncDocs.ps1""/>
|
||||
<Exec Command="dotnet run --project "$(MSBuildProjectDirectory)\..\Console\Console.csproj""/>
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
{
|
||||
{
|
||||
"notes": [
|
||||
{
|
||||
"slug": "artificer",
|
||||
"title": "Artificer",
|
||||
"category": "Role",
|
||||
"slug": "artificer"
|
||||
"category": "Role"
|
||||
},
|
||||
{
|
||||
"slug": "awareness",
|
||||
"title": "Awareness"
|
||||
},
|
||||
{
|
||||
"slug": "cache-map",
|
||||
"title": "Cache Map",
|
||||
"category": "Gear",
|
||||
"slug": "cache-map"
|
||||
"category": "Gear"
|
||||
},
|
||||
{
|
||||
"slug": "card-library",
|
||||
"title": "Card Library"
|
||||
},
|
||||
{
|
||||
"slug": "concoliator",
|
||||
"title": "Concoliator",
|
||||
"category": "Role",
|
||||
"slug": "concoliator"
|
||||
"category": "Role"
|
||||
},
|
||||
{
|
||||
"slug": "contents",
|
||||
@@ -44,14 +44,14 @@
|
||||
"title": "Dirt Roads"
|
||||
},
|
||||
{
|
||||
"slug": "dolewood-canoe",
|
||||
"title": "Dolewood Canoe",
|
||||
"category": "Gear",
|
||||
"slug": "dolewood-canoe"
|
||||
"category": "Gear"
|
||||
},
|
||||
{
|
||||
"slug": "e03",
|
||||
"title": "E.03",
|
||||
"category": "Event",
|
||||
"slug": "e03"
|
||||
"category": "Event"
|
||||
},
|
||||
{
|
||||
"slug": "ecology",
|
||||
@@ -78,95 +78,95 @@
|
||||
"title": "Explore Phase"
|
||||
},
|
||||
{
|
||||
"slug": "explorer",
|
||||
"title": "Explorer",
|
||||
"category": "Role",
|
||||
"slug": "explorer"
|
||||
"category": "Role"
|
||||
},
|
||||
{
|
||||
"slug": "ferinodex",
|
||||
"title": "Ferinodex",
|
||||
"category": "Gear",
|
||||
"slug": "ferinodex"
|
||||
"category": "Gear"
|
||||
},
|
||||
{
|
||||
"slug": "flora-meeples",
|
||||
"title": "Flora Meeples"
|
||||
},
|
||||
{
|
||||
"slug": "forest-1",
|
||||
"title": "Forest 1",
|
||||
"category": "Region",
|
||||
"slug": "forest-1"
|
||||
"category": "Region"
|
||||
},
|
||||
{
|
||||
"slug": "forest-2",
|
||||
"title": "Forest 2",
|
||||
"category": "Region",
|
||||
"slug": "forest-2"
|
||||
"category": "Region"
|
||||
},
|
||||
{
|
||||
"slug": "forest-3",
|
||||
"title": "Forest 3",
|
||||
"category": "Region",
|
||||
"slug": "forest-3"
|
||||
"category": "Region"
|
||||
},
|
||||
{
|
||||
"slug": "forest-4",
|
||||
"title": "Forest 4",
|
||||
"category": "Region",
|
||||
"slug": "forest-4"
|
||||
"category": "Region"
|
||||
},
|
||||
{
|
||||
"slug": "forest-5",
|
||||
"title": "Forest 5",
|
||||
"category": "Region",
|
||||
"slug": "forest-5"
|
||||
"category": "Region"
|
||||
},
|
||||
{
|
||||
"slug": "forest",
|
||||
"title": "Forest"
|
||||
},
|
||||
{
|
||||
"slug": "gauzeblade",
|
||||
"title": "Gauzeblade",
|
||||
"category": "Gear",
|
||||
"slug": "gauzeblade"
|
||||
"category": "Gear"
|
||||
},
|
||||
{
|
||||
"slug": "gear-cards",
|
||||
"title": "Gear Cards"
|
||||
},
|
||||
{
|
||||
"slug": "grass-1",
|
||||
"title": "Grass 1",
|
||||
"category": "Region",
|
||||
"slug": "grass-1"
|
||||
"category": "Region"
|
||||
},
|
||||
{
|
||||
"slug": "grass-2",
|
||||
"title": "Grass 2",
|
||||
"category": "Region",
|
||||
"slug": "grass-2"
|
||||
"category": "Region"
|
||||
},
|
||||
{
|
||||
"slug": "grass-3",
|
||||
"title": "Grass 3",
|
||||
"category": "Region",
|
||||
"slug": "grass-3"
|
||||
"category": "Region"
|
||||
},
|
||||
{
|
||||
"slug": "grass-4",
|
||||
"title": "Grass 4",
|
||||
"category": "Region",
|
||||
"slug": "grass-4"
|
||||
"category": "Region"
|
||||
},
|
||||
{
|
||||
"slug": "grass-5",
|
||||
"title": "Grass 5",
|
||||
"category": "Region",
|
||||
"slug": "grass-5"
|
||||
"category": "Region"
|
||||
},
|
||||
{
|
||||
"slug": "grasslands",
|
||||
"title": "Grasslands"
|
||||
},
|
||||
{
|
||||
"slug": "guide",
|
||||
"title": "Guide",
|
||||
"category": "Role",
|
||||
"slug": "guide"
|
||||
"category": "Role"
|
||||
},
|
||||
{
|
||||
"slug": "hidden-trail-map",
|
||||
"title": "Hidden Trail Map",
|
||||
"category": "Gear",
|
||||
"slug": "hidden-trail-map"
|
||||
"category": "Gear"
|
||||
},
|
||||
{
|
||||
"slug": "injury-cards",
|
||||
@@ -185,52 +185,52 @@
|
||||
"title": "Market"
|
||||
},
|
||||
{
|
||||
"slug": "mountain-1",
|
||||
"title": "Mountain 1",
|
||||
"category": "Region",
|
||||
"slug": "mountain-1"
|
||||
"category": "Region"
|
||||
},
|
||||
{
|
||||
"slug": "mountain-2",
|
||||
"title": "Mountain 2",
|
||||
"category": "Region",
|
||||
"slug": "mountain-2"
|
||||
"category": "Region"
|
||||
},
|
||||
{
|
||||
"slug": "mountain-3",
|
||||
"title": "Mountain 3",
|
||||
"category": "Region",
|
||||
"slug": "mountain-3"
|
||||
"category": "Region"
|
||||
},
|
||||
{
|
||||
"slug": "mountain-4",
|
||||
"title": "Mountain 4",
|
||||
"category": "Region",
|
||||
"slug": "mountain-4"
|
||||
"category": "Region"
|
||||
},
|
||||
{
|
||||
"slug": "mountain-5",
|
||||
"title": "Mountain 5",
|
||||
"category": "Region",
|
||||
"slug": "mountain-5"
|
||||
"category": "Region"
|
||||
},
|
||||
{
|
||||
"slug": "mountain",
|
||||
"title": "Mountain"
|
||||
},
|
||||
{
|
||||
"slug": "paratrepsis-whistle",
|
||||
"title": "Paratrepsis Whistle",
|
||||
"category": "Gear",
|
||||
"slug": "paratrepsis-whistle"
|
||||
"category": "Gear"
|
||||
},
|
||||
{
|
||||
"slug": "paved-roads",
|
||||
"title": "Paved Roads"
|
||||
},
|
||||
{
|
||||
"slug": "perfect-day-1",
|
||||
"title": "Perfect Day 1",
|
||||
"category": "Event",
|
||||
"slug": "perfect-day-1"
|
||||
"category": "Event"
|
||||
},
|
||||
{
|
||||
"slug": "phonoscopic-headset",
|
||||
"title": "Phonoscopic Headset",
|
||||
"category": "Gear",
|
||||
"slug": "phonoscopic-headset"
|
||||
"category": "Gear"
|
||||
},
|
||||
{
|
||||
"slug": "player-boards",
|
||||
@@ -285,23 +285,23 @@
|
||||
"title": "Round"
|
||||
},
|
||||
{
|
||||
"slug": "ruins-map",
|
||||
"title": "Ruins Map",
|
||||
"category": "Gear",
|
||||
"slug": "ruins-map"
|
||||
"category": "Gear"
|
||||
},
|
||||
{
|
||||
"slug": "scout",
|
||||
"title": "Scout"
|
||||
},
|
||||
{
|
||||
"slug": "shaper",
|
||||
"title": "Shaper",
|
||||
"category": "Role",
|
||||
"slug": "shaper"
|
||||
"category": "Role"
|
||||
},
|
||||
{
|
||||
"slug": "shepard",
|
||||
"title": "Shepard",
|
||||
"category": "Role",
|
||||
"slug": "shepard"
|
||||
"category": "Role"
|
||||
},
|
||||
{
|
||||
"slug": "story",
|
||||
@@ -312,37 +312,37 @@
|
||||
"title": "Supply"
|
||||
},
|
||||
{
|
||||
"slug": "terrain-2",
|
||||
"title": "Terrain 2",
|
||||
"category": "Terrain",
|
||||
"slug": "terrain-2"
|
||||
"category": "Terrain"
|
||||
},
|
||||
{
|
||||
"slug": "terrain-3",
|
||||
"title": "Terrain 3",
|
||||
"category": "Terrain",
|
||||
"slug": "terrain-3"
|
||||
"category": "Terrain"
|
||||
},
|
||||
{
|
||||
"slug": "terrain-cards",
|
||||
"title": "Terrain Cards"
|
||||
},
|
||||
{
|
||||
"slug": "terrain",
|
||||
"title": "Terrain",
|
||||
"category": "Terrain",
|
||||
"slug": "terrain"
|
||||
"category": "Terrain"
|
||||
},
|
||||
{
|
||||
"slug": "totem-of-the-irix",
|
||||
"title": "Totem of the Irix",
|
||||
"category": "Gear",
|
||||
"slug": "totem-of-the-irix"
|
||||
"category": "Gear"
|
||||
},
|
||||
{
|
||||
"slug": "trade",
|
||||
"title": "Trade"
|
||||
},
|
||||
{
|
||||
"slug": "trader",
|
||||
"title": "Trader",
|
||||
"category": "Role",
|
||||
"slug": "trader"
|
||||
"category": "Role"
|
||||
},
|
||||
{
|
||||
"slug": "trail-markers",
|
||||
@@ -369,38 +369,38 @@
|
||||
"title": "Victory Condition"
|
||||
},
|
||||
{
|
||||
"slug": "wasteland-1",
|
||||
"title": "Wasteland 1",
|
||||
"category": "Region",
|
||||
"slug": "wasteland-1"
|
||||
"category": "Region"
|
||||
},
|
||||
{
|
||||
"slug": "wasteland",
|
||||
"title": "Wasteland"
|
||||
},
|
||||
{
|
||||
"slug": "water-1",
|
||||
"title": "Water 1",
|
||||
"category": "Region",
|
||||
"slug": "water-1"
|
||||
"category": "Region"
|
||||
},
|
||||
{
|
||||
"slug": "water-2",
|
||||
"title": "Water 2",
|
||||
"category": "Region",
|
||||
"slug": "water-2"
|
||||
"category": "Region"
|
||||
},
|
||||
{
|
||||
"slug": "water-3",
|
||||
"title": "Water 3",
|
||||
"category": "Region",
|
||||
"slug": "water-3"
|
||||
"category": "Region"
|
||||
},
|
||||
{
|
||||
"slug": "water-4",
|
||||
"title": "Water 4",
|
||||
"category": "Region",
|
||||
"slug": "water-4"
|
||||
"category": "Region"
|
||||
},
|
||||
{
|
||||
"slug": "water-5",
|
||||
"title": "Water 5",
|
||||
"category": "Region",
|
||||
"slug": "water-5"
|
||||
"category": "Region"
|
||||
},
|
||||
{
|
||||
"slug": "weather",
|
||||
|
||||
Reference in New Issue
Block a user