Module: Presently::Slide::Parser

Defined in:
lib/presently/slide.rb

Overview

Parses a Markdown slide file into structured data for Presently::Slide.

Handles YAML front_matter extraction, presenter note separation, and Markdown AST construction via Markly.

Class Method Summary collapse

Class Method Details

.load(path) ⇒ Object

Parse the file and return a Presently::Slide.



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/presently/slide.rb', line 68

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

.parse_sections(document) ⇒ Object

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 Fragment wrapping a document node.



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/presently/slide.rb', line 123

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