feat(blog): add markdown blog sourced from a gitea repo
posts are markdown files with yaml frontmatter (title, slug, date;
optional draft/public) in the grenade/blog repo. the worker's new
BlogSource polls the repo — one branch-tip request when nothing
changed — and upserts posts into events with source='blog' and
occurred_at from the frontmatter date, so imported posts keep their
original publish dates and backfill the contribution graph.
- new /v1/blog and /v1/blog/{slug} endpoints over the existing
EventReader port; drafts stay hidden via the public gate
- new /blog and /blog/:slug routes, nav link, activity-feed entry
with post icon and filter toggle; relative image srcs resolve to
gitea raw urls
- shared Markdown component extracted from ProjectPage
- vite proxy target overridable via API_PROXY_TARGET for local dev
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ pub enum Source {
|
||||
Gitea,
|
||||
Hg,
|
||||
Bugzilla,
|
||||
Blog,
|
||||
}
|
||||
|
||||
impl Source {
|
||||
@@ -16,6 +17,7 @@ impl Source {
|
||||
Source::Gitea,
|
||||
Source::Hg,
|
||||
Source::Bugzilla,
|
||||
Source::Blog,
|
||||
];
|
||||
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
@@ -24,6 +26,7 @@ impl Source {
|
||||
Source::Gitea => "gitea",
|
||||
Source::Hg => "hg",
|
||||
Source::Bugzilla => "bugzilla",
|
||||
Source::Blog => "blog",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,6 +40,7 @@ impl std::str::FromStr for Source {
|
||||
"gitea" => Ok(Source::Gitea),
|
||||
"hg" => Ok(Source::Hg),
|
||||
"bugzilla" => Ok(Source::Bugzilla),
|
||||
"blog" => Ok(Source::Blog),
|
||||
other => Err(ParseSourceError(other.to_string())),
|
||||
}
|
||||
}
|
||||
@@ -204,5 +208,28 @@ pub enum TimelineIcon {
|
||||
Star,
|
||||
Release,
|
||||
Bug,
|
||||
Post,
|
||||
Generic,
|
||||
}
|
||||
|
||||
/// Blog index entry returned by `GET /v1/blog`.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct BlogPostSummary {
|
||||
pub slug: String,
|
||||
pub title: String,
|
||||
pub published_at: DateTime<Utc>,
|
||||
pub excerpt: String,
|
||||
}
|
||||
|
||||
/// Full blog post returned by `GET /v1/blog/{slug}`. The host/repo/branch
|
||||
/// triple lets the UI resolve relative image srcs to forge raw URLs.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct BlogPost {
|
||||
pub slug: String,
|
||||
pub title: String,
|
||||
pub published_at: DateTime<Utc>,
|
||||
pub markdown: String,
|
||||
pub host: String,
|
||||
pub repo: String,
|
||||
pub branch: String,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user