homura-runtime 0.3.6 → 0.3.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6fac4160687b6043e752f8d18ba217e5eb53dcb1efa16158f2b8409da7e26d39
4
- data.tar.gz: 57386658268ff69b225ebbb3fac5a9400c702783c384eb9fec117fc6a315cbf5
3
+ metadata.gz: 5d20bdc2e926b60f96a8a50afbb7274cfa38d700d08d036bce728fc07e46797a
4
+ data.tar.gz: e624fd81ebd4062d2def3d14232963d818d9e638f8aae83f33e6266f12962f4d
5
5
  SHA512:
6
- metadata.gz: 50fd0246537d673f1211066e3aa1a443f8f50cbb33bdfd5197a70cf9786c67a401b8109646189eb16af3d33cd0c936420a9f93d7a7e2dec327221062705c1048
7
- data.tar.gz: 075e7b5786548a85a3bb90f7ee451c4288ec5a759597942ae92df797bcc39be453d3e80b2e9a4c619462b469c009453942022e6930fb938766d475e07565d19a
6
+ metadata.gz: 97805f4a9a5de8192b3732ab8fef5786e8cf60cdd4931e82c91aae417b9ce6def91982a4fe9100cd785c4e23b933c1971b9e7b6c8057dbfaf34fa133a2dafcf0
7
+ data.tar.gz: 73023936543efd1172a3c4154b59531374e4babc5990980e3303c233335318c0047080a0c88dcb297d2e60ba2d6f57be0c2c353a087ba1055a096ea2fa4fc49b
data/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.8 (2026-05-06)
4
+
5
+ - Discover and attach arbitrary Durable Object bindings from `env`, not just
6
+ the built-in `COUNTER` demo binding. This lets app code use
7
+ `durable_object(:voice_limit, ...)` and other custom DO names without
8
+ gem-side shims.
9
+ - `examples/ai-voice-chat` now uses that generic DO binding path for its
10
+ daily request cap.
11
+
12
+ ## 0.3.7 (2026-05-06)
13
+
14
+ - Add Ruby-shaped Workers AI helpers for the staged voice examples:
15
+ `ai.chat`, `ai.chat_text`, `ai.transcribe`, `ai.transcribe_text`,
16
+ `ai.speak`, and `ai.speak_data_url`.
17
+ - `ai.speak` returns a `Cloudflare::BinaryBody`, so a Sinatra route can
18
+ stream Aura audio directly back to the browser without exposing JS
19
+ response plumbing in user code.
20
+ - Register the new AI helpers with auto-await so example/source Ruby stays
21
+ sync-shaped.
22
+
3
23
  ## 0.3.6 (2026-05-03)
4
24
 
5
25
  - Release the no-await-surface examples/docs baseline: public Rack,
data/exe/auto-await CHANGED
@@ -13,34 +13,47 @@
13
13
  # output directory earlier on the Opal load path and fall back to
14
14
  # the original input for unchanged files.
15
15
 
16
- require 'fileutils'
17
- require 'pathname'
18
- require_relative '../lib/homura/runtime/build_support'
16
+ require "fileutils"
17
+ require "pathname"
18
+ require_relative "../lib/homura/runtime/build_support"
19
19
 
20
20
  # homura-runtime lib path resolution (with legacy alias fallback)
21
- runtime_lib = ENV['CFW_RUNTIME_LIB']
21
+ runtime_lib = ENV["CFW_RUNTIME_LIB"]
22
22
  unless runtime_lib
23
- runtime_lib = HomuraRuntime::BuildSupport.runtime_root(current_file: __FILE__).join('lib').to_s
23
+ runtime_lib =
24
+ HomuraRuntime::BuildSupport
25
+ .runtime_root(current_file: __FILE__)
26
+ .join("lib")
27
+ .to_s
24
28
  end
25
29
  $LOAD_PATH.unshift(runtime_lib) unless $LOAD_PATH.include?(runtime_lib)
26
30
 
