rdoc-generator-solarfish 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.rubocop.yml +26 -0
- data/.travis.yml +9 -0
- data/Gemfile +2 -0
- data/LICENSE +21 -0
- data/README.md +175 -0
- data/Rakefile +28 -0
- data/data/rdoc-generator-solarfish/templates/onepage.slim +110 -0
- data/data/rdoc-generator-solarfish/themes/common/fonts/LICENSE +7 -0
- data/data/rdoc-generator-solarfish/themes/common/fonts/LICENSE.Raleway +95 -0
- data/data/rdoc-generator-solarfish/themes/common/fonts/LICENSE.Roboto +201 -0
- data/data/rdoc-generator-solarfish/themes/common/fonts/Raleway-Regular.ttf +0 -0
- data/data/rdoc-generator-solarfish/themes/common/fonts/Raleway-SemiBold.ttf +0 -0
- data/data/rdoc-generator-solarfish/themes/common/fonts/Roboto-Regular.ttf +0 -0
- data/data/rdoc-generator-solarfish/themes/common/syntax/LICENSE +3 -0
- data/data/rdoc-generator-solarfish/themes/common/syntax/LICENSE.onelight +20 -0
- data/data/rdoc-generator-solarfish/themes/common/syntax/onelight.sass +47 -0
- data/data/rdoc-generator-solarfish/themes/light/main.sass +215 -0
- data/data/rdoc-generator-solarfish/themes/light.yml +16 -0
- data/docs/example.rb +142 -0
- data/docs/example_output/Raleway-Regular.ttf +0 -0
- data/docs/example_output/Raleway-SemiBold.ttf +0 -0
- data/docs/example_output/Roboto-Regular.ttf +0 -0
- data/docs/example_output/created.rid +2 -0
- data/docs/example_output/index.html +404 -0
- data/docs/example_output/index.json +428 -0
- data/docs/example_output/main.css +210 -0
- data/docs/example_output/onelight.css +22 -0
- data/lib/rdoc/discover.rb +1 -0
- data/lib/rdoc/generator/doc_loader.rb +315 -0
- data/lib/rdoc/generator/html_writer.rb +35 -0
- data/lib/rdoc/generator/json_writer.rb +16 -0
- data/lib/rdoc/generator/settings.rb +57 -0
- data/lib/rdoc/generator/solarfish.rb +135 -0
- data/lib/rdoc/generator/template_loader.rb +42 -0
- data/lib/rdoc/generator/theme_loader.rb +160 -0
- data/lib/solarfish.rb +2 -0
- data/rdoc-generator-solarfish.gemspec +31 -0
- data/test/test_generator.rb +95 -0
- data/test/test_theme_loader.rb +89 -0
- data/test/themes.rb +213 -0
- metadata +216 -0
@@ -0,0 +1,315 @@
|
|
1
|
+
# DocLoader reads RDoc documentation from RDoc store and builds a hash that
|
2
|
+
# will be passed to HTML template or written to JSON file.
|
3
|
+
class DocLoader
|
4
|
+
def initialize(options, store)
|
5
|
+
@options = options
|
6
|
+
@store = store
|
7
|
+
end
|
8
|
+
|
9
|
+
def load
|
10
|
+
build_classes
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def build_classes
|
16
|
+
classes = @store.all_classes_and_modules
|
17
|
+
|
18
|
+
classes = classes.reject do |klass|
|
19
|
+
skip_class? klass.full_name
|
20
|
+
end
|
21
|
+
|
22
|
+
class_list = classes.map do |klass|
|
23
|
+
{
|
24
|
+
id: klass.full_name.strip,
|
25
|
+
title: klass.full_name,
|
26
|
+
kind: get_class_kind(klass.full_name),
|
27
|
+
comment: get_comment(klass),
|
28
|
+
groups: build_groups(klass)
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
stable_sort_by! class_list do |klass|
|
33
|
+
klass[:id]
|
34
|
+
end
|
35
|
+
|
36
|
+
with_labels class_list
|
37
|
+
end
|
38
|
+
|
39
|
+
def build_groups(klass)
|
40
|
+
members = build_members(klass)
|
41
|
+
groups = {}
|
42
|
+
|
43
|
+
members.each do |member|
|
44
|
+
group = get_builtin_group(member)
|
45
|
+
next unless group
|
46
|
+
|
47
|
+
group_id = make_id(klass, group[:type].to_s)
|
48
|
+
|
49
|
+
unless groups.include? group_id
|
50
|
+
groups[group_id] = group.merge(
|
51
|
+
id: group_id,
|
52
|
+
members: []
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
groups[group_id][:members] << member
|
57
|
+
end
|
58
|
+
|
59
|
+
group_list = groups.values
|
60
|
+
|
61
|
+
group_list.each do |group|
|
62
|
+
stable_sort_by! group[:members] do |member|
|
63
|
+
member[:id]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
stable_sort_by! group_list do |group|
|
68
|
+
builtin_group_order.index group[:type]
|
69
|
+
end
|
70
|
+
|
71
|
+
group_list
|
72
|
+
end
|
73
|
+
|
74
|
+
def build_members(klass)
|
75
|
+
members = []
|
76
|
+
|
77
|
+
method_members = build_members_from_list klass, klass.method_list do |member|
|
78
|
+
member[:kind] = :method
|
79
|
+
end
|
80
|
+
|
81
|
+
attr_members = build_members_from_list klass, klass.attributes do |member|
|
82
|
+
member[:kind] = :attribute
|
83
|
+
end
|
84
|
+
|
85
|
+
const_members = build_members_from_list klass, klass.constants do |member|
|
86
|
+
member[:kind] = :constant
|
87
|
+
end
|
88
|
+
|
89
|
+
extends_members = build_members_from_list klass, klass.extends do |member|
|
90
|
+
member[:kind] = :extended
|
91
|
+
end
|
92
|
+
|
93
|
+
include_members = build_members_from_list klass, klass.includes do |member|
|
94
|
+
member[:kind] = :included
|
95
|
+
end
|
96
|
+
|
97
|
+
members.push(*method_members)
|
98
|
+
members.push(*attr_members)
|
99
|
+
members.push(*const_members)
|
100
|
+
members.push(*extends_members)
|
101
|
+
members.push(*include_members)
|
102
|
+
|
103
|
+
with_labels members
|
104
|
+
end
|
105
|
+
|
106
|
+
def build_members_from_list(klass, member_list)
|
107
|
+
members = []
|
108
|
+
|
109
|
+
member_list.each do |m|
|
110
|
+
next if skip_member? m.name
|
111
|
+
|
112
|
+
member = {}
|
113
|
+
|
114
|
+
member[:id] = make_id(klass, m.name)
|
115
|
+
member[:title] = get_title(m)
|
116
|
+
member[:signature] = get_signature(m)
|
117
|
+
member[:comment] = get_comment(m)
|
118
|
+
|
119
|
+
if m.respond_to? :markup_code
|
120
|
+
member[:code] = m.markup_code if m.markup_code && m.markup_code != ''
|
121
|
+
end
|
122
|
+
|
123
|
+
if m.respond_to? :type
|
124
|
+
member[:level] = m.type.to_sym if m.type
|
125
|
+
end
|
126
|
+
|
127
|
+
if m.respond_to? :visibility
|
128
|
+
member[:visibility] = m.visibility.to_sym if m.visibility
|
129
|
+
end
|
130
|
+
|
131
|
+
yield member
|
132
|
+
|
133
|
+
members << member
|
134
|
+
end
|
135
|
+
|
136
|
+
members
|
137
|
+
end
|
138
|
+
|
139
|
+
def build_labels(object)
|
140
|
+
labels = []
|
141
|
+
|
142
|
+
case object[:kind]
|
143
|
+
when :module, :class, :constant, :included, :extended
|
144
|
+
labels << {
|
145
|
+
id: object[:kind].capitalize,
|
146
|
+
title: object[:kind].to_s
|
147
|
+
}
|
148
|
+
|
149
|
+
when :method
|
150
|
+
labels << if object[:level] == :class
|
151
|
+
{
|
152
|
+
id: 'ClassMethod',
|
153
|
+
title: 'class method'
|
154
|
+
}
|
155
|
+
else
|
156
|
+
{
|
157
|
+
id: 'InstanceMethod',
|
158
|
+
title: 'instance method'
|
159
|
+
}
|
160
|
+
end
|
161
|
+
|
162
|
+
when :attribute
|
163
|
+
labels << if object[:level] == :class
|
164
|
+
{
|
165
|
+
id: 'ClassAttribute',
|
166
|
+
title: 'class attribute'
|
167
|
+
}
|
168
|
+
else
|
169
|
+
{
|
170
|
+
id: 'InstanceAttribute',
|
171
|
+
title: 'instance attribute'
|
172
|
+
}
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
if object[:visibility]
|
177
|
+
labels << {
|
178
|
+
id: object[:visibility].capitalize,
|
179
|
+
title: object[:visibility].to_s
|
180
|
+
}
|
181
|
+
end
|
182
|
+
|
183
|
+
labels
|
184
|
+
end
|
185
|
+
|
186
|
+
def with_labels(array)
|
187
|
+
array.each do |object|
|
188
|
+
object[:labels] = build_labels(object)
|
189
|
+
end
|
190
|
+
array
|
191
|
+
end
|
192
|
+
|
193
|
+
def make_id(klass, name)
|
194
|
+
klass.full_name.strip + '::' + name
|
195
|
+
end
|
196
|
+
|
197
|
+
def get_title(object)
|
198
|
+
object.name
|
199
|
+
end
|
200
|
+
|
201
|
+
def get_signature(object)
|
202
|
+
if object.respond_to? :arglists
|
203
|
+
return object.arglists if object.arglists
|
204
|
+
end
|
205
|
+
''
|
206
|
+
end
|
207
|
+
|
208
|
+
def get_comment(object)
|
209
|
+
if object.comment.respond_to? :text
|
210
|
+
object.description.strip
|
211
|
+
else
|
212
|
+
object.comment
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def get_class_kind(class_name)
|
217
|
+
if @store.all_modules.select { |m| m.full_name == class_name }.size == 1
|
218
|
+
:module
|
219
|
+
else
|
220
|
+
:class
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def builtin_group_order
|
225
|
+
%i[
|
226
|
+
ExtendedClasses
|
227
|
+
IncludedModules
|
228
|
+
Constants
|
229
|
+
ClassAttributes
|
230
|
+
ClassMethods
|
231
|
+
InstanceAttributes
|
232
|
+
InstanceMethods
|
233
|
+
]
|
234
|
+
end
|
235
|
+
|
236
|
+
def get_builtin_group(member)
|
237
|
+
case member[:kind]
|
238
|
+
when :method
|
239
|
+
case member[:level]
|
240
|
+
when :instance
|
241
|
+
{
|
242
|
+
title: 'Instance Methods',
|
243
|
+
type: :InstanceMethods,
|
244
|
+
kind: :method,
|
245
|
+
level: :instance
|
246
|
+
}
|
247
|
+
when :class
|
248
|
+
{
|
249
|
+
title: 'Class Methods',
|
250
|
+
type: :ClassMethods,
|
251
|
+
kind: :method,
|
252
|
+
level: :class
|
253
|
+
}
|
254
|
+
end
|
255
|
+
when :attribute
|
256
|
+
case member[:level]
|
257
|
+
when :instance
|
258
|
+
{
|
259
|
+
title: 'Instance Attributes',
|
260
|
+
type: :InstanceAttributes,
|
261
|
+
kind: :attribute,
|
262
|
+
level: :instance
|
263
|
+
}
|
264
|
+
when :class
|
265
|
+
{
|
266
|
+
title: 'Class Attributes',
|
267
|
+
type: :ClassAttributes,
|
268
|
+
kind: :attribute,
|
269
|
+
level: :class
|
270
|
+
}
|
271
|
+
end
|
272
|
+
when :constant
|
273
|
+
{
|
274
|
+
title: 'Constants',
|
275
|
+
type: :Constants,
|
276
|
+
kind: :constant
|
277
|
+
}
|
278
|
+
when :extended
|
279
|
+
{
|
280
|
+
title: 'Extended Classes',
|
281
|
+
type: :ExtendedClasses,
|
282
|
+
kind: :extended
|
283
|
+
}
|
284
|
+
when :included
|
285
|
+
{
|
286
|
+
title: 'Included Modules',
|
287
|
+
type: :IncludedModules,
|
288
|
+
kind: :included
|
289
|
+
}
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def stable_sort_by!(array)
|
294
|
+
sorted = array.each_with_index.sort_by do |e, n|
|
295
|
+
[yield(e), n]
|
296
|
+
end
|
297
|
+
array.replace(sorted.map(&:first))
|
298
|
+
end
|
299
|
+
|
300
|
+
def skip_class?(class_name)
|
301
|
+
if @options.sf_filter_classes
|
302
|
+
@options.sf_filter_classes.match(class_name).nil?
|
303
|
+
else
|
304
|
+
false
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
def skip_member?(member_name)
|
309
|
+
if @options.sf_filter_members
|
310
|
+
@options.sf_filter_members.match(member_name).nil?
|
311
|
+
else
|
312
|
+
false
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
# HTMLWriter builds HTML file from a template and copies HTML and
|
4
|
+
# theme files to the output directory.
|
5
|
+
class HTMLWriter
|
6
|
+
def initialize(options)
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def write(data, theme_files, template)
|
11
|
+
html = template.render(data)
|
12
|
+
install_theme(theme_files)
|
13
|
+
install_html(html)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def install_theme(theme_files)
|
19
|
+
theme_files.each do |file|
|
20
|
+
if file[:dst_name]
|
21
|
+
if file[:src_path]
|
22
|
+
FileUtils.copy_file(file[:src_path], file[:dst_name])
|
23
|
+
elsif file[:data]
|
24
|
+
File.write(file[:dst_name], file[:data])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def install_html(html)
|
31
|
+
File.open(@options.sf_htmlfile, 'w') do |file|
|
32
|
+
file.write(html)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
# JSONWriter builds JSON file and copies it to the output directory.
|
4
|
+
class JSONWriter
|
5
|
+
def initialize(options)
|
6
|
+
@options = options
|
7
|
+
end
|
8
|
+
|
9
|
+
def write(data)
|
10
|
+
json = JSON.pretty_generate(data)
|
11
|
+
|
12
|
+
File.open(@options.sf_jsonfile, 'w') do |file|
|
13
|
+
file.write(json)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
# Predefined configuration.
|
5
|
+
module Settings
|
6
|
+
DEFAULT_HTMLFILE = 'index.html'.freeze
|
7
|
+
DEFAULT_TEMPLATE = 'onepage'.freeze
|
8
|
+
DEFAULT_THEME = 'light'.freeze
|
9
|
+
|
10
|
+
def self.list_file_names(dir, ext)
|
11
|
+
data_files(dir, "*#{ext}").map do |file|
|
12
|
+
File.basename(file, ext)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.find_file(dir, ext, name)
|
17
|
+
if name.include? '/'
|
18
|
+
File.absolute_path name
|
19
|
+
else
|
20
|
+
data_files(dir, "*#{ext}").each do |file|
|
21
|
+
return file if File.basename(file, ext) == name
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.data_files(subdir, pattern)
|
27
|
+
files = []
|
28
|
+
|
29
|
+
data_dirs(subdir).each do |dir|
|
30
|
+
pattern = File.join dir, pattern
|
31
|
+
|
32
|
+
Dir[pattern].sort.map do |file|
|
33
|
+
files << file
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
files.uniq
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.data_dirs(subdir)
|
41
|
+
gemdirs = [
|
42
|
+
Pathname.new(File.join(File.dirname(__FILE__), '../../..')).cleanpath.to_s
|
43
|
+
]
|
44
|
+
Gem::Specification.each do |spec|
|
45
|
+
gemdirs << spec.full_gem_path
|
46
|
+
end
|
47
|
+
|
48
|
+
datadirs = gemdirs.map do |dir|
|
49
|
+
File.join dir, 'data', 'rdoc-generator-solarfish', subdir
|
50
|
+
end
|
51
|
+
datadirs = datadirs.select do |dir|
|
52
|
+
File.exist? dir
|
53
|
+
end
|
54
|
+
|
55
|
+
datadirs.uniq
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'rdoc/rdoc'
|
2
|
+
|
3
|
+
require_relative 'settings'
|
4
|
+
require_relative 'doc_loader'
|
5
|
+
require_relative 'theme_loader'
|
6
|
+
require_relative 'template_loader'
|
7
|
+
require_relative 'json_writer'
|
8
|
+
require_relative 'html_writer'
|
9
|
+
|
10
|
+
# SolarFish generator options.
|
11
|
+
class RDoc::Options
|
12
|
+
attr_accessor :sf_htmlfile
|
13
|
+
attr_accessor :sf_jsonfile
|
14
|
+
attr_accessor :sf_prefix
|
15
|
+
attr_accessor :sf_template
|
16
|
+
attr_accessor :sf_themes
|
17
|
+
attr_accessor :sf_filter_classes
|
18
|
+
attr_accessor :sf_filter_members
|
19
|
+
end
|
20
|
+
|
21
|
+
# SolarFish generator.
|
22
|
+
# Registers command line options and generates HTML and/or JSON output for given
|
23
|
+
# RDoc documentation and options.
|
24
|
+
class RDoc::Generator::SolarFish
|
25
|
+
RDoc::RDoc.add_generator(self)
|
26
|
+
|
27
|
+
def self.setup_options(rdoc_options)
|
28
|
+
rdoc_options.sf_htmlfile = Settings::DEFAULT_HTMLFILE
|
29
|
+
|
30
|
+
opt = rdoc_options.option_parser
|
31
|
+
opt.separator 'SolarFish generator options:'
|
32
|
+
|
33
|
+
opt.separator nil
|
34
|
+
opt.on('--sf-htmlfile=FILE', String,
|
35
|
+
'Set output HTML file name.',
|
36
|
+
"Defaults to '#{Settings::DEFAULT_HTMLFILE}'.") do |value|
|
37
|
+
rdoc_options.sf_htmlfile = value
|
38
|
+
end
|
39
|
+
|
40
|
+
opt.separator nil
|
41
|
+
opt.on('--sf-jsonfile=FILE', String,
|
42
|
+
'Set output JSON file name.',
|
43
|
+
'Empty by default.') do |value|
|
44
|
+
rdoc_options.sf_jsonfile = value
|
45
|
+
end
|
46
|
+
|
47
|
+
opt.separator nil
|
48
|
+
opt.on('--sf-template=NAME', String,
|
49
|
+
"Set template. Defaults to '#{Settings::DEFAULT_TEMPLATE}'.",
|
50
|
+
"If name contains slash, it's a path, and",
|
51
|
+
"otherwise it's a name of installed template.",
|
52
|
+
'Installed templates:',
|
53
|
+
*(TemplateLoader.templates_list
|
54
|
+
.map { |s| " - #{s}" })) do |value|
|
55
|
+
rdoc_options.sf_template = TemplateLoader.template_path(value)
|
56
|
+
end
|
57
|
+
|
58
|
+
opt.separator nil
|
59
|
+
opt.on('--sf-theme=NAME', String,
|
60
|
+
"Set theme. Defaults to '#{Settings::DEFAULT_THEME}'. Specify",
|
61
|
+
'multiple times to merge several themes. Every',
|
62
|
+
'next theme overwrites options set by previous',
|
63
|
+
"themes. If name contains slash, it's a path,",
|
64
|
+
"and otherwise it's a name of installed theme.",
|
65
|
+
'Installed themes:',
|
66
|
+
*(ThemeLoader.themes_list
|
67
|
+
.map { |s| " - #{s}" })) do |value|
|
68
|
+
rdoc_options.sf_themes ||= []
|
69
|
+
rdoc_options.sf_themes << ThemeLoader.theme_path(value)
|
70
|
+
end
|
71
|
+
|
72
|
+
opt.separator nil
|
73
|
+
opt.on('--sf-prefix=PREFIX', String,
|
74
|
+
'Set URL prefix for links to stylesheets and',
|
75
|
+
'scripts in generated HTML. Empty by default.') do |value|
|
76
|
+
rdoc_options.sf_prefix = value
|
77
|
+
end
|
78
|
+
|
79
|
+
opt.separator nil
|
80
|
+
opt.on('--sf-filter-classes=REGEX', String,
|
81
|
+
'Include only classes and modules that',
|
82
|
+
'match regex.') do |value|
|
83
|
+
rdoc_options.sf_filter_classes = Regexp.new(value)
|
84
|
+
end
|
85
|
+
|
86
|
+
opt.separator nil
|
87
|
+
opt.on('--sf-filter-members=REGEX', String,
|
88
|
+
'Include only members that match regex.') do |value|
|
89
|
+
rdoc_options.sf_filter_members = Regexp.new(value)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def initialize(store, options)
|
94
|
+
@store = store
|
95
|
+
@options = options
|
96
|
+
end
|
97
|
+
|
98
|
+
def class_dir
|
99
|
+
nil
|
100
|
+
end
|
101
|
+
|
102
|
+
def file_dir
|
103
|
+
nil
|
104
|
+
end
|
105
|
+
|
106
|
+
def generate
|
107
|
+
@options.sf_themes ||= [ThemeLoader.theme_path(Settings::DEFAULT_THEME)]
|
108
|
+
@options.sf_template ||= TemplateLoader.template_path(Settings::DEFAULT_TEMPLATE)
|
109
|
+
|
110
|
+
doc_loader = DocLoader.new(@options, @store)
|
111
|
+
classes = doc_loader.load
|
112
|
+
|
113
|
+
theme_loader = ThemeLoader.new(@options)
|
114
|
+
theme, theme_files = theme_loader.load
|
115
|
+
|
116
|
+
data = {
|
117
|
+
title: @options.title,
|
118
|
+
theme: theme,
|
119
|
+
classes: classes
|
120
|
+
}
|
121
|
+
|
122
|
+
if @options.sf_jsonfile
|
123
|
+
json_writer = JSONWriter.new(@options)
|
124
|
+
json_writer.write(data)
|
125
|
+
end
|
126
|
+
|
127
|
+
if @options.sf_htmlfile
|
128
|
+
template_loader = TemplateLoader.new(@options)
|
129
|
+
template = template_loader.load
|
130
|
+
|
131
|
+
html_writer = HTMLWriter.new(@options)
|
132
|
+
html_writer.write(data, theme_files, template)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'slim'
|
2
|
+
require 'recursive-open-struct'
|
3
|
+
|
4
|
+
require_relative 'settings'
|
5
|
+
|
6
|
+
# TemplateLoader reads a template from `.slim' file and builds a Template object
|
7
|
+
# that may render HTML given a hash with documentation and theme.
|
8
|
+
class TemplateLoader
|
9
|
+
def self.templates_list
|
10
|
+
Settings.list_file_names 'templates', '.slim'
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.template_path(name)
|
14
|
+
Settings.find_file 'templates', '.slim', name
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(options)
|
18
|
+
@options = options
|
19
|
+
end
|
20
|
+
|
21
|
+
def load
|
22
|
+
Template.new @options.sf_template
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Template allows to render HTML from a given hash with documentation and theme.
|
27
|
+
class Template
|
28
|
+
def initialize(path)
|
29
|
+
@path = path
|
30
|
+
end
|
31
|
+
|
32
|
+
def render(data)
|
33
|
+
opts = {
|
34
|
+
pretty: true
|
35
|
+
}
|
36
|
+
|
37
|
+
vars = RecursiveOpenStruct.new(data, recurse_over_arrays: true)
|
38
|
+
|
39
|
+
template = Slim::Template.new(@path, opts)
|
40
|
+
template.render(vars)
|
41
|
+
end
|
42
|
+
end
|