#!/usr/bin/env ruby
TEMPLATE = <<-TEMPLATE.strip
class HelloWorld < Prism::Component
attr_accessor :name
def initialize(name = "World")
@name = name
end
def render
div(".hello-world", [
input(onInput: call(:name=).with_target_data(:value)),
div("Hello, \#{name}")
])
end
end
Prism.mount(HelloWorld.new)
TEMPLATE
HTML_TEMPLATE = <<-HTML.strip
Hello World
HTML
def init(path = "app.rb")
fail "#{path} already exists" if File.exist?(path)
File.write(path, TEMPLATE) # TODO - there's a race condition here where the file is created between the previous statement and this one
puts "Created new Prism app at app.rb\n\nRun prism build #{path} to compile your app."
end
def build(files)
mrbc_path = `which mrbc`.split("\n").first
emcc_path = `which emcc`.split("\n").first
if (!mrbc_path || !emcc_path)
puts "Error: Please ensure you have mruby and emscripten installed and available on the $PATH.\n\n mrbc: #{mrbc_path || 'Not found!'}\n emcc: #{emcc_path || 'Not found! Do you need to source emsdk_env.sh?'}"
exit 1
end
all_files = ["#{__dir__}/../src/prism.rb"] + files
bundle = all_files.map { |f| File.read(f) }.join("\n")
`mkdir -p build`
Dir.chdir("build")
File.write("./bundle.rb", bundle)
puts "Compiling ruby code to mruby bytecode..."
`mrbc -Bbundle bundle.rb`
`cp #{__dir__}/../main.c main.c`
puts "Compiling to Wasm..."
`
emcc \
-s ALLOW_MEMORY_GROWTH=1 \
-s EXPORTED_FUNCTIONS="['_main', '_render', '_dispatch', '_event']" \
-s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]' \
-s WASM=1 \
-I #{__dir__}/../mruby/include \
-g4 \
main.c \
#{__dir__}/../mruby/build/emscripten/lib/libmruby.a \
-o bundle.js
`
`cp #{__dir__}/../dist/prism.js ./prism.js`
File.write("./index.html", HTML_TEMPLATE) unless File.exists?("./index.html")
`rm bundle.c bundle.rb main.c`
puts "Compiled to build/"
end
def server
Dir.chdir("build")
`node #{__dir__}/../wasm-server.js`
end
def help
puts <<-HEREDOC.strip
Usage: prism [options]
Commands:
init initializes a new prism application
build builds a prism application
server
HEREDOC
end
command, *rest = ARGV
case command
when "init"
init
when "build"
rest = ["app.rb"] if rest.empty?
build(rest)
when "server"
server
else
help
end