27
- require 'homura/runtime/async_registry'
28
- require 'homura/runtime/auto_await/analyzer'
29
- require 'homura/runtime/auto_await/transformer'
31
+ require "homura/runtime/async_registry"
32
+ require "homura/runtime/auto_await/analyzer"
33
+ require "homura/runtime/auto_await/transformer"
30
34
 
31
- options = { input: nil, output: nil, debug: ENV['CLOUDFLARE_WORKERS_AUTO_AWAIT_DEBUG'] == '1' }
35
+ options = {
36
+ input: nil,
37
+ output: nil,
38
+ debug: ENV["CLOUDFLARE_WORKERS_AUTO_AWAIT_DEBUG"] == "1"
39
+ }
32
40
 
33
41
  ARGV.each_with_index do |arg, i|
34
42
  case arg
35
- when '--input' then options[:input] = ARGV[i + 1]
36
- when '--output' then options[:output] = ARGV[i + 1]
37
- when '--debug' then options[:debug] = true
43
+ when "--input"
44
+ options[:input] = ARGV[i + 1]
45
+ when "--output"
46
+ options[:output] = ARGV[i + 1]
47
+ when "--debug"
48
+ options[:debug] = true
38
49
  end
39
50
  end
40
51
 
41
- abort('Usage: auto-await --input DIR --output DIR [--debug]') unless options[:input] && options[:output]
52
+ unless options[:input] && options[:output]
53
+ abort("Usage: auto-await --input DIR --output DIR [--debug]")
54
+ end
42
55
 
43
- input_root = Pathname(options[:input]).expand_path
56
+ input_root = Pathname(options[:input]).expand_path
44
57
  output_root = Pathname(options[:output]).expand_path
45
58
 
46
59
  registry = HomuraRuntime::AsyncRegistry.instance
@@ -49,18 +62,19 @@ registry = HomuraRuntime::AsyncRegistry.instance
49
62
  HomuraRuntime::AsyncRegistry.auto_load_gem_async_sources(debug: options[:debug])
50
63
 
51
64
  # Load project-specific async source registrations if present.
52
- project_async = File.join(Dir.pwd, 'lib', 'homura_async_sources.rb')
65
+ project_async = File.join(Dir.pwd, "lib", "homura_async_sources.rb")
53
66
  require project_async if File.exist?(project_async)
54
67
 
55
68
  changed = 0
56
69
  skipped = 0
57
- errors = 0
70
+ errors = 0
58
71
 
59
- paths = if File.directory?(input_root)
60
- Dir.glob(input_root.join('**', '*.rb')).sort
61
- else
62
- [input_root.to_s]
63
- end
72
+ paths =
73
+ if File.directory?(input_root)
74
+ Dir.glob(input_root.join("**", "*.rb")).sort
75
+ else
76
+ [input_root.to_s]
77
+ end
64
78
 
65
79
  paths.each do |path|
66
80
  rel = Pathname(path).relative_path_from(input_root)
@@ -72,10 +86,11 @@ paths.each do |path|
72
86
  # needed to tell Opal to wrap the file in an async function and to
73
87
  # translate #__await__ calls into real JS await keywords.
