|
1 module DataEmbed |
|
2 module_function |
|
3 |
|
4 # Returns a hash of filename => content read from the DATA section of a given |
|
5 # source, or the caller. Does not cache for you. If given a handle, it is |
|
6 # read; a string, used as a file path to read; a module or class, its file is |
|
7 # guessed using +const_source_location+. |
|
8 # |
|
9 # Note: This isn't careful with encoding. A battle-tested version of this |
|
10 # that should be okay with encodings can be found in Sinatra. |
|
11 # |
|
12 # @example Read my own data section |
|
13 # files = DataEmbed.data_section(__FILE__) |
|
14 # |
|
15 # @example A specific module |
|
16 # files = DataEmbed.data_section(Some::Class) |
|
17 # |
|
18 # @example The DATA global (only opened for $0 unlike perl) |
|
19 # files = DataEmbed.data_section(DATA) |
|
20 # |
|
21 # @param source [Module, String, #read] |
|
22 # @return [{String => String}] |
|
23 def data_section(source) |
|
24 data = |
|
25 case source |
|
26 when Module |
|
27 File.read(Object.const_source_location(source.name)[0]) |
|
28 when String |
|
29 File.read(source) |
|
30 else |
|
31 source.read |
|
32 end |
|
33 |
|
34 data |
|
35 .split(/^__END__$/, 2) |
|
36 .last |
|
37 .split(/^@@\s*(.+?)\s*\r?\n/m) |
|
38 .tap { _1.shift if _1.length.odd? } |
|
39 .each_slice(2) |
|
40 .to_h |
|
41 .transform_values { _1.gsub(/\n+\z/, "\n") } |
|
42 end |
|
43 |
|
44 # Process the given tmpl using ERB, with % trim enabled. Either a binding or |
|
45 # a hash may be given. Only locals are available to the template if a hash |
|
46 # is used. |
|
47 # |
|
48 # @param tmpl [String] |
|
49 # @param vars [Binding, Hash] |
|
50 # @return [String] |
|
51 def process_template(tmpl, vars) |
|
52 require "erb" |
|
53 |
|
54 ERB |
|
55 .new(tmpl, trim_mode: "%") |
|
56 .public_send(vars.is_a?(Binding) ? :result : :result_with_hash, vars) |
|
57 end |
|
58 |
|
59 # Process templates in both keys and values of the given hash |
|
60 # |
|
61 # @param data [{String => String}] |
|
62 # @param vars [Binding, Hash] |
|
63 # @return [{String => String}] |
|
64 def process_templates(data, vars) |
|
65 data |
|
66 .transform_keys { process_template(_1, vars) } |
|
67 .transform_values! { process_template(_1, vars) } |
|
68 end |
|
69 end |