Compare commits

..

No commits in common. "81ac6fde22ad4a1606a43cb1da9e79a93692db71" and "05d1dcda4db1be61e9f2b00caa3dc3c14ed33e78" have entirely different histories.

14 changed files with 28 additions and 262 deletions

View file

@ -1,7 +1,7 @@
--- ---
title: "Minecraft: Bedrock Edition on Waydroid" title: "Minecraft: Bedrock Edition on Waydroid"
description: "A guide to running Minecraft: Bedrock Edition on Linux with Waydroid" description: "A guide to running Minecraft: Bedrock Edition on Linux with Waydroid"
published: 2024-02-29T21:00:00.000+10:00 published: 2024-02-29
edited: 2024-04-24T15:03:00.000+10:00 edited: 2024-04-24T15:03:00.000+10:00
footer: cc_by footer: cc_by
header: header.webp header: header.webp

View file

@ -1,7 +1,7 @@
--- ---
title: Comparison of Misskey Forks title: Comparison of Misskey Forks
description: The Misskey family of Fediverse servers is quite large. While they all share a common origin there are some notable feature differences between them. description: The Misskey family of Fediverse servers is quite large. While they all share a common origin there are some notable feature differences between them.
published: 2024-02-02T21:47:00.000+10:00 published: 2024-02-02
edited: 2025-02-10T19:24:00.000+10:00 edited: 2025-02-10T19:24:00.000+10:00
footer: cc_by footer: cc_by
header: banner.webp header: banner.webp
@ -616,3 +616,20 @@ Brief descriptions of each feature listed above. I'm keeping them vague as they
- [@privateger@plasmatrap.com](https://plasmatrap.com/@privateger") - [@privateger@plasmatrap.com](https://plasmatrap.com/@privateger")
- [@vavency@kitsunes.club](https://kitsunes.club/@vavency") - [@vavency@kitsunes.club](https://kitsunes.club/@vavency")
- [@Weeble@bungle.online](https://bungle.online/@Weeble") - [@Weeble@bungle.online](https://bungle.online/@Weeble")
<style>
.table-y {
background-color: var(--success);
color: black;
}
.table-p {
background-color: var(--warn);
color: black;
}
.table-n {
background-color: var(--error);
color: black;
}
</style>

View file

@ -5,7 +5,6 @@
<meta charset="utf-8"/> <meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<base href="/"/> <base href="/"/>
<meta name="theme-color" content="#b462cbff">
@* Icons *@ @* Icons *@
<link rel="icon" type="image/webp" href="@Assets["icon.webp"]"> <link rel="icon" type="image/webp" href="@Assets["icon.webp"]">

View file

@ -3,17 +3,11 @@
@if (Post != null) @if (Post != null)
{ {
<HeadContent>
<OpenGraph UrlPath="@Post.Slug" Title="@Post.Title" Description="@Post.Description"
ImagePath="@($"post-assets/{Post.Slug}/{Post.HeaderFilename}")" ImageAlt="@Post.HeaderAlt" LargeImage="true"/>
</HeadContent>
<SectionContent SectionName="Header"> <SectionContent SectionName="Header">
@if (Post.HeaderFilename != null) @if (Post.HeaderFilename != null)
{ {
<figure class="header"> <figure class="header">
<img src="@Assets[$"post-assets/{Post.Slug}/{Post.HeaderFilename}"]" alt="@Post.HeaderAlt" <img src="@Assets[$"post-assets/{Post.Slug}/{Post.HeaderFilename}"]" alt="@Post.HeaderAlt" class="header-img">
class="header-img">
@if (Post.HeaderCaption != null) @if (Post.HeaderCaption != null)
{ {
<figcaption>@Post.HeaderCaption</figcaption> <figcaption>@Post.HeaderCaption</figcaption>
@ -27,18 +21,14 @@
{ {
var edited = Post.Edited ?? DateTime.Now; // this null check should never happen var edited = Post.Edited ?? DateTime.Now; // this null check should never happen
<small> <small>
Posted: Posted: <RenderDateOnly Dateonly="Post.Published"/>
<RenderDateTime Datetime="@Post.Published"/>
&bull; &bull;
Latest edit: Latest edit: <RenderDateTime Datetime="@(edited)"/>
<RenderDateTime Datetime="@edited"/>
</small> </small>
} }
else else
{ {
<small>Posted: <small>Posted: <RenderDateOnly Dateonly="Post.Published"/></small>
<RenderDateTime Datetime="@Post.Published"/>
</small>
} }
<hr> <hr>
</div> </div>
@ -46,8 +36,6 @@
} }
else else
{ {
<PageTitle>Not found</PageTitle>
<main id="main-content" class="container"> <main id="main-content" class="container">
<h1>Not found</h1> <h1>Not found</h1>
<p>Page not found</p> <p>Page not found</p>
@ -98,5 +86,4 @@ else
Post = BlogPosts.Posts.FirstOrDefault(p => p.Slug == Slug); Post = BlogPosts.Posts.FirstOrDefault(p => p.Slug == Slug);
} }
} }

View file

@ -4,14 +4,7 @@
@using PancakesWeb.Data @using PancakesWeb.Data
@using PancakesWeb.Schema @using PancakesWeb.Schema
<HeadContent> <PageTitle>Home</PageTitle>
@* Feeds *@
<link rel="alternate" type="application/atom+xml" href="/feed.atom"/>
<link rel="alternate" type="application/feed+json" href="/feed.json"/>
<OpenGraph UrlPath="" Title="Home"
Description="I'm a cat enby (they/it) from Australia that likes cats, Linux, and programming"/>
</HeadContent>
<main id="main-content" class="container"> <main id="main-content" class="container">
<h1 id="pancakes">pancakes</h1> <h1 id="pancakes">pancakes</h1>

View file

@ -8,14 +8,14 @@
{ {
var edited = post.Edited ?? DateTime.Now; // this null check should never happen var edited = post.Edited ?? DateTime.Now; // this null check should never happen
<small> <small>
Posted: <RenderDateTime Datetime="post.Published"/> Posted: <RenderDateOnly Dateonly="post.Published"/>
&bull; &bull;
Edited: <RenderDateTime Datetime="@(edited)"/> Edited: <RenderDateTime Datetime="@(edited)"/>
</small> </small>
} }
else else
{ {
<small>Posted: <RenderDateTime Datetime="post.Published"/></small> <small>Posted: <RenderDateOnly Dateonly="post.Published"/></small>
} }
</li> </li>
} }

View file

@ -33,7 +33,7 @@ public partial class BlogPosts : ComponentBase
public string Title = null!; public string Title = null!;
public string Description = null!; public string Description = null!;
public DateTime Published = DateTime.Today; public DateOnly Published = DateOnly.MinValue;
public DateTime? Edited; public DateTime? Edited;
public PostFooter? Footer; public PostFooter? Footer;
public string? HeaderFilename; public string? HeaderFilename;
@ -98,7 +98,7 @@ public partial class BlogPosts : ComponentBase
public string? HeaderAlt { get; set; } public string? HeaderAlt { get; set; }
public string? HeaderCaption { get; set; } public string? HeaderCaption { get; set; }
public PostFooter? Footer { get; set; } public PostFooter? Footer { get; set; }
public DateTime Published { get; set; } public DateOnly Published { get; set; }
public DateTime? Edited { get; set; } public DateTime? Edited { get; set; }
} }

View file

@ -1,31 +0,0 @@
<PageTitle>@Title - pancakes</PageTitle>
<meta name="description" content="@Description"/>
<meta property="og:url" content="https://pancakes.gay/@UrlPath">
<meta property="og:site_name" content="pancakes">
<meta property="og:title" content="@Title">
<meta property="og:description" content="@Description">
<meta property="og:image" content="@(Assets[ImagePath ?? "icon.webp"])">
@if (ImageAlt != null)
{
<meta property="og:image:alt" content="@ImageAlt">
}
@if (LargeImage)
{
<meta property="og:type" content="article">
<meta property="twitter:card" content="summary_large_image">
}
else
{
<meta property="og:type" content="website">
}
<meta name="fediverse:creator" content="@@pancakes@meow.company">
@code {
[Parameter, EditorRequired] public required string UrlPath { get; set; }
[Parameter, EditorRequired] public required string Title { get; set; }
[Parameter] public string? Description { get; set; }
[Parameter] public string? ImagePath { get; set; }
[Parameter] public string? ImageAlt { get; set; }
[Parameter] public bool LargeImage { get; set; }
}

View file

@ -1,171 +0,0 @@
using System.Net.Mime;
using System.ServiceModel.Syndication;
using System.Text.Json.Serialization;
using System.Xml;
using Microsoft.AspNetCore.Mvc;
using PancakesWeb.Components.UI;
using J = System.Text.Json.Serialization.JsonPropertyNameAttribute;
using JI = System.Text.Json.Serialization.JsonIgnoreAttribute;
namespace PancakesWeb.Controllers;
[ApiController]
public class FeedController : ControllerBase
{
[HttpGet("/feed.atom")]
[Produces("application/atom+xml")]
public ContentResult GetAtomFeed()
{
var feed = new SyndicationFeed
{
Title = new TextSyndicationContent("pancakes' blog"),
Description = new TextSyndicationContent("🐈‍⬛"),
Id = "https://pancakes.gay/feed.atom",
BaseUri = new Uri("https://pancakes.gay/feed.atom"),
Authors = { new SyndicationPerson("p@pancakes.gay", "pancakes", "https://pancakes.gay") },
Items = BlogPosts.Posts.OrderByDescending(post => post.Published).Select(post =>
new SyndicationItem(post.Title, SyndicationContent.CreateHtmlContent(post.Content),
new Uri($"https://pancakes.gay/{post.Slug}"), $"https://pancakes.gay/{post.Slug}",
new DateTimeOffset(post.Edited ?? post.Published))
{
Copyright = post.Footer is BlogPosts.PostFooter.CcBy
? new TextSyndicationContent(
$"{post.Title} © {post.Published.Year} by pancakes is licensed under CC BY 4.0")
: null,
PublishDate = new DateTimeOffset(post.Published),
Summary = new TextSyndicationContent(post.Description)
}),
Links =
{
SyndicationLink.CreateSelfLink(new Uri("https://pancakes.gay/feed.atom")),
SyndicationLink.CreateAlternateLink(new Uri("https://pancakes.gay"), MediaTypeNames.Text.Html),
}
};
var stringWriter = new StringWriter();
var writer = new XmlTextWriter(stringWriter);
feed.SaveAsAtom10(writer);
return Content(stringWriter.ToString(), "application/atom+xml");
}
[HttpGet("/feed.json")]
[Produces("application/feed+json", MediaTypeNames.Application.Json)]
public JsonFeed GetJsonFeed() => new JsonFeed
{
Title = "pancakes' blog",
HomePageUrl = "https://pancakes.gay",
FeedUrl = "https://pancakes.gay/feed.json",
Description = "🐈‍⬛",
Icon = "https://pancakes.gay/icon.webp",
Favicon = "https://pancakes.gay/favicon.ico",
Authors =
[
new JsonFeedAuthor
{
Name = "pancakes",
Url = "https://pancakes.gay",
Avatar = "https://pancakes.gay/icon.webp"
}
],
Language = "en",
Items = BlogPosts.Posts.OrderByDescending(post => post.Published).Select(post => new JsonFeedItem
{
Id = $"https://pancakes.gay/{post.Slug}",
Url = $"https://pancakes.gay/{post.Slug}",
Title = post.Title,
ContentHtml = post.Content,
Summary = post.Description,
BannerImage = $"https://pancakes.gay/post-assets/{post.Slug}/{post.HeaderFilename}",
DatePublished = post.Published,
DateModified = post.Edited,
Tags = null
}).ToList()
};
public class JsonFeed
{
[J("version")] public string Version => "https://jsonfeed.org/version/1.1";
[J("title")] public required string Title { get; set; }
[J("home_page_url")]
[JI(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? HomePageUrl { get; set; }
[J("feed_url")]
[JI(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? FeedUrl { get; set; }
[J("description")]
[JI(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Description { get; set; }
[J("icon")]
[JI(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Icon { get; set; }
[J("favicon")]
[JI(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Favicon { get; set; }
[J("authors")]
[JI(Condition = JsonIgnoreCondition.WhenWritingNull)]
public List<JsonFeedAuthor>? Authors { get; set; }
[J("language")]
[JI(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Language { get; set; }
[J("items")] public List<JsonFeedItem> Items { get; set; } = [];
}
public class JsonFeedAuthor
{
[J("name")]
[JI(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Name { get; set; }
[J("url")]
[JI(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Url { get; set; }
[J("avatar")]
[JI(Condition = JsonIgnoreCondition.Never)]
public string? Avatar { get; set; }
}
public class JsonFeedItem
{
[J("id")] public required string Id { get; set; }
[J("url")]
[JI(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Url { get; set; }
[J("title")]
[JI(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Title { get; set; }
[J("content_html")] public required string ContentHtml { get; set; }
[J("summary")]
[JI(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Summary { get; set; }
[J("banner_image")]
[JI(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? BannerImage { get; set; }
[J("date_published")]
[JI(Condition = JsonIgnoreCondition.WhenWritingNull)]
public DateTime? DatePublished { get; set; }
[J("date_modified")]
[JI(Condition = JsonIgnoreCondition.WhenWritingNull)]
public DateTime? DateModified { get; set; }
[J("tags")]
[JI(Condition = JsonIgnoreCondition.WhenWritingNull)]
public List<string>? Tags { get; set; }
}
}

View file

@ -187,12 +187,6 @@ public static class Buttons
{ {
Image = "wii.webp", Image = "wii.webp",
Title = "Wii" Title = "Wii"
},
new Button
{
Image = "valid_atom.webp",
Title = "Valid Atom 1.0",
Href = "/feed.atom"
} }
]; ];
} }

View file

@ -8,12 +8,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Markdig" Version="0.42.0" /> <PackageReference Include="Markdig" Version="0.42.0" />
<PackageReference Include="System.ServiceModel.Syndication" Version="9.0.9" />
<PackageReference Include="YamlDotNet" Version="16.3.0" /> <PackageReference Include="YamlDotNet" Version="16.3.0" />
</ItemGroup> </ItemGroup>
<Target Name="_RemovePublishDirBeforePublishing" BeforeTargets="BeforePublish">
<RemoveDir Directories="$(PublishDir)" Condition="'$(PublishDir)' != ''" />
</Target>
</Project> </Project>

View file

@ -6,7 +6,6 @@ var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorComponents() builder.Services.AddRazorComponents()
.AddInteractiveServerComponents(); .AddInteractiveServerComponents();
builder.Services.AddHttpClient(); builder.Services.AddHttpClient();
builder.Services.AddControllers();
builder.Configuration.AddEnvironmentVariables(); builder.Configuration.AddEnvironmentVariables();
@ -33,6 +32,5 @@ app.UseAntiforgery();
app.MapStaticAssets(); app.MapStaticAssets();
app.MapRazorComponents<App>() app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode(); .AddInteractiveServerRenderMode();
app.MapControllers();
app.Run(); app.Run();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

View file

@ -222,21 +222,6 @@ pre code:hover + .copy-code-button, .copy-code-button:hover {
height: 1.5em; height: 1.5em;
} }
.table-y {
background-color: var(--success);
color: black;
}
.table-p {
background-color: var(--warn);
color: black;
}
.table-n {
background-color: var(--error);
color: black;
}
@keyframes title-fade-in { @keyframes title-fade-in {
0% { 0% {
margin-top: 0; margin-top: 0;