require 'rubygems' require 'rake' require 'json' $LOAD_PATH.unshift File.expand_path("../lib", __FILE__) require 'rspec' require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) do |spec| spec.rspec_opts = ["--color"] spec.pattern = "spec/**/*_spec.rb" end def load_sdk_vars if File.exists?("sdk-vars.rb") require "sdk-vars.rb" else puts "Error: sdk-vars.rb not found." puts puts "Please create file sdk-vars.rb and define constants SDK_DIR and OUT_DIR in it." puts puts "For example:" puts puts " # path to Ext JS 4 build" puts " EXT_DIR='/path/to/ext-4.0.7'" puts " # where to output the docs" puts " OUT_DIR='/path/to/ouput/dir'" puts " # path to SDK (for developers at Sencha)" puts " SDK_DIR='/path/to/SDK'" puts " # path to Animator (for developers at Sencha)" puts " ANIMATOR_DIR='/path/to/Animator'" exit 1 end end # Compress JS/CSS file in-place # Using a hackish way to access yui-compressor def yui_compress(fname) system "java -jar $(dirname $(which sencha))/../jsbuilder/ycompressor/ycompressor.jar -o #{fname} #{fname}" end # Reads in all CSS files referenced between BEGIN CSS and END CSS markers. # Deletes those input CSS files and writes out concatenated CSS to # resources/css/app.css # Finally replaces the CSS section with to that one CSS file. def combine_css(html, dir, opts = :write) css_section_re = /.*/m css = [] css_section_re.match(html)[0].each_line do |line| if line =~ /') end # Same thing for JavaScript, result is written to: app.js def combine_js(html, dir) js_section_re = /.*/m js = [] js_section_re.match(html)[0].each_line do |line| if line =~ /') end # Compress JavaScript and CSS files of JSDuck def compress load_sdk_vars # Clean up template-min/ left over from previous compress task system("rm", "-rf", "template-min") # Copy template/ files to template-min/ system("cp", "-r", "template", "template-min") # Now do everything that follows in template-min/ dir dir = "template-min" # Create JSB3 file for Docs app system("sencha", "create", "jsb", "-a", "#{dir}/build-js.html", "-p", "#{dir}/app.jsb3") # Concatenate files listed in JSB3 file system("sencha", "build", "-p", "#{dir}/app.jsb3", "-d", dir) # Remove intermediate build files system("rm", "#{dir}/app.jsb3") system("rm", "#{dir}/all-classes.js") # Replace app.js with app-all.js system("mv", "#{dir}/app-all.js", "#{dir}/app.js") # Remove the entire app/ dir system("rm", "-r", "#{dir}/app") # Concatenate CSS in print-template.html file print_template = "#{dir}/print-template.html"; html = IO.read(print_template); # Just modify HTML to link app.css, don't write files. html = combine_css(html, dir, :replace_html_only) File.open(print_template, 'w') {|f| f.write(html) } # Concatenate CSS and JS files referenced in template.html file template_html = "#{dir}/template.html" html = IO.read(template_html) html = combine_css(html, dir) html = combine_js(html, dir) File.open(template_html, 'w') {|f| f.write(html) } # Clean up SASS files # (But keep prettify lib, which is needed for source files) system "rm -rf #{dir}/resources/sass" system "rm -rf #{dir}/resources/codemirror" system "rm -rf #{dir}/resources/.sass-cache" # Empty the extjs dir, leave only the main JS files, CSS and images system "rm -rf #{dir}/extjs" system "mkdir #{dir}/extjs" system "cp #{EXT_DIR}/ext-all.js #{dir}/extjs" system "cp #{EXT_DIR}/ext-all-debug.js #{dir}/extjs" system "cp #{EXT_DIR}/bootstrap.js #{dir}/extjs" system "mkdir -p #{dir}/extjs/resources/css" system "cp #{EXT_DIR}/resources/css/ext-all.css #{dir}/extjs/resources/css" system "mkdir -p #{dir}/extjs/resources/themes/images" system "cp -r #{EXT_DIR}/resources/themes/images/default #{dir}/extjs/resources/themes/images" end class JsDuckRunner def initialize @options = [] load_sdk_vars @sdk_dir = SDK_DIR @out_dir = OUT_DIR @ext_dir = EXT_DIR @animator_dir = ANIMATOR_DIR @base_url = "http://projects.sencha.com/auth" end def add_options(options) @options += options end def add_sdk(mode = nil) head_html = <<-EOHTML EOHTML if mode == 'export' relative_sdk_path = "../" ["template-min/extIframe.html", "template-min/welcome.html"].each do |file| html = IO.read(file); out = [] html.each_line do |line| out << line.sub(/((src|href)="extjs\/)/, '\2="' + relative_sdk_path) end File.open(file, 'w') {|f| f.write(out) } end head_html = <<-EOHTML EOHTML end @options += [ "--title", "Sencha Docs - Ext JS 4.0", "--head-html", head_html, "--footer", "Ext JS 4.0.7 Docs - Generated with JSDuck rev #{revision}", "--welcome", "template/welcome.html", "--guides", "#{@sdk_dir}/extjs/docs/guides.json", "--videos", "#{@sdk_dir}/extjs/docs/videos.json", "--examples", "#{@sdk_dir}/extjs/examples/examples.json", "--categories", "#{@sdk_dir}/extjs/docs/categories.json", "--local-storage-db", "ext-4", "--output", "#{@out_dir}", "--builtin-classes", "--images", "#{@sdk_dir}/extjs/docs/resources", "--images", "#{@sdk_dir}/platform/docs/resources", "#{@sdk_dir}/extjs/src", "#{@sdk_dir}/platform/src", "#{@sdk_dir}/platform/core/src", ] end def add_ext3 head_html = <<-EOHTML EOHTML @options += [ "--title", "Sencha Docs - Ext JS 3.4", "--footer", "Ext JS 3.4 Docs - Generated with JSDuck revison #{revision}", "--categories", "#{@sdk_dir}/../ext-3.4.0/src/categories.json", "--ignore-global", "--local-storage-db", "ext-3", "--output", "#{@out_dir}", "#{@sdk_dir}/../ext-3.4.0/src/core", "#{@sdk_dir}/../ext-3.4.0/src/data", "#{@sdk_dir}/../ext-3.4.0/src/dd", "#{@sdk_dir}/../ext-3.4.0/src/direct", "#{@sdk_dir}/../ext-3.4.0/src/ext-core/src", "#{@sdk_dir}/../ext-3.4.0/src/state", "#{@sdk_dir}/../ext-3.4.0/src/util", "#{@sdk_dir}/../ext-3.4.0/src/widgets" ] end def add_ext4 @options += [ "--title", "Sencha Docs - Ext JS 4.0", "--footer", "Ext JS 4.0 Docs - Generated with JSDuck revison #{revision}", "--ignore-global", "--no-warnings", "--images", "#{@ext_dir}/docs/doc-resources", "--local-storage-db", "ext-4", "--output", "#{@out_dir}", "#{@ext_dir}/src", ] end def add_touch head_html = <<-EOHTML EOHTML @options += [ "--title", "Sencha Docs - Touch 1.1", "--head-html", head_html, "--footer", "Sencha Touch 1.1 Docs - Generated with JSDuck revison #{revision}", "--categories", "#{@sdk_dir}/touch/doc-resources/categories.json", "--videos", "#{@sdk_dir}/touch/doc-resources/videos.json", "--local-storage-db", "touch-1", "--output", "#{@out_dir}", "--external=google.maps.Map,google.maps.LatLng", "--images", "#{@sdk_dir}/touch/doc-resources", "#{@sdk_dir}/touch/resources/themes/stylesheets/sencha-touch/default", ] @options += extract_jsb_build_files("#{@sdk_dir}/touch/sencha-touch.jsb3") end def add_touch2 head_html = <<-EOHTML EOHTML @options += [ "--title", "Sencha Docs - Touch 2.0", "--head-html", head_html, "--footer", "Sencha Touch 2.0 Docs - Generated with JSDuck revison #{revision}", "--categories", "#{@sdk_dir}/touch/docs/categories.json", "--welcome", "template/touch-welcome.html", "--videos", "#{@sdk_dir}/touch/docs/videos.json", "--guides", "#{@sdk_dir}/touch/docs/guides.json", "--examples", "#{@sdk_dir}/touch/docs/examples.json", "--touch-examples-ui", "--local-storage-db", "touch-2", "--output", "#{@out_dir}", "--external=google.maps.Map,google.maps.LatLng", "--builtin-classes", "--img", "

