require 'fileutils' require 'lib/handle_js_files' # Compass generator for jrails 0.1+ JRAILS_SRC = File.join(GEM_ROOT, 'src', 'jrails') JRAILS_SRC_SCRIPTS = JRAILS_SRC + "/*.js" JQUERY_SRC = File.join(GEM_ROOT, 'src', 'jquery-1.3.2') JQUERY_SRC_SCRIPTS = JQUERY_SRC + "/*.js" JQUERY_UI_SRC = File.join(GEM_ROOT, 'src', 'jquery.ui-1.7.2') JQUERY_UI_SRC_SCRIPTS = File.join(JQUERY_UI_SRC, 'js') + "/*.js" JQUERY_UI_SRC_THEMES = File.join(JQUERY_UI_SRC, 'themes') JQUERY_UI_SRC_TRANSLATIONS = File.join(JQUERY_UI_SRC, 'js', 'i18n') #+ "/*.js" JRAILS_DEST_TEMPLATES = File.join(GEM_ROOT, 'templates', 'jrails') JRAILS_DEST_TRANSLATIONS = File.join(JRAILS_DEST_TEMPLATES, 'i18n', 'jquery.ui') JRAILS_DEST_THEMES = File.join(JRAILS_DEST_TEMPLATES, 'jquery.ui') JRAILS_DEST_IMAGES = File.join(JRAILS_DEST_TEMPLATES, 'jquery.ui') JRAILS_MESSAGE1 = "# Generated by compass-jquery-plugin/gem-tasks/jrails.rake\n# Install with: compass -f jquery -p jrails\n\n" JRAILS_MESSAGE2 = "// Generated by compass-jquery-plugin/gem-tasks/jrails.rake\n\n" namespace :build do desc 'Build the stylesheets and templates for jRails.' task :jrails do FileUtils.remove_dir JRAILS_DEST_TEMPLATES if File.exists? JRAILS_DEST_TEMPLATES FileUtils.mkdir_p(File.join(JRAILS_DEST_TEMPLATES, 'config', 'initializers')) open File.join(JRAILS_DEST_TEMPLATES, 'manifest.rb'), 'w' do |manifest| # jRails manifest.print JRAILS_MESSAGE1 open File.join(JRAILS_DEST_TEMPLATES, 'config', 'initializers', 'jrails.rb'), 'w' do |f| f.print(File.read(File.join(JRAILS_SRC, 'config', 'initializers', 'jrails.rb'))) end manifest.print "file 'config/initializers/jrails.rb'\n" open File.join(JRAILS_DEST_TEMPLATES, 'jrails.js'), 'w' do |f| f.print concat_files(all_files(JRAILS_SRC_SCRIPTS)) end manifest.print "javascript 'jrails.js'\n" open File.join(JRAILS_DEST_TEMPLATES, 'jrails.min.js'), 'w' do |f| f.print compress_js(all_files(JRAILS_SRC_SCRIPTS)) end manifest.print "javascript 'jrails.min.js'\n" # jQuery 1.3 open File.join(JRAILS_DEST_TEMPLATES, 'jquery.js'), 'w' do |f| f.print concat_files(all_files(JQUERY_SRC_SCRIPTS)) end manifest.print "javascript 'jquery.js'\n" open File.join(JRAILS_DEST_TEMPLATES, 'jquery.min.js'), 'w' do |f| f.print compress_js(all_files(JQUERY_SRC_SCRIPTS)) end manifest.print "javascript 'jquery.min.js'\n" # jQuery 1.3 Plugins ['plugins'].each do |path| Dir.foreach File.join(JQUERY_SRC, path) do |file| next unless /\.js$/ =~ file js = File.read File.join(JQUERY_SRC, path, file) manifest.print "javascript '#{file}'\n" open File.join(JRAILS_DEST_TEMPLATES, file), 'w' do |f| f.write js end file.gsub!(/\.js$/, '.min.js') manifest.print "javascript '#{file}'\n" open File.join(JRAILS_DEST_TEMPLATES, file), 'w' do |f| f.write compress_js(js) end end end # jQuery.UI # Scripts all_jquery_ui_scripts = [ 'jquery-ui-1.7.2.custom.js', 'effects.blind.js', 'effects.bounce.js', 'effects.clip.js', 'effects.core.js', 'effects.drop.js', 'effects.explode.js', 'effects.fold.js', 'effects.highlight.js', 'effects.pulsate.js', 'effects.scale.js', 'effects.shake.js', 'effects.slide.js', 'effects.transfer.js', 'effects.blind.js', 'ui.accordion.js', 'ui.core.js', 'ui.datepicker.js', 'ui.dialog.js', 'ui.draggable.js', 'ui.droppable.js', 'ui.progressbar.js', 'ui.resizable.js', 'ui.selectable.js', 'ui.slider.js', 'ui.sortable.js', 'ui.tabs.js' ].collect {|filename| File.read(File.join(JQUERY_UI_SRC, 'js', filename))}.join "\n\n" open File.join(JRAILS_DEST_TEMPLATES, 'jquery-ui.js'), 'w' do |f| f.print concat_files(all_jquery_ui_scripts) end manifest.print "javascript 'jquery-ui.js'\n" open File.join(JRAILS_DEST_TEMPLATES, 'jquery-ui.min.js'), 'w' do |f| f.print compress_js(all_jquery_ui_scripts) end manifest.print "javascript 'jquery-ui.min.js'\n" # jQuery UI locales # FileUtils.mkdir_p File.join(JRAILS_DEST_TEMPLATES, 'i18n') # open File.join(JRAILS_DEST_TEMPLATES, 'i18n', 'jquery.ui.locale.js'), 'w' do |f| # f.print concat_files(all_files(JQUERY_UI_SRC_TRANSLATIONS)) # end # manifest.print "javascript 'i18n/jquery.ui.locale.js'\n" # # open File.join(JRAILS_DEST_TEMPLATES, 'i18n', 'jquery.ui.locale.min.js'), 'w' do |f| # f.print compress_js(all_files(JQUERY_UI_SRC_TRANSLATIONS)) # end # manifest.print "javascript 'i18n/jquery.ui.locale.min.js'\n" ['i18n'].each do |path| FileUtils.mkdir_p File.join(JRAILS_DEST_TRANSLATIONS) Dir.foreach JQUERY_UI_SRC_TRANSLATIONS do |file| next unless /^ui\.datepicker-(.+)\.js$/ =~ file lang = file #lang.gsub!(/^ui\.datepicker-(.+)\.js$/, '') #puts lang js = File.read File.join(JQUERY_UI_SRC_TRANSLATIONS, file) file.gsub!(/^ui\./,'') manifest.print "javascript '#{File.join(path, 'jquery.ui', file)}'\n" open File.join(JRAILS_DEST_TRANSLATIONS, file), 'w' do |f| f.write js end file.gsub!(/\.js$/, '.min.js') manifest.print "javascript '#{File.join(path, 'jquery.ui', file)}'\n" open File.join(JRAILS_DEST_TRANSLATIONS, file), 'w' do |f| f.write compress_js(js) end end end # jQuery UI Themes FileUtils.mkdir_p(File.join(JRAILS_DEST_THEMES)) ui = JqueryUiTheme.new(File.join(JQUERY_UI_SRC_THEMES, 'base')) ui.convert_css(File.join(JRAILS_DEST_THEMES, '_partials')) all_jquery_ui_stylesheets = [ '_core.sass', '_accordion.sass', '_datepicker.sass', '_dialog.sass', '_progressbar.sass', '_resizable.sass', '_slider.sass', '_tabs.sass', '_theme.sass' ].collect {|filename| File.read(File.join(JRAILS_DEST_THEMES, '_partials', filename))}.join "\n\n" open File.join(JRAILS_DEST_THEMES, '_theme.sass'), 'w' do |f| sass = JRAILS_MESSAGE2 f.print(all_jquery_ui_stylesheets) f.print sass FileUtils.rm_r(File.join(JRAILS_DEST_THEMES, '_partials')) end manifest.print "stylesheet 'jquery.ui/_theme.sass', :media => 'screen, projection'\n" Dir.foreach JQUERY_UI_SRC_THEMES do |theme| next if /^\./ =~ theme # Convert the stylesheet manifest.print "stylesheet 'jquery.ui/#{theme}.sass', :media => 'screen, projection'\n" ui.convert_theme(theme, File.join(JQUERY_UI_SRC_THEMES, theme), File.join(JRAILS_DEST_THEMES)) # Copy the theme images directory src_dir = File.join(JQUERY_UI_SRC_THEMES, theme, 'images') dest_dir = File.join(JRAILS_DEST_IMAGES, theme) FileUtils.mkdir_p dest_dir Dir.foreach(src_dir) do |image| next if /^\./ =~ image FileUtils.cp(File.join(src_dir, image), dest_dir) manifest.print "image 'jquery.ui/#{theme}/#{image}'\n" end end end end end namespace :jrails do desc 'Remove the prototype / script.aculo.us javascript files' task :scrub_default_js do files = %W[controls.js dragdrop.js effects.js prototype.js] project_dir = File.join(RAILS_ROOT, 'public', 'javascripts') files.each do |fname| FileUtils.rm File.join(project_dir, fname) end end end class JqueryUiTheme VARIABLE_NAME_BASE = 'ui_' VARIABLE_MATCHER = /(\S*)\/\*\{(\w*)\}\*\// THEME_FILENAME = 'ui.theme.css' attr_accessor :base_theme # Initialize with the base theme def initialize(base_theme_directory) @base_theme_directory = base_theme_directory @base_theme = File.read(File.join(@base_theme_directory, THEME_FILENAME)) if @base_theme[3775..3794] == "#363636/*{fcError}*/" print "Fixing up bug in 1.7.1 template\n" @base_theme[3775..3794] == "#cd0a0a/*{fcError}*/" end if @base_theme[416,16] == ".ui-widget input" print "Fixing up bug in 1.7.2 template\n" @base_theme[416,0] = ".ui-widget .ui-widget { font-size: 1em; }\n" end end # This sets up the Regexp that will extract the variables from a theme def regexp return @regexp if @regexp placeholder = '___PLACEHOLDER___' @regexp = @base_theme.dup # Install placeholders for the variable data @regexp.gsub!(VARIABLE_MATCHER) {placeholder} # Strip the header comments @regexp.gsub! /.*^\*\/\s*/m, '' # Collapse all whitespace @regexp.gsub! /\s+/, ' ' # Escape the literal strings @regexp = Regexp.escape(@regexp) # Whitespace means nothing @regexp.gsub! /\\\ /, '\s+' # Fast variable finder @regexp.gsub! placeholder, '([^;]*|\S*)' # Get 'er done @regexp = Regexp.new(@regexp) end # You can zip this with the regexp captures to create a variable hash def regexp_variables return @regexp_variables if @regexp_variables @regexp_variables = Array.new @base_theme.scan(VARIABLE_MATCHER) {@regexp_variables << $2} @regexp_variables end # Convert all the ui.*.css files into sass goodness def convert_css(stylesheets) FileUtils.mkdir_p(File.join(stylesheets)) Dir.foreach @base_theme_directory do |file| next unless /^ui\..*\.css$/ =~ file next if %w{ui.all.css ui.base.css}.include? file css = File.read(File.join(@base_theme_directory, file)) open File.join(stylesheets, '_' + file.gsub(/\.css$/,'.sass').gsub(/^ui\./,'')), 'w' do |f| if file == THEME_FILENAME f.print(self.class.theme_css2sass(@base_theme)) else f.print(self.class.css2sass(css)) end f.close end end end # Create a sass file of variables names and copy the images def convert_theme(name, dir, stylesheets) if name == 'base' theme = @base_theme else theme = File.read(File.join(dir, THEME_FILENAME)) end FileUtils.mkdir_p stylesheets # Figure out the variables with the regexp vars = Hash.new regexp.match(theme).captures.each_with_index do |capture, index| # Remove variable comments capture.gsub! /\/\*\{\w*\}\*\/$/, '' # Update url capture.gsub! /^url\(images(.*)\)/, "image_url(\"jquery.ui/#{name}\\1\")" # Quote most things capture = "\"#{capture}\"" if capture =~ /[^#%0-9a-fptxm\-]/ and !(capture =~ /^image_url/) vars[VARIABLE_NAME_BASE + regexp_variables[index]] ||= capture end # Write out the theme sass open File.join(stylesheets, "#{name}.sass"), 'w' do |f| f.print JRAILS_MESSAGE2 # Preserve header comment (css2sass currently doesn't convert comments) theme =~ /\/\*\s*(.*)^\*\//m $1.each {|line| f.print line.gsub(/^(\s*\*\s*)/,'// ')} f.print "\n" vars.each do |variable_name, value| f.print "!#{variable_name} ||= #{value}\n" end f.print "\n@import jquery.ui/_theme.sass\n" end end # Converter for ui.theme.css which has the variable names def self.theme_css2sass(theme_css) # Install variable names and convert to sass sass = css2sass(theme_css.gsub(VARIABLE_MATCHER){"!#{VARIABLE_NAME_BASE}#{$2}"}) # Convert select lines from literal to programatic syntax sass.gsub!(/.*/){|x| /\!/=~x ? x.gsub(/:/,'=').gsub(/ solid /, ' "solid" ') : x} sass end # Sass is simply awesome def self.css2sass(css) sass = '' IO.popen("css2sass", 'r+') { |f| f.print(css); f.close_write; sass = f.read } return sass end end