Wed, 28 Aug 2024 04:44:05 -0500
add assign types gopls hint too
1003 | 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 |