ymdp 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/.document +5 -0
  2. data/.gitignore +21 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +17 -0
  5. data/Rakefile +53 -0
  6. data/VERSION +1 -0
  7. data/lib/application_view/application_view.rb +210 -0
  8. data/lib/application_view/asset_tag_helper.rb +106 -0
  9. data/lib/application_view/commands/generate.rb +3 -0
  10. data/lib/application_view/compiler/template_compiler.rb +417 -0
  11. data/lib/application_view/config.rb +39 -0
  12. data/lib/application_view/environment.rb +29 -0
  13. data/lib/application_view/generator/base.rb +15 -0
  14. data/lib/application_view/generator/templates/javascript.js +51 -0
  15. data/lib/application_view/generator/templates/stylesheet.css +5 -0
  16. data/lib/application_view/generator/templates/translation.pres +8 -0
  17. data/lib/application_view/generator/templates/view.html.haml +8 -0
  18. data/lib/application_view/generator/view.rb +170 -0
  19. data/lib/application_view/helpers.rb +4 -0
  20. data/lib/application_view/processor/compressor.rb +81 -0
  21. data/lib/application_view/processor/processor.rb +132 -0
  22. data/lib/application_view/processor/validator.rb +125 -0
  23. data/lib/application_view/support/file.rb +54 -0
  24. data/lib/application_view/support/form_post.rb +58 -0
  25. data/lib/application_view/support/g.rb +11 -0
  26. data/lib/application_view/support/growl.rb +36 -0
  27. data/lib/application_view/support/timer.rb +40 -0
  28. data/lib/application_view/support/w3c.rb +22 -0
  29. data/lib/application_view/tag_helper.rb +147 -0
  30. data/lib/application_view/translator/base.rb +387 -0
  31. data/lib/application_view/translator/blank.rb +58 -0
  32. data/lib/application_view/translator/ymdp_translate.rb +92 -0
  33. data/lib/ymdp.rb +1 -0
  34. data/test/helper.rb +10 -0
  35. data/test/test_ymdp.rb +4 -0
  36. data/ymdp.gemspec +77 -0
  37. metadata +92 -0
