/
renderer.rb
154 lines (130 loc) · 4.12 KB
/
renderer.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# encoding: UTF-8
module Jekyll
class Renderer
attr_reader :document, :site
def initialize(site, document)
@site = site
@document = document
end
# Determine which converters to use based on this document's
# extension.
#
# Returns an array of Converter instances.
def converters
@converters ||= site.converters.select { |c| c.matches(document.extname) }
end
# Determine the extname the outputted file should have
#
# Returns the output extname including the leading period.
def output_ext
converters.first.output_ext(document.extname)
end
######################
## DAT RENDER THO
######################
def run
payload = Utils.deep_merge_hashes({
"page" => document.to_liquid
}, site.site_payload)
info = {
filters: [Jekyll::Filters],
registers: { :site => site, :page => payload['page'] }
}
# render and transform content (this becomes the final content of the object)
payload["highlighter_prefix"] = converters.first.highlighter_prefix
payload["highlighter_suffix"] = converters.first.highlighter_suffix
output = document.content
if document.render_with_liquid?
output = render_liquid(output, payload, info)
end
output = convert(output)
document.content = output
if document.place_in_layout?
place_in_layouts(
output,
payload,
info
)
else
output
end
end
# Convert the given content using the converters which match this renderer's document.
#
# content - the raw, unconverted content
#
# Returns the converted content.
def convert(content)
converters.reduce(content) do |output, converter|
begin
converter.convert output
rescue => e
Jekyll.logger.error "Conversion error:", "#{converter.class} encountered an error while converting '#{document.relative_path}':"
Jekyll.logger.error("", e.to_s)
raise e
end
end
end
# Render the given content with the payload and info
#
# content -
# payload -
# info -
# path - (optional) the path to the file, for use in ex
#
# Returns the content, rendered by Liquid.
def render_liquid(content, payload, info, path = nil)
Liquid::Template.parse(content).render!(payload, info)
rescue Tags::IncludeTagError => e
Jekyll.logger.error "Liquid Exception:", "#{e.message} in #{e.path}, included in #{path || document.relative_path}"
raise e
rescue Exception => e
Jekyll.logger.error "Liquid Exception:", "#{e.message} in #{path || document.relative_path}"
raise e
end
# Checks if the layout specified in the document actually exists
#
# layout - the layout to check
#
# Returns true if the layout is invalid, false if otherwise
def invalid_layout?(layout)
!document.data["layout"].nil? && layout.nil?
end
# Render layouts and place given content inside.
#
# content - the content to be placed in the layout
#
#
# Returns the content placed in the Liquid-rendered layouts
def place_in_layouts(content, payload, info)
output = content.dup
layout = site.layouts[document.data["layout"]]
Jekyll.logger.warn("Build Warning:", "Layout '#{document.data["layout"]}' requested in #{document.relative_path} does not exist.") if invalid_layout? layout
used = Set.new([layout])
while layout
payload = Utils.deep_merge_hashes(
payload,
{
"content" => output,
"page" => document.to_liquid,
"layout" => layout.data
}
)
output = render_liquid(
layout.content,
payload,
info,
File.join(site.config['layouts'], layout.name)
)
if layout = site.layouts[layout.data["layout"]]
if used.include?(layout)
layout = nil # avoid recursive chain
else
used << layout
end
end
end
output
end
end
end