# Closure Script Overview Closure Script is a specialized web server that automates the Closure build process. Typically, Closure development is driven by static HTML pages or your main application is given knowledge of your development systems. With Script, you build HTML or Javascript with embedded Ruby. The core Script technology is very simple and all Scripts execute in the same context regardless if they are test, demo, or compiler scripts. Exploring or extending the examples is the best way to learn Closure Script. If you are looking for information about Closure in general, Closure: The Definitive Guide is a solid reference. ## Closure::Script Context A Script is executed in the context of a Rack::Request that has been extended with Closure::Script. Rack::Request is everything having to do with the http request and Closure::Script is all about the interface to Closure. In most cases, the only Script I will put on a page simply relays the query string to the compiler Script: Script helps with testing because it can see your filesystem in ways that browsers are not allowed to. Here's a replacement for the static alltests.js in closure-library: <% all_test_files = Dir.glob expand_path '**/*_test.html' json_strings = all_test_files.map { |x| relative_src(x).dump } -%>var _allTests = [<%= json_strings.join(',') %>]; A Script can be entirely Ruby, entirely HTML, or anything in-between. Scripts of mostly Ruby look like models or controllers and Scripts of mostly HTML look like views. This makes Script a poor framework for enforcing web server patterns but gives it a great deal of flexibility as a build tool. The instance of Closure::Goog in Closure::Script provides easy access to the compiler and other information about your source Javascript. Script that compiles generally starts simple then grows with options as your project matures. Here's the simple version: <% @response = goog.compile(%w{ --compilation_level ADVANCED_OPTIMIZATIONS --js_output_file compiler_out.js --ns myapp.hello }).to_response %> And what it looks likes when you start processing query options: <% args = %w{ --ns myapp.hello } args += case query_string when 'build': %w{ --compilation_level ADVANCED_OPTIMIZATIONS --js_output_file compiler_build.js } when 'debug': %w{ --debug true --formatting PRETTY_PRINT --compilation_level ADVANCED_OPTIMIZATIONS --js_output_file compiler_debug.js } else;[];end @response = goog.compile(args).to_response %> The @response attribute of Closure::Script is an instance of Rack::Response. If you do nothing with this then then results of rendering will be sent as a response. If you write to @response or change it to another object then the rendering is discarded. Regardless of your language background, cut-and-paste programming from the scaffold examples should be practical. That's the idea anyways. If you can conditionally build arrays of strings in Ruby, you're good to go. But, of course, the more Ruby you know the more you'll be able to do. ## config.ru This file is unique in that there's only one and it's the only one that isn't a Script. Ruby developers may recognize the filename since it's convention for starting a web server. Changing this file requires a server restart but there isn't much in config.ru that needs changing. The default config.ru explains more in its comments. The smallest practical config.ru would be: require 'closure' Closure.add_source '.', '/' use Closure::Middleware run Rack::File.new '.' ## Argument Augmentation Closure Script adds additional features to the compiler like file modification checks and easy module generation. It does this by augmenting the command line arguments. The compiler arguments in Ruby are going to be the same arguments as if you ran compiler.jar from the command line. Except for the few things that are augmented by Closure Script. The most important augmentation is the addition of the --ns option. This is how you compile a namespace and its dependencies. How it works is simple in concept. Closure Script watches your source files and knows all their goog.provide and require namespaces. It will drop the --ns option and replace it with --js options to satisfy the namespace before calling compiler.jar. If you're coming from plovr then you are probably used to compiling a namespace by specifying a file as the root. Closure Script will not calculate the dependencies if you use --js. This works for plovr with its JSON config, but overloading --js in Script would leave ambiguity that could never be resolved. Do I follow the namespaces or not? The are three more augmented arguments. Not specifying a --compilation_level will load the original sources instead of compiling. Module format --module api:*:app will have the * replaced with an actual file count. And, if you specify a --js_output_file then compilation will be conditional on one of the sources having a modification time greater than the output file. Because Script doesn't use a modified compiler, you are free to use the latest compiler version or revert to an older one. Simply set Closure.config.compiler_jar in config.ru to point to the one you want to use. Java and JRuby developers: the jars are fetched with URLClassLoader and don't need to be in any Java paths. ## Compatibility The .jar only needs Java. It contains JRuby and the Closure tools. Guaranteed success. The gem should work on any kind of Ruby that is like version 1.8 or greater. The Script source code is non-magical so any issues will be easy to fix. Mac, Linux, and Windows all work. If you can get Rack running, Closure Script should be no problem. ## Script Engines Closure Script comes with support for several file formats. If you want something else, it is easy to add new engines to Script with the Closure.config.engines setting. ERB (.erb) : This is plain old HTML with support for Ruby in <% %> and <%= %> tags. ERB::Util is mixed in for <%=h 'string' %> and <%=u 'string' %> helpers. Haml (.haml) : This is an indented format (no closing tags) that a lot of Ruby developers use. Markdown (.md, .markdown) : Read-me files and developer documentation look nice for cheap and easy. This very document is in markdown source.