%a%a

", "--eg-iframe", "template/touch-iframe.html", "#{@sdk_dir}/touch/resources/themes/stylesheets/sencha-touch/default", ] @options += extract_jsb_build_files("#{@sdk_dir}/touch/touch.jsb3") end def add_touch_export @options += [ "--json", "--output", "#{@out_dir}/../export/touch1", "--external=google.maps.Map,google.maps.LatLng", ] @options += extract_jsb_build_files("#{@sdk_dir}/touch/sencha-touch.jsb3") end def add_touch2_export @options += [ "--json", "--output", "#{@out_dir}/../export/touch2", "--external=google.maps.Map,google.maps.LatLng", ] @options += extract_jsb_build_files("#{@sdk_dir}/touch/touch.jsb3") end def set_touch2_src relative_touch_path = "../" touch_iframe = "template-min/touchIframe.html"; ["template-min/touchIframe.html", "template-min/touch-welcome.html"].each do |file| html = IO.read(file); touch_src_re = /((src|href)="touch)/m out = [] html.each_line do |line| out << line.sub(/((src|href)="touch\/)/, '\2="' + relative_touch_path) end File.open(file, 'w') {|f| f.write(out) } end head_html = <<-EOHTML EOHTML @options += [ "--welcome", "template-min/touch-welcome.html", "--body-html", head_html ] end def add_touch_charts head_html = <<-EOHTML EOHTML @options += [ "--title", "Sencha Docs - Touch Charts 1.0", "--head-html", head_html, "--footer", "Sencha Touch Charts 1.0 Docs - Generated with JSDuck", "--categories", "#{@sdk_dir}/charts/docs/categories.json", "--guides", "#{@sdk_dir}/charts/docs/guides.json", "--images", "#{@sdk_dir}/charts/docs/resources", "--local-storage-db", "touch-charts", "--output", "#{@out_dir}" ] @options += extract_jsb_build_files("#{@sdk_dir}/charts/touch-charts.jsb3") end def add_sencha_io head_html = <<-EOHTML EOHTML @options += [ "--title", "Sencha Docs - IO 1.0", "--head-html", head_html, "--footer", "Sencha.io 1.0 Docs - Generated with JSDuck", "--guides", "#{@sdk_dir}/../sync/docs/guides.json", "--images", "#{@sdk_dir}/../sync/docs/resources", "--local-storage-db", "sencha-io", "--ignore-global", "--output", "#{@out_dir}" ] @options += extract_jsb_build_files("#{@sdk_dir}/../sync/sencha-io.jsb3") end def add_animator head_html = <<-EOHTML EOHTML @options += [ "--title", "Sencha Docs - Animator 1.0", "--head-html", head_html, "--footer", "Sencha Animator 1.0 Docs - Generated with JSDuck revison #{revision}", # "--videos", "#{@animator_dir}/docs/videos.json", "--guides", "#{@animator_dir}/docs/guides.json", # "--examples", "#{@animator_dir}/docs/examples/examples.json", "--local-storage-db", "animator", "--output", "#{@out_dir}", ] end # Extracts files of first build in jsb file def extract_jsb_build_files(jsb_file) json = JSON.parse(IO.read(jsb_file)) basedir = File.dirname(jsb_file) return json["builds"][0]["packages"].map do |package_id| package = json["packages"].find {|p| p["id"] == package_id } package["files"].map do |file| basedir + "/" + file["path"] + file["name"] end end.flatten end # Returns shortened hash of naming current git revision def revision `git rev-parse HEAD`.slice(0, 7) end def add_debug @options += [ "--extjs-path", "extjs/ext-all-debug.js", "--template-links", "--template", "template", ] end def add_seo @options += [ "--seo", ] end def add_sdk_export_notice @options += [ "--body-html", <<-EOHTML EOHTML ] end def add_touch2_export_notice @options += [ "--body-html", <<-EOHTML EOHTML ] end def add_google_analytics @options += [ "--body-html", <<-EOHTML EOHTML ] end # Copy over SDK examples def copy_sdk_examples system "mkdir #{@out_dir}/extjs/builds" system "cp #{@ext_dir}/builds/ext-core.js #{@out_dir}/extjs/builds/ext-core.js" system "cp #{@ext_dir}/release-notes.html #{@out_dir}/extjs" system "cp -r #{@ext_dir}/examples #{@out_dir}/extjs" system "cp -r #{@ext_dir}/welcome #{@out_dir}/extjs" end def copy_animator_examples system "mkdir -p #{@out_dir}/extjs" system "cp -r #{@animator_dir}/docs/examples #{@out_dir}/extjs" end # Copy over Sencha Touch def copy_touch2_build system "cp -r #{@sdk_dir}/touch/build #{@out_dir}/touch" end def run # Pass multiple arguments to system, so we'll take advantage of the built-in escaping system(*["ruby", "bin/jsduck"].concat(@options)) end end # Run compass to generate CSS files task :sass do system "compass compile --quiet template/resources/sass" end desc "Updates JSB3 file for Docs app.\n"+ "Run this before every commit that changes JS dependencies." task :jsb do system("sencha", "create", "jsb", "-a", "template/build-js.html", "-p", "template/app.jsb3") end desc "Run JSDuck on Ext JS SDK (for internal use at Sencha)\n" + "sdk - creates debug/development version\n" + "sdk[export] - creates export version\n" + "sdk[live] - create live version for deployment\n" task :sdk, [:mode] => :sass do |t, args| mode = args[:mode] || "debug" throw "Unknown mode #{mode}" unless ["debug", "export", "live"].include?(mode) compress if mode == "export" || mode == "live" runner = JsDuckRunner.new runner.add_sdk(mode) runner.add_debug if mode == "debug" runner.add_seo if mode == "debug" || mode == "live" runner.add_sdk_export_notice if mode == "export" runner.add_google_analytics if mode == "live" runner.run runner.copy_sdk_examples if mode == "export" || mode == "live" end desc "Run JSDuck on official Ext JS 4.0.2a build\n" + "ext4 - creates debug/development version\n" + "ext4[export] - creates export/deployable version\n" task :ext4, [:mode] => :sass do |t, args| mode = args[:mode] || "debug" throw "Unknown mode #{mode}" unless ["debug", "export"].include?(mode) compress if mode == "export" runner = JsDuckRunner.new runner.add_ext4 runner.add_debug if mode == "debug" runner.add_seo runner.run end desc "Run JSDuck on official Ext JS 3.4 build\n" + "ext3 - creates debug/development version\n" + "ext3[export] - creates export/deployable version\n" "ext3[live] - creates live version for deployment\n" task :ext3, [:mode] => :sass do |t, args| mode = args[:mode] || "debug" throw "Unknown mode #{mode}" unless ["debug", "export", "live"].include?(mode) compress if mode == "export" runner = JsDuckRunner.new runner.add_ext3 runner.add_debug if mode == "debug" runner.add_seo if mode == "live" runner.add_google_analytics if mode == "live" runner.run end desc "Run JSDuck on Sencha Touch (for internal use at Sencha)\n" + "touch - creates debug/development version\n" + "touch[live] - create live version for deployment\n" task :touch, [:mode] => :sass do |t, args| mode = args[:mode] || "debug" throw "Unknown mode #{mode}" unless ["debug", "live"].include?(mode) compress if mode == "live" runner = JsDuckRunner.new runner.add_touch runner.add_debug if mode == "debug" runner.add_seo if mode == "debug" || mode == "live" runner.add_google_analytics if mode == "live" runner.run end desc "Run JSDuck on Sencha Touch 2 (for internal use at Sencha)\n" + "touch2 - creates debug/development version\n" + "touch2[export] - creates export version\n" + "touch2[live] - create live version for deployment\n" task :touch2, [:mode] => :sass do |t, args| mode = args[:mode] || "debug" throw "Unknown mode #{mode}" unless ["debug", "export", "live"].include?(mode) compress if mode == "live" || mode == "export" runner = JsDuckRunner.new runner.add_touch2 runner.add_debug if mode == "debug" runner.add_touch2_export_notice if mode == "export" runner.set_touch2_src if mode == "export" runner.add_seo if mode == "debug" || mode == "live" runner.add_google_analytics if mode == "live" runner.run runner.copy_touch2_build if mode != "export" end desc "Run JSDuck on Sencha Touch Charts (for internal use at Sencha)\n" + "charts - creates debug/development version\n" + "charts[export] - create live version for deployment\n" "charts[live] - create live version for deployment\n" task :charts, [:mode] => :sass do |t, args| mode = args[:mode] || "debug" throw "Unknown mode #{mode}" unless ["debug", "export", "live"].include?(mode) compress if mode == "live" runner = JsDuckRunner.new runner.add_touch_charts runner.add_debug if mode == "debug" runner.add_seo if mode == "debug" || mode == "live" runner.add_google_analytics if mode == "live" runner.run end desc "Run JSDuck on Sencha.IO Sync (for internal use at Sencha)\n" + "senchaio - creates debug/development version\n" + "senchaio[export] - create live version for deployment\n" "senchaio[live] - create live version for deployment\n" task :senchaio, [:mode] => :sass do |t, args| mode = args[:mode] || "debug" throw "Unknown mode #{mode}" unless ["debug", "export", "live"].include?(mode) compress if mode == "live" runner = JsDuckRunner.new runner.add_sencha_io runner.add_debug if mode == "debug" runner.add_seo if mode == "debug" || mode == "live" runner.add_google_analytics if mode == "live" runner.run end desc "Run JSDuck JSON Export (for internal use at Sencha)\n" + "export[touch] - creates export for Touch 1\n" + "export[touch2] - creates export for Touch 2" task :export, [:mode] do |t, args| mode = args[:mode] throw "Unknown mode #{mode}" unless ["touch", "touch2"].include?(mode) runner = JsDuckRunner.new runner.add_touch_export if mode == "touch" runner.add_touch2_export if mode == "touch2" runner.run end desc "Run JSDuck on Sencha Animator (for internal use at Sencha)\n" + "animator - creates debug/development version\n" + "animator[export] - create live version for deployment\n" "animator[live] - create live version for deployment\n" task :animator, [:mode] => :sass do |t, args| mode = args[:mode] || "debug" throw "Unknown mode #{mode}" unless ["debug", "live", "export"].include?(mode) compress if mode == "live" runner = JsDuckRunner.new runner.add_animator runner.add_debug if mode == "debug" runner.add_seo if mode == "debug" || mode == "live" runner.add_google_analytics if mode == "live" runner.run runner.copy_animator_examples end desc "Build JSDuck gem" task :gem => :sass do compress system "gem build jsduck.gemspec" end task :default => :spec