add oauth
Some checks are pending
Deploy ailog / build-and-deploy (push) Waiting to run

This commit is contained in:
2025-06-08 06:42:10 +09:00
parent c0e4dc63ea
commit 637028c264
65 changed files with 9101 additions and 804 deletions

View File

@ -94,6 +94,46 @@ impl Generator {
fs::copy(path, &dest_path)?;
}
}
// Copy files from atproto-auth-widget dist (if available)
let widget_dist = self.base_path.join("atproto-auth-widget/dist");
if widget_dist.exists() {
for entry in WalkDir::new(&widget_dist).min_depth(1) {
let entry = entry?;
let path = entry.path();
let relative_path = path.strip_prefix(&widget_dist)?;
let dest_path = public_dir.join(relative_path);
if path.is_dir() {
fs::create_dir_all(&dest_path)?;
} else {
if let Some(parent) = dest_path.parent() {
fs::create_dir_all(parent)?;
}
fs::copy(path, &dest_path)?;
}
}
println!("{} widget files from dist", "Copied".yellow());
}
// Handle client-metadata.json based on environment (fallback)
let is_production = std::env::var("PRODUCTION").unwrap_or_default() == "true";
let metadata_dest = public_dir.join("client-metadata.json");
// First try to get from widget dist (preferred)
let widget_metadata = widget_dist.join("client-metadata.json");
if widget_metadata.exists() {
fs::copy(&widget_metadata, &metadata_dest)?;
println!("{} client-metadata.json from widget", "Using".yellow());
} else if is_production {
// Fallback to local static files
let prod_metadata = static_dir.join("client-metadata-prod.json");
if prod_metadata.exists() {
fs::copy(&prod_metadata, &metadata_dest)?;
println!("{} production client-metadata.json (fallback)", "Using".yellow());
}
}
println!("{} static files", "Copied".cyan());
}
@ -144,11 +184,16 @@ impl Generator {
let html_content = self.markdown_processor.render(&content)?;
let slug = path
.file_stem()
.and_then(|s| s.to_str())
.unwrap_or("post")
.to_string();
// Use slug from frontmatter if available, otherwise derive from filename
let slug = frontmatter.get("slug")
.and_then(|v| v.as_str())
.map(|s| s.to_string())
.unwrap_or_else(|| {
path.file_stem()
.and_then(|s| s.to_str())
.unwrap_or("post")
.to_string()
});
let mut post = Post {
title: frontmatter.get("title")
@ -211,7 +256,34 @@ impl Generator {
}
async fn generate_index(&self, posts: &[Post]) -> Result<()> {
let context = self.template_engine.create_context(&self.config, posts)?;
// Enhance posts with additional metadata for timeline view
let enhanced_posts: Vec<serde_json::Value> = posts.iter().map(|post| {
let excerpt = self.extract_excerpt(&post.content);
let markdown_url = format!("/posts/{}.md", post.slug);
let translation_url = if let Some(ref translations) = post.translations {
translations.first().map(|t| t.url.clone())
} else {
None
};
serde_json::json!({
"title": post.title,
"date": post.date,
"content": post.content,
"slug": post.slug,
"url": post.url,
"tags": post.tags,
"excerpt": excerpt,
"markdown_url": markdown_url,
"translation_url": translation_url,
"language": self.config.site.language
})
}).collect();
let mut context = tera::Context::new();
context.insert("config", &self.config.site);
context.insert("posts", &enhanced_posts);
let html = self.template_engine.render("index.html", &context)?;
let output_path = self.base_path.join("public/index.html");
@ -223,7 +295,33 @@ impl Generator {
async fn generate_post_page(&self, post: &Post) -> Result<()> {
let mut context = tera::Context::new();
context.insert("config", &self.config.site);
context.insert("post", post);
// Create enhanced post with additional URLs
let mut enhanced_post = post.clone();
enhanced_post.url = format!("/posts/{}.html", post.slug);
// Add markdown view URL
let markdown_url = format!("/posts/{}.md", post.slug);
// Add translation URLs if available
let translation_urls: Vec<String> = if let Some(ref translations) = post.translations {
translations.iter().map(|t| t.url.clone()).collect()
} else {
Vec::new()
};
context.insert("post", &serde_json::json!({
"title": enhanced_post.title,
"date": enhanced_post.date,
"content": enhanced_post.content,
"slug": enhanced_post.slug,
"url": enhanced_post.url,
"tags": enhanced_post.tags,
"ai_comment": enhanced_post.ai_comment,
"markdown_url": markdown_url,
"translation_url": translation_urls.first(),
"language": self.config.site.language
}));
let html = self.template_engine.render_with_context("post.html", &context)?;
@ -232,6 +330,9 @@ impl Generator {
let output_path = output_dir.join(format!("{}.html", post.slug));
fs::write(output_path, html)?;
// Generate markdown view
self.generate_markdown_view(post).await?;
Ok(())
}
@ -260,6 +361,72 @@ impl Generator {
Ok(())
}
fn extract_excerpt(&self, html_content: &str) -> String {
// Simple excerpt extraction - take first 200 characters of text content
let text_content = html_content
.replace("<p>", "")
.replace("</p>", " ")
.replace("<br>", " ")
.replace("<br/>", " ");
// Remove HTML tags with a simple regex-like approach
let mut text = String::new();
let mut in_tag = false;
for ch in text_content.chars() {
match ch {
'<' => in_tag = true,
'>' => in_tag = false,
_ if !in_tag => text.push(ch),
_ => {}
}
}
let excerpt = text.trim().chars().take(200).collect::<String>();
if text.len() > 200 {
format!("{}...", excerpt)
} else {
excerpt
}
}
async fn generate_markdown_view(&self, post: &Post) -> Result<()> {
// Find original markdown file
let posts_dir = self.base_path.join("content/posts");
// Try to find the markdown file by checking all files in posts directory
for entry in fs::read_dir(&posts_dir)? {
let entry = entry?;
let path = entry.path();
if let Some(extension) = path.extension() {
if extension == "md" {
let content = fs::read_to_string(&path)?;
let (frontmatter, _) = self.markdown_processor.parse_frontmatter(&content)?;
// Check if this file has the same slug
let file_slug = frontmatter.get("slug")
.and_then(|v| v.as_str())
.unwrap_or_else(|| {
path.file_stem()
.and_then(|s| s.to_str())
.unwrap_or("")
});
if file_slug == post.slug {
let output_dir = self.base_path.join("public/posts");
fs::create_dir_all(&output_dir)?;
let output_path = output_dir.join(format!("{}.md", post.slug));
fs::write(output_path, content)?;
break;
}
}
}
}
Ok(())
}
}
#[derive(Debug, Clone, serde::Serialize)]