cdn/app/models/doc_page.rb
2026-01-30 13:45:56 -05:00

79 lines
1.8 KiB
Ruby

# frozen_string_literal: true
class DocPage
DOCS_PATH = Rails.root.join("app/views/docs/pages")
attr_reader :id, :title, :icon, :order, :content
def initialize(id:, title:, icon:, order:, content:)
@id = id
@title = title
@icon = icon
@order = order
@content = content
end
class << self
def all
@all ||= load_all_docs.sort_by(&:order)
end
def find(id)
all.find { |doc| doc.id == id } || raise(ActiveRecord::RecordNotFound, "Doc '#{id}' not found")
end
def reload!
@all = nil
end
private
def load_all_docs
Dir.glob(DOCS_PATH.join("*.md")).map do |file|
parse_doc_file(file)
end
end
def parse_doc_file(file)
id = File.basename(file, ".md")
raw_content = File.read(file)
frontmatter, content = extract_frontmatter(raw_content)
new(
id: id,
title: frontmatter["title"] || id.titleize,
icon: (frontmatter["icon"] || "file").to_sym,
order: frontmatter["order"] || 999,
content: render_markdown(content)
)
end
def extract_frontmatter(content)
if content.start_with?("---")
parts = content.split("---", 3)
if parts.length >= 3
frontmatter = YAML.safe_load(parts[1]) || {}
return [ frontmatter, parts[2].strip ]
end
end
[ {}, content ]
end
def render_markdown(content)
renderer = Redcarpet::Render::HTML.new(
hard_wrap: true,
link_attributes: { target: "_blank", rel: "noopener" }
)
markdown = Redcarpet::Markdown.new(
renderer,
autolink: true,
tables: true,
fenced_code_blocks: true,
strikethrough: true,
highlight: true,
footnotes: true
)
markdown.render(content)
end
end
end