mirror of
https://github.com/samsonjs/samhuri.net.git
synced 2026-03-25 09:05:47 +00:00
148 lines
3.9 KiB
Ruby
148 lines
3.9 KiB
Ruby
require "kramdown"
|
|
require "yaml"
|
|
require_relative "file_writer"
|
|
require_relative "../site"
|
|
require_relative "../views/layout"
|
|
require_relative "../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
|