@@ -0,0 +1,125 @@
1
+ require 'support/file'
2
+
3
+ module ApplicationView
4
+ module Validator
5
+ class Base
6
+ extend ApplicationView::Config
7
+ extend ApplicationView::FileSupport
8
+ end
9
+
10
+ class HTML < Base
11
+ def self.validate(path)
12
+ html_display_path = display_path(path)
13
+
14
+ doctype = CONFIG["doctype"] || "HTML 4.0 Transitional"
15
+
16
+ resp = post_file_to_w3c_validator(path, doctype)
17
+ html = resp.read_body
18
+ if html.include? "[Valid]"
19
+ $stdout.puts " #{html_display_path} validating . . . OK"
20
+ else
21
+ log_path = "#{TMP_PATH}/#{File.basename(path)}_errors.html"
22
+ $stdout.puts " #{html_display_path} is not valid HTML, writing to #{display_path(log_path)}"
23
+ $stdout.puts
24
+ $stdout.puts " To view errors:"
25
+ $stdout.puts " open #{display_path(log_path)}"
26
+ $stdout.puts
27
+ File.open(log_path,'w') { |f| f.puts html }
28
+ $stdout.puts " Viewing errors..."
29
+
30
+ g("HTML validation errors found")
31
+ system "open #{log_path}"
32
+ raise "Invalid HTML"
33
+ end
34
+ end
35
+ end
36
+
37
+ class JavaScript < Base
38
+ def self.validate?
39
+ validate_embedded_js?
40
+ end
41
+
42
+ def self.validate(filename)
43
+ if validate?
44
+ validate_javascript(filename)
45
+ end
46
+ end
47
+
48
+ def self.use_jslint_settings?
49
+ !jslint_settings.blank?
50
+ end
51
+
52
+ def self.jslint_settings
53
+ <<-JSLINT
54
+ /*jslint bitwise: true, browser: true, evil: true, eqeqeq: true, immed: true, newcap: true, onevar: false, plusplus: true, regexp: true, undef: true, sub: true */
55
+ /*global YAHOO, openmail, OpenMailIntl, _gat, unescape, $, $$, $A, $H, $R, $w, $div, Event, Effect, Behavior, Try, PeriodicalExecuter, Element, identify, Sortable, window, I18n, Identity, Logger, OIB, Tags, ABTesting, Flash, Debug */
56
+ JSLINT
57
+ end
58
+
59
+ def self.jslint_settings_count
60
+ jslint_settings.to_s.split("\n").size
61
+ end
62
+
63
+ def self.pre_process(content)
64
+ content
65
+ end
66
+
67
+ def self.validate_javascript(path)
68
+ display = display_path(path)
69
+ $stdout.print " #{display} validating . . . "
70
+ output = ""
71
+
72
+ File.open(path) do |f|
73
+ output = f.read
74
+ end
75
+
76
+ output = pre_process(output)
77
+
78
+ js_fragment_path = File.expand_path("#{TMP_PATH}/#{File.basename(path)}_fragment")
79
+ fragment_display_path = display_path(js_fragment_path)
80
+
81
+ unless File.exists?(js_fragment_path)
82
+ File.open(js_fragment_path,'w') do |f|
83
+ f.puts jslint_settings if use_jslint_settings?
84
+ f.puts output
85
+ end
86
+
87
+ results = `java org.mozilla.javascript.tools.shell.Main ./script/jslint.js #{js_fragment_path}`
88
+
89
+ if results =~ /jslint: No problems found/
90
+ $stdout.puts "OK"
91
+ else
92
+ $stdout.puts "errors found!"
93
+ results.split("\n").each do |result|
94
+ if result =~ /line (\d+) character (\d+): (.*)/
95
+ line_number = $1.to_i
96
+ error = "Error at #{fragment_display_path} line #{line_number-jslint_settings_count} character #{$2}: #{$3}"
97
+ error += get_line_from_file(js_fragment_path, line_number)
98
+
99
+ $stdout.puts error
100
+ end
101
+ end
102
+ message = "Javascript Errors embedded in #{display}"
103
+ g(message)
104
+ raise message
105
+ end
106
+ end
107
+ end
108
+ end
109
+
110
+ class JSON < JavaScript
111
+ def self.validate?
112
+ validate_json_assets?
113
+ end
114
+
115
+ def pre_process(output)
116
+ output = output.gsub("\\u003C", "HELLO")
117
+ output = output.gsub("\\u003E", "HELLO")
118
+ output
119
+ end
120
+
121
+ def self.jslint_settings
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,54 @@
1
+ module ApplicationView
2
+ module FileSupport
3
+ def confirm_overwrite(path)
4
+ if File.exists?(path)
5
+ puts "File exists: #{display_path(path)}"
6
+ print " overwrite? (y/n)"
7
+ answer = $stdin.gets
8
+
9
+ answer =~ /^y/i
10
+ else
11
+ true
12
+ end
13
+ end
14
+
15
+ # friendlier display of paths
16
+ def display_path(path)
17
+ path = File.expand_path(path)
18
+ path.gsub(BASE_PATH, "")
19
+ end
20
+
21
+ # saves the output string to the filename given
22
+ #
23
+ def save_to_file(output, filename)
24
+ unless File.exists?(filename)
25
+ File.open(filename, "w") do |w|
26
+ w.write(output)
27
+ end
28
+ end
29
+ end
30
+
31
+ # given a path and line number, returns the line and two lines previous
32
+ #
33
+ def get_line_from_file(path, line_number)
34
+ line_number = line_number.to_i
35
+ output = ""
36
+ lines = []
37
+
38
+ File.open(path) do |f|
39
+ lines = f.readlines
40
+ end
41
+
42
+ output += "\n"
43
+
44
+ 3.times do |i|
45
+ line = lines[line_number-(3-i)]
46
+ output += line if line
47
+ end
48
+
49
+ output += "\n"
50
+
51
+ output
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,58 @@
1
+ # from http://devlicio.us/blogs/sergio_pereira/archive/2008/04/02/xhtml-validation-script-using-ruby.aspx
2
+
3
+ require 'rubygems'
4
+ require 'mime/types'
5
+ require 'net/http'
6
+ require 'CGI'
7
+
8
+ class FormField
9
+ attr_accessor :name, :value
10
+ def initialize( name, value )
11
+ @name = name
12
+ @value = value
13
+ end
14
+
15
+ def to_form_data
16
+ field = CGI::escape(@name)
17
+ "Content-Disposition: form-data; name=\"#{field}\"" +
18
+ "\r\n\r\n#{@value}\r\n"
19
+ end
20
+ end
21
+
22
+ class FileField
23
+ attr_accessor :name, :path, :content
24
+ def initialize( name, path, content )
25
+ @name = name
26
+ @path = "#{path}.html"
27
+ @content = content
28
+ end
29
+
30
+ def to_form_data
31
+ "Content-Disposition: form-data; " +
32
+ "name=\"#{CGI::escape(@name)}\"; " +
33
+ "filename=\"#{@path}\"\r\n" +
34
+ "Content-Transfer-Encoding: binary\r\n" +
35
+ "Content-Type: #{MIME::Types.type_for(@path)}" +
36
+ "\r\n\r\n#{@content}\r\n"
37
+ end
38
+ end
39
+
40
+ class MultipartPost
41
+ SEPARATOR = 'willvalidate-aaaaaabbbb0000'
42
+ REQ_HEADER = {
43
+ "Content-type" => "multipart/form-data, boundary=#{SEPARATOR} "
44
+ }
45
+
46
+ def self.build_form_data ( form_fields )
47
+ fields = []
48
+ form_fields.each do |key, value|
49
+ if value.instance_of?(File)
50
+ fields << FileField.new(key.to_s, value.path, value.read)
51
+ else
52
+ fields << FormField.new(key.to_s, value)
53
+ end
54
+ end
55
+ fields.collect {|f| "--#{SEPARATOR}\r\n#{f.to_form_data}" }.join("") +
56
+ "--#{SEPARATOR}--"
57
+ end
58
+ end
@@ -0,0 +1,11 @@
1
+ def g(s)
2
+ if CONFIG["growl"]
3
+ growl(s, :title => "YMDP")
4
+ end
5
+ rescue StandardError => e
6
+ if e.message =~ /Connection refused/
7
+ puts s
8
+ else
9
+ raise e
10
+ end
11
+ end
@@ -0,0 +1,36 @@
1
+ require 'rubygems'
2
+ require 'ruby-growl'
3
+ require 'pp'
4
+
5
+ $g_host ||= "localhost"
6
+ $g_priority ||= 0
7
+ $g_sticky ||= true
8
+
9
+ module Kernel
10
+ def growl(*args)
11
+ options = {}
12
+ if args.last.class == Hash
13
+ options = args.pop
14
+ end
15
+
16
+ title = options[:title] || 'g'
17
+ g = Growl.new $g_host, title, [$0]
18
+
19
+ messages =
20
+ if args.empty?
21
+ ['g!']
22
+ else
23
+ args.map { |i| i.pretty_inspect }
24
+ end
25
+
26
+ messages.each { |i| g.notify $0, title, i, $g_priority, $g_sticky }
27
+
28
+ if args.empty?
29
+ nil
30
+ elsif args.size == 1
31
+ args.first
32
+ else
33
+ args
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,40 @@
1
+ module ApplicationView
2
+ module Support
3
+ module Timer
4
+ def time(message="")
5
+ start_time = Time.now
6
+ yield
7
+ end_time = Time.now
8
+ put_elapsed_time(start_time, end_time, message)
9
+ end
10
+
11
+ def put_elapsed_time(start_time, end_time, message="")
12
+ seconds = end_time - start_time
13
+ if seconds > 59
14
+ minutes = seconds / 60.0
15
+ seconds = (minutes - minutes.to_i) * 60
16
+
17
+ m = minutes.to_i > 1 ? "minutes" : "minute"
18
+ elapsed_time = "#{minutes.to_i} #{m}"
19
+ if seconds > 0
20
+ s = seconds.to_i > 1 ? "seconds" : "minutes"
21
+ elapsed_time += ", #{seconds.to_i} #{s}"
22
+ end
23
+ else
24
+ s = seconds.to_i > 1 ? "seconds" : "minutes"
25
+ elapsed_time = "#{seconds.to_i} #{s}"
26
+ end
27
+
28
+ puts
29
+ e = ""
30
+ unless message.blank?
31
+ message += ". "
32
+ end
33
+ e = message + e
34
+ e += "Elapsed time: #{elapsed_time}"
35
+ puts e
36
+ g(e)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,22 @@
1
+ def post_file_to_w3c_validator(file_path, doc_type)
2
+ query = MultipartPost.build_form_data(
3
+ :uploaded_file => File.new(file_path, 'r'),
4
+ :charset => '(detect automatically)',
5
+ :doctype => doc_type,
6
+ :group => '1'
7
+ )
8
+
9
+ Net::HTTP.start('validator.w3.org') do |http|
10
+ http.post2("/check", query, MultipartPost::REQ_HEADER)
11
+ end
12
+ end
13
+
14
+ def valid_response?(w3c_response)
15
+ html = w3c_response.read_body
16
+ html.include? "[Valid]"
17
+ end
18
+
19
+ def w3c_valid?(file_path)
20
+ resp = post_file_to_w3c_validator(file_path, 'HTML 4.01 Strict')
21
+ valid_response?(resp)
22
+ end
@@ -0,0 +1,147 @@
1
+ module ActionView
2
+ module Helpers #:nodoc:
3
+ # Provides methods to generate HTML tags programmatically when you can't use
4
+ # a Builder. By default, they output XHTML compliant tags.
5
+ module TagHelper
6
+ include ERB::Util
7
+
8
+ BOOLEAN_ATTRIBUTES = %w(disabled readonly multiple checked).to_set
9
+ BOOLEAN_ATTRIBUTES.merge(BOOLEAN_ATTRIBUTES.map {|a| a.to_sym })
10
+
11
+ # Returns an empty HTML tag of type +name+ which by default is XHTML
12
+ # compliant. Set +open+ to true to create an open tag compatible
13
+ # with HTML 4.0 and below. Add HTML attributes by passing an attributes
14
+ # hash to +options+. Set +escape+ to false to disable attribute value
15
+ # escaping.
16
+ #
17
+ # ==== Options
18
+ # The +options+ hash is used with attributes with no value like (<tt>disabled</tt> and
19
+ # <tt>readonly</tt>), which you can give a value of true in the +options+ hash. You can use
20
+ # symbols or strings for the attribute names.
21
+ #
22
+ # ==== Examples
23
+ # tag("br")
24
+ # # => <br />
25
+ #
26
+ # tag("br", nil, true)
27
+ # # => <br>
28
+ #
29
+ # tag("input", { :type => 'text', :disabled => true })
30
+ # # => <input type="text" disabled="disabled" />
31
+ #
32
+ # tag("img", { :src => "open & shut.png" })
33
+ # # => <img src="open &amp; shut.png" />
34
+ #
35
+ # tag("img", { :src => "open &amp; shut.png" }, false, false)
36
+ # # => <img src="open &amp; shut.png" />
37
+ def tag(name, options = nil, open = false, escape = true)
38
+ "<#{name}#{tag_options(options, escape) if options}#{open ? ">" : " />"}"
39
+ end
40
+
41
+ # Returns an HTML block tag of type +name+ surrounding the +content+. Add
42
+ # HTML attributes by passing an attributes hash to +options+.
43
+ # Instead of passing the content as an argument, you can also use a block
44
+ # in which case, you pass your +options+ as the second parameter.
45
+ # Set escape to false to disable attribute value escaping.
46
+ #
47
+ # ==== Options
48
+ # The +options+ hash is used with attributes with no value like (<tt>disabled</tt> and
49
+ # <tt>readonly</tt>), which you can give a value of true in the +options+ hash. You can use
50
+ # symbols or strings for the attribute names.
51
+ #
52
+ # ==== Examples
53
+ # content_tag(:p, "Hello world!")
54
+ # # => <p>Hello world!</p>
55
+ # content_tag(:div, content_tag(:p, "Hello world!"), :class => "strong")
56
+ # # => <div class="strong"><p>Hello world!</p></div>
57
+ # content_tag("select", options, :multiple => true)
58
+ # # => <select multiple="multiple">...options...</select>
59
+ #
60
+ # <% content_tag :div, :class => "strong" do -%>
61
+ # Hello world!
62
+ # <% end -%>
63
+ # # => <div class="strong">Hello world!</div>
64
+ def content_tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block)
65
+ # if block_given?
66
+ # options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
67
+ # content_tag = content_tag_string(name, capture(&block), options, escape)
68
+ #
69
+ # if block_called_from_erb?(block)
70
+ # concat(content_tag)
71
+ # else
72
+ # content_tag
73
+ # end
74
+ # else
75
+ content_tag_string(name, content_or_options_with_block, options, escape)
76
+ # end
77
+ end
78
+
79
+ # Returns a CDATA section with the given +content+. CDATA sections
80
+ # are used to escape blocks of text containing characters which would
81
+ # otherwise be recognized as markup. CDATA sections begin with the string
82
+ # <tt><![CDATA[</tt> and end with (and may not contain) the string <tt>]]></tt>.
83
+ #
84
+ # ==== Examples
85
+ # cdata_section("<hello world>")
86
+ # # => <![CDATA[<hello world>]]>
87
+ #
88
+ # cdata_section(File.read("hello_world.txt"))
89
+ # # => <![CDATA[<hello from a text file]]>
90
+ def cdata_section(content)
91
+ "<![CDATA[#{content}]]>"
92
+ end
93
+
94
+ # Returns an escaped version of +html+ without affecting existing escaped entities.
95
+ #
96
+ # ==== Examples
97
+ # escape_once("1 > 2 &amp; 3")
98
+ # # => "1 &lt; 2 &amp; 3"
99
+ #
100
+ # escape_once("&lt;&lt; Accept & Checkout")
101
+ # # => "&lt;&lt; Accept &amp; Checkout"
102
+ def escape_once(html)
103
+ html.to_s.gsub(/[\"><]|&(?!([a-zA-Z]+|(#\d+));)/) { |special| ERB::Util::HTML_ESCAPE[special] }
104
+ end
105
+
106
+ private
107
+ BLOCK_CALLED_FROM_ERB = 'defined? __in_erb_template'
108
+
109
+ if RUBY_VERSION < '1.9.0'
110
+ # Check whether we're called from an erb template.
111
+ # We'd return a string in any other case, but erb <%= ... %>
112
+ # can't take an <% end %> later on, so we have to use <% ... %>
113
+ # and implicitly concat.
114
+ def block_called_from_erb?(block)
115
+ block && eval(BLOCK_CALLED_FROM_ERB, block)
116
+ end
117
+ else
118
+ def block_called_from_erb?(block)
119
+ block && eval(BLOCK_CALLED_FROM_ERB, block.binding)
120
+ end
121
+ end
122
+
123
+ def content_tag_string(name, content, options, escape = true)
124
+ tag_options = tag_options(options, escape) if options
125
+ "<#{name}#{tag_options}>#{content}</#{name}>"
126
+ end
127
+
128
+ def tag_options(options, escape = true)
129
+ unless options.blank?
130
+ attrs = []
131
+ if escape
132
+ options.each_pair do |key, value|
133
+ if BOOLEAN_ATTRIBUTES.include?(key)
134
+ attrs << %(#{key}="#{key}") if value
135
+ else
136
+ attrs << %(#{key}="#{escape_once(value)}") if !value.nil?
137
+ end
138
+ end
139
+ else
140
+ attrs = options.map { |key, value| %(#{key}="#{value}") }
141
+ end
142
+ " #{attrs.sort * ' '}" unless attrs.empty?
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end