74
88
  has_magic = source.lines.first(5).any? { |l| l.match?(/#\s*await:/) }
75
- has_existing_await = source.include?('.__await__')
89
+ has_existing_await = source.include?(".__await__")
76
90
 
77
91
  begin
78
- analyzer = HomuraRuntime::AutoAwait::Analyzer.new(registry, debug: options[:debug])
92
+ analyzer =
93
+ HomuraRuntime::AutoAwait::Analyzer.new(registry, debug: options[:debug])
79
94
  buffer, nodes = analyzer.process(source, path)
80
95
  needs_magic_only_output = has_existing_await && !has_magic
81
96
 
@@ -91,13 +106,13 @@ paths.each do |path|
91
106
  else
92
107
  HomuraRuntime::AutoAwait::Transformer.transform(source, nodes, buffer)
93
108
  end
94
- unless has_magic
95
- transformed = "# await: true\n" + transformed
96
- end
109
+ transformed = "# await: true\n" + transformed unless has_magic
97
110
  out_path = output_root.join(rel)
98
111
  FileUtils.mkdir_p(out_path.dirname)
99
112
  File.write(out_path, transformed)
100
- puts "[auto-await] write #{rel} (#{nodes.length} await#{'s' if nodes.length > 1})" if options[:debug]
113
+ if options[:debug]
114
+ puts "[auto-await] write #{rel} (#{nodes.length} await#{"s" if nodes.length > 1})"
115
+ end
101
116
  changed += 1
102
117
  rescue => e
103
118
  $stderr.puts "[auto-await] ERROR #{rel}: #{e.message}"
data/exe/compile-assets CHANGED
@@ -12,39 +12,39 @@
12
12
  # Usage:
13
13
  # ruby bin/compile-assets --input public --output build/homura_assets.rb --namespace HomuraAssets
14
14
 
15
- require 'base64'
16
- require 'fileutils'
17
- require 'optparse'
15
+ require "base64"
16
+ require "fileutils"
17
+ require "optparse"
18
18
 
19
19
  MIME_TYPES = {
20
- '.css' => 'text/css; charset=utf-8',
21
- '.js' => 'application/javascript; charset=utf-8',
22
- '.json' => 'application/json; charset=utf-8',
23
- '.html' => 'text/html; charset=utf-8',
24
- '.svg' => 'image/svg+xml',
25
- '.png' => 'image/png',
26
- '.jpg' => 'image/jpeg',
27
- '.jpeg' => 'image/jpeg',
28
- '.gif' => 'image/gif',
29
- '.ico' => 'image/x-icon',
30
- '.woff' => 'font/woff',
31
- '.woff2'=> 'font/woff2',
32
- '.txt' => 'text/plain; charset=utf-8',
33
- '.xml' => 'application/xml; charset=utf-8',
34
- '.webp' => 'image/webp',
35
- '.map' => 'application/json',
20
+ ".css" => "text/css; charset=utf-8",
21
+ ".js" => "application/javascript; charset=utf-8",
22
+ ".json" => "application/json; charset=utf-8",
23
+ ".html" => "text/html; charset=utf-8",
24
+ ".svg" => "image/svg+xml",
25
+ ".png" => "image/png",
26
+ ".jpg" => "image/jpeg",
27
+ ".jpeg" => "image/jpeg",
28
+ ".gif" => "image/gif",
29
+ ".ico" => "image/x-icon",
30
+ ".woff" => "font/woff",
31
+ ".woff2" => "font/woff2",
32
+ ".txt" => "text/plain; charset=utf-8",
33
+ ".xml" => "application/xml; charset=utf-8",
34
+ ".webp" => "image/webp",
35
+ ".map" => "application/json"
36
36
  }.freeze
37
37
 
38
38
  def mime_for(path)
39
39
  ext = File.extname(path).downcase
40
- MIME_TYPES[ext] || 'application/octet-stream'
40
+ MIME_TYPES[ext] || "application/octet-stream"
41
41
  end
42
42
 
43
43
  def binary_content_type?(content_type)
44
- !(content_type.start_with?('text/') ||
45
- content_type.include?('javascript') ||
46
- content_type.include?('json') ||
47
- content_type.include?('xml'))
44
+ !(
45
+ content_type.start_with?("text/") || content_type.include?("javascript") ||
46
+ content_type.include?("json") || content_type.include?("xml")
47
+ )
48
48
  end
49
49
 
50
50
  HELP = <<~USAGE
@@ -55,23 +55,31 @@ HELP = <<~USAGE
55
55
  --input public --output build/homura_assets.rb --namespace HomuraAssets
56
56
  USAGE
57
57
 
58
- if ARGV.include?('-h') || ARGV.include?('--help')
58
+ if ARGV.include?("-h") || ARGV.include?("--help")
59
59
  puts HELP
60
60
  exit 0
61
61
  end
62
62
 
63
63
  options = {
64
- input_dir: 'public',
65
- output: 'build/homura_assets.rb',
66
- namespace: 'HomuraAssets'
64
+ input_dir: "public",
65
+ output: "build/homura_assets.rb",
66
+ namespace: "HomuraAssets"
67
67
  }
68
68
 
69
- OptionParser.new do |op|
70
- op.banner = 'Usage: bin/compile-assets [options]'
71
- op.on('--input DIR', 'Root directory to embed (recursive)') { |d| options[:input_dir] = d }
72
- op.on('--output PATH', 'Generated Ruby output path') { |p| options[:output] = p }
73
- op.on('--namespace NAME', 'Ruby module name') { |n| options[:namespace] = n }
74
- end.parse!
69
+ OptionParser
70
+ .new do |op|
71
+ op.banner = "Usage: bin/compile-assets [options]"
72
+ op.on("--input DIR", "Root directory to embed (recursive)") do |d|
73
+ options[:input_dir] = d
74
+ end
75
+ op.on("--output PATH", "Generated Ruby output path") do |p|
76
+ options[:output] = p
77
+ end
78
+ op.on("--namespace NAME", "Ruby module name") do |n|
79
+ options[:namespace] = n
80
+ end
81
+ end
82
+ .parse!
75
83
 
76
84
  public_dir = File.join(Dir.pwd, options[:input_dir])
77
85
  unless File.directory?(public_dir)
@@ -81,12 +89,13 @@ end
81
89
 
82
90
  ns = options[:namespace]
83
91
 
84
- files = Dir.glob(File.join(public_dir, '**', '*')).select { |f| File.file?(f) }.sort
92
+ files =
93
+ Dir.glob(File.join(public_dir, "**", "*")).select { |f| File.file?(f) }.sort
85
94
 
86
95
  out_path = options[:output]
87
96
  FileUtils.mkdir_p(File.dirname(out_path))
88
97
 
89
- File.open(out_path, 'w') do |io|
98
+ File.open(out_path, "w") do |io|
90
99
  io.puts <<~RUBY
91
100
  # frozen_string_literal: true
92
101
  # Auto-generated by bin/compile-assets — DO NOT EDIT BY HAND.
@@ -131,7 +140,7 @@ File.open(out_path, 'w') do |io|
131
140
  RUBY
132
141
 
133
142
  files.each do |full_path|
134
- rel = full_path.sub(public_dir, '') # e.g. "/style.css"
143
+ rel = full_path.sub(public_dir, "") # e.g. "/style.css"
135
144
  content = File.binread(full_path)
136
145
  ct = mime_for(full_path)
137
146
  binary = binary_content_type?(ct)
data/exe/compile-erb CHANGED
@@ -22,8 +22,8 @@
22
22
  # The output registers each template with `HomuraTemplates` and
23
23
  # monkey-patches `Sinatra::Templates#erb` to dispatch there.
24
24
 
25
- require 'fileutils'
26
- require 'optparse'
25
+ require "fileutils"
26
+ require "optparse"
27
27
 
28
28
  HELP = <<~USAGE
29
29
  Usage:
@@ -53,7 +53,7 @@ module HomuraERB
53
53
  end
54
54
 
55
55
  def normalize_fragment(fragment)
56
- return '__homura_template_yield__' if supported_yield_fragment?(fragment)
56
+ return "__homura_template_yield__" if supported_yield_fragment?(fragment)
57
57
  rewrite_class_variables(fragment)
58
58
  end
59
59
 
@@ -75,13 +75,15 @@ module HomuraERB
75
75
  # comments are vanishingly rare in real templates. Anything more
76
76
  # ambitious would need a Ruby parser, which is overkill for the
77
77
  # `@@ivar` shape we actually have to handle here.
78
- CVAR_OP_ASSIGN_RE = /(?<![@\w])@@([A-Za-z_]\w*)\s*(\|\||&&|\+|-|\*|\/|%|\*\*|<<|>>|\||&|\^)=\s*([^;\n]+)/.freeze
78
+ CVAR_OP_ASSIGN_RE =
79
+ %r{(?<![@\w])@@([A-Za-z_]\w*)\s*(\|\||&&|\+|-|\*|/|%|\*\*|<<|>>|\||&|\^)=\s*([^;\n]+)}.freeze
79
80
  CVAR_ASSIGN_RE = /(?<![@\w])@@([A-Za-z_]\w*)\s*=(?!=)\s*([^;\n]+)/.freeze
80
81
  # Read pattern excludes `@@name` that appears on the left-hand side
81
82
  # of an assignment (`@@name =`, `@@name +=`, `@@name ||=`, etc.) so
82
83
  # the assignment passes still see the raw token to rewrite. The
83
84
  # `=(?!=)` guard keeps `==` (comparison) treated as a read.
84
- CVAR_READ_RE = %r{
85
+ CVAR_READ_RE =
86
+ %r{
85
87
  (?<![@\w])@@([A-Za-z_]\w*)\b
86
88
  (?!
87
89
  \s*
@@ -94,13 +96,14 @@ module HomuraERB
94
96
  CVAR_PLACEHOLDER_SUFFIX = "\x01".freeze
95
97
 
96
98
  def rewrite_class_variables(fragment)
97
- return fragment unless fragment.include?('@@')
99
+ return fragment unless fragment.include?("@@")
98
100
 
99
101
  placeholders = []
100
- record = lambda do |replacement|
101
- placeholders << replacement
102
- "#{CVAR_PLACEHOLDER_PREFIX}#{placeholders.length - 1}#{CVAR_PLACEHOLDER_SUFFIX}"
103
- end
102
+ record =
103
+ lambda do |replacement|
104
+ placeholders << replacement
105
+ "#{CVAR_PLACEHOLDER_PREFIX}#{placeholders.length - 1}#{CVAR_PLACEHOLDER_SUFFIX}"
106
+ end
104
107
 
105
108
  # Reads first: rewrite every `@@name` that is *not* the target of
106
109
  # an assignment, including occurrences on the right-hand side of
@@ -108,36 +111,41 @@ module HomuraERB
108
111
  # later assignment passes see the original `@@name = ...` shape
109
112
  # (without their RHS reads being clobbered) and so the final
110
113
  # output never re-enters this same rewrite loop.
111
- work = fragment.gsub(CVAR_READ_RE) do
112
- name = Regexp.last_match(1)
113
- record.call("self.class.class_variable_get(:@@#{name})")
114
- end
114
+ work =
115
+ fragment.gsub(CVAR_READ_RE) do
116
+ name = Regexp.last_match(1)
117
+ record.call("self.class.class_variable_get(:@@#{name})")
118
+ end
115
119
 
116
- work = work.gsub(CVAR_OP_ASSIGN_RE) do
117
- name = Regexp.last_match(1)
118
- op = Regexp.last_match(2)
119
- value = Regexp.last_match(3)
120
- replacement =
121
- case op
122
- when '||'
123
- "self.class.class_variable_set(:@@#{name}, (self.class.class_variable_defined?(:@@#{name}) ? self.class.class_variable_get(:@@#{name}) : nil) || (#{value}))"
124
- when '&&'
125
- "self.class.class_variable_set(:@@#{name}, (self.class.class_variable_defined?(:@@#{name}) ? self.class.class_variable_get(:@@#{name}) : nil) && (#{value}))"
126
- else
127
- "self.class.class_variable_set(:@@#{name}, self.class.class_variable_get(:@@#{name}) #{op} (#{value}))"
128
- end
129
- record.call(replacement)
130
- end
120
+ work =
121
+ work.gsub(CVAR_OP_ASSIGN_RE) do
122
+ name = Regexp.last_match(1)
123
+ op = Regexp.last_match(2)
124
+ value = Regexp.last_match(3)
125
+ replacement =
126
+ case op
127
+ when "||"
128
+ "self.class.class_variable_set(:@@#{name}, (self.class.class_variable_defined?(:@@#{name}) ? self.class.class_variable_get(:@@#{name}) : nil) || (#{value}))"
129
+ when "&&"
130
+ "self.class.class_variable_set(:@@#{name}, (self.class.class_variable_defined?(:@@#{name}) ? self.class.class_variable_get(:@@#{name}) : nil) && (#{value}))"
131
+ else
132
+ "self.class.class_variable_set(:@@#{name}, self.class.class_variable_get(:@@#{name}) #{op} (#{value}))"
133
+ end
134
+ record.call(replacement)
135
+ end
131
136
 
132
- work = work.gsub(CVAR_ASSIGN_RE) do
133
- name = Regexp.last_match(1)
134
- value = Regexp.last_match(2)
135
- record.call("self.class.class_variable_set(:@@#{name}, (#{value}))")
136
- end
137
+ work =
138
+ work.gsub(CVAR_ASSIGN_RE) do
139
+ name = Regexp.last_match(1)
140
+ value = Regexp.last_match(2)
141
+ record.call("self.class.class_variable_set(:@@#{name}, (#{value}))")
142
+ end
137
143
 
138
- placeholder_re = /#{Regexp.escape(CVAR_PLACEHOLDER_PREFIX)}(\d+)#{Regexp.escape(CVAR_PLACEHOLDER_SUFFIX)}/
144
+ placeholder_re =
145
+ /#{Regexp.escape(CVAR_PLACEHOLDER_PREFIX)}(\d+)#{Regexp.escape(CVAR_PLACEHOLDER_SUFFIX)}/
139
146
  loop do
140
- replaced = work.gsub(placeholder_re) { placeholders[Regexp.last_match(1).to_i] }
147
+ replaced =
148
+ work.gsub(placeholder_re) { placeholders[Regexp.last_match(1).to_i] }
141
149
  break if replaced == work
142
150
  work = replaced
143
151
  end
@@ -146,7 +154,10 @@ module HomuraERB
146
154
 
147
155
  def validate_code_fragment!(fragment)
148
156
  stripped = fragment.strip
149
- return unless supported_yield_fragment?(stripped) || yield_with_args_fragment?(stripped)
157
+ unless supported_yield_fragment?(stripped) ||
158
+ yield_with_args_fragment?(stripped)
159
+ return
160
+ end
150
161
 
151
162
  raise <<~MSG.strip
152
163
  Unsupported ERB yield form `<% #{stripped} %>`.
@@ -176,7 +187,7 @@ module HomuraERB
176
187
  ruby = +"_out = ''\n"
177
188
  cursor = 0
178
189
  while cursor < source.length
179
- open_idx = source.index('<%', cursor)
190
+ open_idx = source.index("<%", cursor)
180
191
  if open_idx.nil?
181
192
  static = source[cursor..]
182
193
  ruby << "_out = _out + #{static.inspect}\n" unless static.empty?
@@ -189,21 +200,23 @@ module HomuraERB
189
200
  ruby << "_out = _out + #{static.inspect}\n"
190
201
  end
191
202
 
192
- close_idx = source.index('%>', open_idx + 2)
193
- raise "Unmatched `<%` in ERB source (starting at #{open_idx})" if close_idx.nil?
203
+ close_idx = source.index("%>", open_idx + 2)
204
+ if close_idx.nil?
205
+ raise "Unmatched `<%` in ERB source (starting at #{open_idx})"
206
+ end
194
207
 
195
208
  inner = source[(open_idx + 2)...close_idx]
196
209
 
197
- if inner.start_with?('#')
210
+ if inner.start_with?("#")
198
211
  # `<%# comment %>` — drop
199
- elsif inner.start_with?('==')
212
+ elsif inner.start_with?("==")
200
213
  # `<%== expression %>` — identical to `<%= %>` in this minimal
201
214
  # dialect (no HTML escaping yet; the author is responsible).
202
215
  expr = inner[2..].strip
203
216
  validate_expression_fragment!(expr)
204
217
  expr = normalize_fragment(expr)
205
218
  ruby << "_out = _out + ((#{expr})).to_s\n"
206
- elsif inner.start_with?('=')
219
+ elsif inner.start_with?("=")
207
220
  # `<%= expression %>`
208
221
  expr = inner[1..].strip
209
222
  validate_expression_fragment!(expr)
@@ -243,17 +256,17 @@ end
243
256
  def default_inputs_for(dir)
244
257
  # Recursive so `views/posts/index.erb` becomes `:'posts/index'`,
245
258
  # matching upstream Sinatra's subdirectory convention.
246
- Dir.glob(File.join(dir, '**', '*.erb')).sort
259
+ Dir.glob(File.join(dir, "**", "*.erb")).sort
247
260
  end
248
261
 
249
262
  def template_name_for(path, root)
250
263
  rel = path.dup
251
264
  if root
252
- root_with_sep = root.end_with?('/') ? root : "#{root}/"
265
+ root_with_sep = root.end_with?("/") ? root : "#{root}/"
253
266
  rel = rel[root_with_sep.length..] if rel.start_with?(root_with_sep)
254
267
  end
255
- rel = File.basename(rel) unless rel.include?('/')
256
- rel.delete_suffix('.erb').to_sym
268
+ rel = File.basename(rel) unless rel.include?("/")
269
+ rel.delete_suffix(".erb").to_sym
257
270
  end
258
271
 
259
272
  def emit_header(io, namespace)
@@ -479,25 +492,34 @@ end
479
492
  # Entry point
480
493
  # ---------------------------------------------------------------------------
481
494
 
482
- if ARGV.include?('-h') || ARGV.include?('--help')
495
+ if ARGV.include?("-h") || ARGV.include?("--help")
483
496
  puts HELP
484
497
  exit 0
485
498
  end
486
499
 
487
500
  options = {
488
- input_dir: 'views',
489
- output: 'build/homura_templates.rb',
490
- namespace: 'HomuraTemplates',
501
+ input_dir: "views",
502
+ output: "build/homura_templates.rb",
503
+ namespace: "HomuraTemplates",
491
504
  stdout: false
492
505
  }
493
506
 
494
- parser = OptionParser.new do |op|
495
- op.banner = 'Usage: bin/compile-erb [options] [--] [files...]'
496
- op.on('--input DIR', 'Directory containing *.erb templates') { |d| options[:input_dir] = d }
497
- op.on('--output PATH', 'Write generated Ruby to PATH') { |p| options[:output] = p }
498
- op.on('--namespace NAME', 'Ruby module name for the registry') { |n| options[:namespace] = n }
499
- op.on('--stdout', 'Write generated Ruby to stdout') { options[:stdout] = true }
500
- end
507
+ parser =
508
+ OptionParser.new do |op|
509
+ op.banner = "Usage: bin/compile-erb [options] [--] [files...]"
510
+ op.on("--input DIR", "Directory containing *.erb templates") do |d|
511
+ options[:input_dir] = d
512
+ end
513
+ op.on("--output PATH", "Write generated Ruby to PATH") do |p|
514
+ options[:output] = p
515
+ end
516
+ op.on("--namespace NAME", "Ruby module name for the registry") do |n|
517
+ options[:namespace] = n
518
+ end
519
+ op.on("--stdout", "Write generated Ruby to stdout") do
520
+ options[:stdout] = true
521
+ end
522
+ end
501
523
  parser.parse!
502
524
 
503
525
  positional = ARGV.dup
@@ -505,12 +527,15 @@ namespace = options[:namespace]
505
527
 
506
528
  inputs =
507
529
  if positional.any?
508
- positional.flat_map { |a| File.directory?(a) ? Dir.glob(File.join(a, '**', '*.erb')).sort : [a] }
530
+ positional.flat_map do |a|
531
+ File.directory?(a) ? Dir.glob(File.join(a, "**", "*.erb")).sort : [a]
532
+ end
509
533
  else
510
534
  default_inputs_for(options[:input_dir])
511
535
  end
512
536
 
513
- template_root = positional.find { |a| File.directory?(a) } || options[:input_dir]
537
+ template_root =
538
+ positional.find { |a| File.directory?(a) } || options[:input_dir]
514
539
 
515
540
  write_file = !options[:stdout] && (positional.empty? || options[:output])
516
541
  out_path = options[:output]
@@ -524,7 +549,7 @@ end
524
549
 
525
550
  if write_file
526
551
  FileUtils.mkdir_p(File.dirname(out_path))
527
- File.open(out_path, 'w') do |io|
552
+ File.open(out_path, "w") do |io|
528
553
  emit_header(io, namespace)
529
554
  emit_templates(io, inputs, namespace, template_root)
530
555
  emit_sinatra_patch(io, namespace) unless inputs.empty?