module Parser
Parses a Markdown slide file into structured data for class Presently::Slide.
Handles YAML front_matter extraction, presenter note separation, and Markdown AST construction via Markly.
Definitions
def load(path)
Parse the file and return a class Presently::Slide.
Signature
-
parameter
pathString The file path to parse.
-
returns
Slide
Implementation
def load(path)
raw = File.read(path)
# Parse once, with native front matter support.
document = Markly.parse(raw, flags: Markly::UNSAFE | Markly::FRONT_MATTER, extensions: Fragment::EXTENSIONS)
# Extract front matter from the first AST node if present.
front_matter = nil
if (front_matter_node = document.first_child) && front_matter_node.type == :front_matter
front_matter = YAML.safe_load(front_matter_node.string_content)
front_matter_node.delete
end
# Find the last hrule, which acts as the separator between slide content and presenter notes.
last_hrule = nil
document.each{|node| last_hrule = node if node.type == :hrule}
if last_hrule
notes_node = Markly::Node.new(:document)
while child = last_hrule.next
notes_node.append_child(child)
end
last_hrule.delete
# Extract the last javascript code block from the notes as the slide script.
script_node = nil
notes_node.each do |node|
if node.type == :code_block && node.fence_info.to_s.strip == "javascript"
script_node = node
end
end
script = nil
if script_node
script = script_node.string_content
script_node.delete
end
content = parse_sections(document)
notes = Fragment.new(notes_node)
else
content = parse_sections(document)
notes = nil
script = nil
end
Slide.new(path, front_matter: front_matter, content: content, notes: notes, script: script)
end
def parse_sections(document)
Parse a Markly document into content sections based on top-level headings.
Each heading becomes a named key; content before the first heading is
collected under "body". Each value is a class Presently::Slide::Fragment wrapping a document node.
Signature
-
parameter
documentMarkly::Node The document to parse.
-
returns
Hash(String, Fragment) Sections keyed by heading name.
Implementation
def parse_sections(document)
sections = {}
current_key = "body"
current_node = Markly::Node.new(:document)
document.each do |node|
if node.type == :header
sections[current_key] = Fragment.new(current_node) unless current_node.first_child.nil?
current_key = node.to_plaintext.strip.downcase.gsub(/\s+/, "_")
current_node = Markly::Node.new(:document)
else
current_node.append_child(node.dup)
end
end
sections[current_key] = Fragment.new(current_node) unless current_node.first_child.nil?
sections
end