mirror of
https://github.com/samsonjs/samhuri.net.git
synced 2026-03-25 09:05:47 +00:00
148 lines
4.1 KiB
Ruby
148 lines
4.1 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
|