mirror of
https://github.com/samsonjs/samhuri.net.git
synced 2026-03-25 09:05:47 +00:00
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.
148 lines
3.9 KiB
Ruby
148 lines
3.9 KiB
Ruby
require "kramdown"
|
|
require "yaml"
|
|
require "pressa/utils/file_writer"
|
|
require "pressa/site"
|
|
require "pressa/views/layout"
|
|
require "pressa/views/icons"
|
|
|
|
module Pressa
|
|
module Utils
|
|
class MarkdownRenderer
|
|
EXCERPT_LENGTH = 300
|
|
|
|
def can_render_file?(filename:, extension:)
|
|
extension == "md"
|
|
end
|
|
|
|
def render(site:, file_path:, target_dir:)
|
|
content = File.read(file_path)
|
|
metadata, body_markdown = parse_content(content)
|
|
|
|
html_body = render_markdown(body_markdown)
|
|
|
|
page_title = presence(metadata["Title"]) || File.basename(file_path, ".md").capitalize
|
|
page_type = presence(metadata["Page type"]) || "website"
|
|
page_description = presence(metadata["Description"]) || generate_excerpt(body_markdown)
|
|
show_extension = ["true", "yes", true].include?(metadata["Show extension"])
|
|
|
|
slug = File.basename(file_path, ".md")
|
|
|
|
relative_dir = File.dirname(file_path).sub(/^.*?\/public\/?/, "")
|
|
relative_dir = "" if relative_dir == "."
|
|
|
|
canonical_path = if show_extension
|
|
"/#{relative_dir}/#{slug}.html".squeeze("/")
|
|
else
|
|
"/#{relative_dir}/#{slug}/".squeeze("/")
|
|
end
|
|
|
|
html = render_layout(
|
|
site:,
|
|
page_subtitle: page_title,
|
|
canonical_url: site.url_for(canonical_path),
|
|
body: html_body,
|
|
page_description:,
|
|
page_type:
|
|
)
|
|
|
|
output_filename = if show_extension
|
|
"#{slug}.html"
|
|
else
|
|
File.join(slug, "index.html")
|
|
end
|
|
|
|
output_path = File.join(target_dir, output_filename)
|
|
FileWriter.write(path: output_path, content: html)
|
|
end
|
|
|
|
private
|
|
|
|
def parse_content(content)
|
|
if content =~ /\A---\s*\n(.*?)\n---\s*\n(.*)/m
|
|
yaml_content = $1
|
|
markdown = $2
|
|
metadata = YAML.safe_load(yaml_content) || {}
|
|
[metadata, markdown]
|
|
else
|
|
[{}, content]
|
|
end
|
|
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 render_layout(site:, page_subtitle:, canonical_url:, body:, page_description:, page_type:)
|
|
layout = Views::Layout.new(
|
|
site:,
|
|
page_subtitle:,
|
|
canonical_url:,
|
|
page_description:,
|
|
page_type:,
|
|
content: PageView.new(page_title: page_subtitle, body:)
|
|
)
|
|
|
|
layout.call
|
|
end
|
|
|
|
class PageView < Phlex::HTML
|
|
def initialize(page_title:, body:)
|
|
@page_title = page_title
|
|
@body = body
|
|
end
|
|
|
|
def view_template
|
|
article(class: "container") do
|
|
h1 { @page_title }
|
|
raw(safe(@body))
|
|
end
|
|
|
|
div(class: "row clearfix") do
|
|
p(class: "fin") do
|
|
raw(safe(Views::Icons.code))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def generate_excerpt(markdown)
|
|
text = markdown.dup
|
|
|
|
# Drop inline and reference-style images before links are simplified.
|
|
text.gsub!(/!\[[^\]]*\]\([^)]+\)/, "")
|
|
text.gsub!(/!\[[^\]]*\]\[[^\]]+\]/, "")
|
|
|
|
# Replace inline and reference links with just their text.
|
|
text.gsub!(/\[([^\]]+)\]\([^)]+\)/, '\1')
|
|
text.gsub!(/\[([^\]]+)\]\[[^\]]+\]/, '\1')
|
|
|
|
# Remove link reference definitions such as: [foo]: http://example.com
|
|
text.gsub!(/(?m)^\[[^\]]+\]:\s*\S.*$/, "")
|
|
|
|
text.gsub!(/<[^>]+>/, "")
|
|
text.gsub!(/\s+/, " ")
|
|
text.strip!
|
|
|
|
return nil if text.empty?
|
|
|
|
"#{text[0...EXCERPT_LENGTH]}..."
|
|
end
|
|
|
|
def presence(value)
|
|
return value unless value.respond_to?(:strip)
|
|
|
|
stripped = value.strip
|
|
stripped.empty? ? nil : stripped
|
|
end
|
|
end
|
|
end
|
|
end
|