require 'forwardable'
require 'active_support/core_ext/string/output_safety'
require 'react/sinatra/template'
require 'react/sinatra/error'
require 'react/sinatra'
module React
module Sinatra
module Runtime
class RuntimeBased
DEFAULT_RENDER_FUNCTION = 'renderToString'.freeze
extend Forwardable
def_delegator React::Sinatra::Template, :[], :t
instance_delegate evaluate: React::Sinatra::Template
instance_delegate i[asset_path use_bundled_react env addon] => 'React::Sinatra.config'
def self.register(runtime)
Runtime.register runtime, self
end
def initialize(code: nil, **options)
@context = compile(code || to_context)
end
def render(component, props, **options)
code = to_runtime_code(component: component, props: props, **options)
render!(code).html_safe
rescue => error
error_handle!(component, props, error)
raise(error)
end
def render!(code)
raise NotImplementedError
end
def compile(context)
raise NotImplementedError
end
def error_handle!(component, props, error)
raise NotImplementedError
end
def assets
Dir.glob(asset_path).map(&File.method(:read)).join(?\n)
end
def to_context
ctx = []
ctx << t(:polyfill) << t(:variables)
if use_bundled_react
prefix = "react-source/#{actual_env}#{'-with-addons' if addon}"
ctx << t(:"#{prefix}/react") << t(:"#{prefix}/react-server")
end
ctx << assets
ctx.join(?\n)
end
def actual_env
env.to_sym == :production ? env : :development
end
def to_runtime_code(render_function: DEFAULT_RENDER_FUNCTION, **attrs)
evaluate :runtime, render_function: render_function, **attrs
end
end
end
end
end