ymdp 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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