samhuri.net/lib/pressa/posts/repo.rb
Sami Samhuri 007b1058b6
Migrate from Swift to Ruby (#33)
Replace the Swift site generator with a Ruby and Phlex implementation.
Loads site and projects from TOML, derive site metadata from posts.

Migrate from make to bake and add standardrb and code coverage tasks.

Update CI and docs to match the new workflow, and remove unused
assets/dependencies plus obsolete tooling.
2026-02-07 21:19:03 -08:00

124 lines
3 KiB
Ruby

require "kramdown"
require "pressa/posts/models"
require "pressa/posts/metadata"
module Pressa
module Posts
class PostRepo
EXCERPT_LENGTH = 300
def initialize(output_path: "posts")
@output_path = output_path
@posts_by_year = {}
end
def read_posts(posts_dir)
enumerate_markdown_files(posts_dir) do |file_path|
post = read_post(file_path)
add_post_to_hierarchy(post)
end
PostsByYear.new(by_year: @posts_by_year)
end
private
def enumerate_markdown_files(dir, &block)
Dir.glob(File.join(dir, "**", "*.md")).each(&block)
end
def read_post(file_path)
content = File.read(file_path)
metadata = PostMetadata.parse(content)
body_markdown = content.sub(/\A---\s*\n.*?\n---\s*\n/m, "")
html_body = render_markdown(body_markdown)
slug = File.basename(file_path, ".md")
path = generate_path(slug, metadata.date)
excerpt = generate_excerpt(body_markdown)
Post.new(
slug:,
title: metadata.title,
author: metadata.author,
date: metadata.date,
formatted_date: metadata.formatted_date,
link: metadata.link,
tags: metadata.tags,
body: html_body,
excerpt:,
path:
)
end
def render_markdown(markdown)
Kramdown::Document.new(
markdown,
input: "GFM",
hard_wrap: false,
syntax_highlighter: "rouge",
syntax_highlighter_opts: {
line_numbers: false,
wrap: true
}
).to_html
end
def generate_path(slug, date)
year = date.year
month = format("%02d", date.month)
"/#{@output_path}/#{year}/#{month}/#{slug}"
end
def generate_excerpt(markdown)
text = markdown.dup
text.gsub!(/!\[[^\]]*\]\([^)]+\)/, "")
text.gsub!(/!\[[^\]]*\]\[[^\]]+\]/, "")
text.gsub!(/\[([^\]]+)\]\([^)]+\)/, '\1')
text.gsub!(/\[([^\]]+)\]\[[^\]]+\]/, '\1')
text.gsub!(/(?m)^\[[^\]]+\]:\s*\S.*$/, "")
text.gsub!(/<[^>]+>/, "")
text.gsub!(/\s+/, " ")
text.strip!
return "..." if text.empty?
"#{text[0...EXCERPT_LENGTH]}..."
end
def add_post_to_hierarchy(post)
year = post.year
month_num = post.month
@posts_by_year[year] ||= create_year_posts(year)
year_posts = @posts_by_year[year]
month_posts = year_posts.by_month[month_num]
if month_posts
updated_posts = month_posts.posts + [post]
year_posts.by_month[month_num] = MonthPosts.new(
month: month_posts.month,
posts: updated_posts
)
else
month = Month.from_date(post.date)
year_posts.by_month[month_num] = MonthPosts.new(
month:,
posts: [post]
)
end
end
def create_year_posts(year)
YearPosts.new(year:, by_month: {})
end
end
end
end