dinsley-markaby 0.0.5

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 (35) hide show
  1. data/README +256 -0
  2. data/Rakefile +49 -0
  3. data/VERSION.yml +4 -0
  4. data/lib/markaby/builder.rb +289 -0
  5. data/lib/markaby/cssproxy.rb +48 -0
  6. data/lib/markaby/metaid.rb +16 -0
  7. data/lib/markaby/rails/action_controller_helpers.rb +13 -0
  8. data/lib/markaby/rails/template_handler.rb +21 -0
  9. data/lib/markaby/tags.rb +179 -0
  10. data/lib/markaby.rb +39 -0
  11. data/test/app_root/app/controllers/application_controller.rb +2 -0
  12. data/test/app_root/app/controllers/markaby_controller.rb +37 -0
  13. data/test/app_root/app/helpers/test_helper.rb +7 -0
  14. data/test/app_root/app/views/markaby/_monkeys.mab +12 -0
  15. data/test/app_root/app/views/markaby/broken.mab +7 -0
  16. data/test/app_root/app/views/markaby/create.mab +9 -0
  17. data/test/app_root/app/views/markaby/index.mab +7 -0
  18. data/test/app_root/app/views/markaby/multiple_forms.mab +7 -0
  19. data/test/app_root/config/boot.rb +115 -0
  20. data/test/app_root/config/database.yml +31 -0
  21. data/test/app_root/config/environment.rb +14 -0
  22. data/test/app_root/config/environments/in_memory.rb +0 -0
  23. data/test/app_root/config/environments/mysql.rb +0 -0
  24. data/test/app_root/config/environments/postgresql.rb +0 -0
  25. data/test/app_root/config/environments/sqlite.rb +0 -0
  26. data/test/app_root/config/environments/sqlite3.rb +0 -0
  27. data/test/app_root/config/routes.rb +4 -0
  28. data/test/app_root/lib/console_with_fixtures.rb +4 -0
  29. data/test/app_root/log/in_memory.log +4215 -0
  30. data/test/app_root/script/console +7 -0
  31. data/test/markaby_controller_test.rb +73 -0
  32. data/test/markaby_test.rb +122 -0
  33. data/test/monkeys.html +13 -0
  34. data/test/test_helper.rb +28 -0
  35. metadata +102 -0
@@ -0,0 +1,48 @@
1
+ module Markaby
2
+ # Class used by Markaby::Builder to store element options. Methods called
3
+ # against the CssProxy object are added as element classes or IDs.
4
+ #
5
+ # See the README for examples.
6
+ class CssProxy
7
+
8
+ # Creates a CssProxy object.
9
+ def initialize(builder, stream, sym)
10
+ @builder, @stream, @sym, @attrs = builder, stream, sym, {}
11
+
12
+ @original_stream_length = @stream.length
13
+
14
+ @builder.tag! @sym
15
+ end
16
+
17
+ # Adds attributes to an element. Bang methods set the :id attribute.
18
+ # Other methods add to the :class attribute.
19
+ def method_missing(id_or_class, *args, &block)
20
+ if (idc = id_or_class.to_s) =~ /!$/
21
+ @attrs[:id] = $`
22
+ else
23
+ @attrs[:class] = @attrs[:class].nil? ? idc : "#{@attrs[:class]} #{idc}".strip
24
+ end
25
+
26
+ unless args.empty?
27
+ if args.last.respond_to? :to_hash
28
+ @attrs.merge! args.pop.to_hash
29
+ end
30
+ end
31
+
32
+ args.push(@attrs)
33
+
34
+ while @stream.length > @original_stream_length
35
+ @stream.pop
36
+ end
37
+
38
+ if block
39
+ @builder.tag! @sym, *args, &block
40
+ else
41
+ @builder.tag! @sym, *args
42
+ end
43
+
44
+ return self
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,16 @@
1
+ # metaprogramming assistant -- metaid.rb
2
+ class Object # :nodoc:
3
+ # The hidden singleton lurks behind everyone
4
+ def metaclass; class << self; self; end; end
5
+ def meta_eval(&blk); metaclass.instance_eval(&blk); end
6
+
7
+ # Adds methods to a metaclass
8
+ def meta_def(name, &blk)
9
+ meta_eval { define_method(name, &blk) }
10
+ end
11
+
12
+ # Defines an instance method within a class
13
+ def class_def(name, &blk)
14
+ class_eval { define_method(name, &blk) }
15
+ end
16
+ end
@@ -0,0 +1,13 @@
1
+ module Markaby
2
+ module Rails
3
+ module ActionControllerHelpers
4
+ # Returns a string of HTML built from the attached +block+. Any +options+ are
5
+ # passed into the render method.
6
+ #
7
+ # Use this method in your controllers to output Markaby directly from inside.
8
+ def render_markaby(options = {}, &block)
9
+ render options.merge({ :text => Builder.new(options[:locals], self, &block).to_s })
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ module Markaby
2
+ module Rails
3
+ class TemplateHandler < ActionView::TemplateHandler
4
+ include ActionView::TemplateHandlers::Compilable
5
+
6
+ def compile(template)
7
+ <<-CODE
8
+ @output_buffer = '' if @output_buffer.blank?;
9
+
10
+ variables = @controller.instance_variable_names;
11
+ variables -= @controller.protected_instance_variables if @controller.respond_to?(:protected_instance_variables);
12
+ variables.each { |name| assigns[name.gsub('@','')] = @controller.instance_variable_get(name); };
13
+
14
+ output = Markaby::Builder.new(assigns.merge!(local_assigns), self);
15
+ output.instance_eval(#{template.source.dump});
16
+ output.to_s;
17
+ CODE
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,179 @@
1
+ module Markaby
2
+
3
+ FORM_TAGS = [ :form, :input, :select, :textarea ]
4
+ SELF_CLOSING_TAGS = [ :base, :meta, :link, :hr, :br, :param, :img, :area, :input, :col, :frame ]
5
+
6
+ # Common sets of attributes.
7
+ AttrCore = [:id, :class, :style, :title]
8
+ AttrI18n = [:lang, 'xml:lang'.intern, :dir]
9
+ AttrEvents = [:onclick, :ondblclick, :onmousedown, :onmouseup, :onmouseover, :onmousemove,
10
+ :onmouseout, :onkeypress, :onkeydown, :onkeyup]
11
+ AttrFocus = [:accesskey, :tabindex, :onfocus, :onblur]
12
+ AttrHAlign = [:align, :char, :charoff]
13
+ AttrVAlign = [:valign]
14
+ Attrs = AttrCore + AttrI18n + AttrEvents
15
+
16
+ # All the tags and attributes from XHTML 1.0 Strict
17
+ class XHTMLStrict
18
+ class << self
19
+ attr_accessor :tags, :tagset, :forms, :self_closing, :doctype
20
+ end
21
+ @doctype = ['-//W3C//DTD XHTML 1.0 Strict//EN', 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd']
22
+ @tagset = {
23
+ :html => AttrI18n + [:id, :xmlns],
24
+ :head => AttrI18n + [:id, :profile],
25
+ :title => AttrI18n + [:id],
26
+ :base => [:href, :id],
27
+ :meta => AttrI18n + [:id, :http, :name, :content, :scheme, 'http-equiv'.intern],
28
+ :link => Attrs + [:charset, :href, :hreflang, :type, :rel, :rev, :media],
29
+ :style => AttrI18n + [:id, :type, :media, :title, 'xml:space'.intern],
30
+ :script => [:id, :charset, :type, :src, :defer, 'xml:space'.intern],
31
+ :noscript => Attrs,
32
+ :body => Attrs + [:onload, :onunload],
33
+ :div => Attrs,
34
+ :p => Attrs,
35
+ :ul => Attrs,
36
+ :ol => Attrs,
37
+ :li => Attrs,
38
+ :dl => Attrs,
39
+ :dt => Attrs,
40
+ :dd => Attrs,
41
+ :address => Attrs,
42
+ :hr => Attrs,
43
+ :pre => Attrs + ['xml:space'.intern],
44
+ :blockquote => Attrs + [:cite],
45
+ :ins => Attrs + [:cite, :datetime],
46
+ :del => Attrs + [:cite, :datetime],
47
+ :a => Attrs + AttrFocus + [:charset, :type, :name, :href, :hreflang, :rel, :rev, :shape, :coords],
48
+ :span => Attrs,
49
+ :bdo => AttrCore + AttrEvents + [:lang, 'xml:lang'.intern, :dir],
50
+ :br => AttrCore,
51
+ :em => Attrs,
52
+ :strong => Attrs,
53
+ :dfn => Attrs,
54
+ :code => Attrs,
55
+ :samp => Attrs,
56
+ :kbd => Attrs,
57
+ :var => Attrs,
58
+ :cite => Attrs,
59
+ :abbr => Attrs,
60
+ :acronym => Attrs,
61
+ :q => Attrs + [:cite],
62
+ :sub => Attrs,
63
+ :sup => Attrs,
64
+ :tt => Attrs,
65
+ :i => Attrs,
66
+ :b => Attrs,
67
+ :big => Attrs,
68
+ :small => Attrs,
69
+ :object => Attrs + [:declare, :classid, :codebase, :data, :type, :codetype, :archive, :standby, :height, :width, :usemap, :name, :tabindex],
70
+ :param => [:id, :name, :value, :valuetype, :type],
71
+ :img => Attrs + [:src, :alt, :longdesc, :height, :width, :usemap, :ismap],
72
+ :map => AttrI18n + AttrEvents + [:id, :class, :style, :title, :name],
73
+ :area => Attrs + AttrFocus + [:shape, :coords, :href, :nohref, :alt],
74
+ :form => Attrs + [:action, :method, :enctype, :onsubmit, :onreset, :accept, :accept],
75
+ :label => Attrs + [:for, :accesskey, :onfocus, :onblur],
76
+ :input => Attrs + AttrFocus + [:type, :name, :value, :checked, :disabled, :readonly, :size, :maxlength, :src, :alt, :usemap, :onselect, :onchange, :accept],
77
+ :select => Attrs + [:name, :size, :multiple, :disabled, :tabindex, :onfocus, :onblur, :onchange],
78
+ :optgroup => Attrs + [:disabled, :label],
79
+ :option => Attrs + [:selected, :disabled, :label, :value],
80
+ :textarea => Attrs + AttrFocus + [:name, :rows, :cols, :disabled, :readonly, :onselect, :onchange],
81
+ :fieldset => Attrs,
82
+ :legend => Attrs + [:accesskey],
83
+ :button => Attrs + AttrFocus + [:name, :value, :type, :disabled],
84
+ :table => Attrs + [:summary, :width, :border, :frame, :rules, :cellspacing, :cellpadding],
85
+ :caption => Attrs,
86
+ :colgroup => Attrs + AttrHAlign + AttrVAlign + [:span, :width],
87
+ :col => Attrs + AttrHAlign + AttrVAlign + [:span, :width],
88
+ :thead => Attrs + AttrHAlign + AttrVAlign,
89
+ :tfoot => Attrs + AttrHAlign + AttrVAlign,
90
+ :tbody => Attrs + AttrHAlign + AttrVAlign,
91
+ :tr => Attrs + AttrHAlign + AttrVAlign,
92
+ :th => Attrs + AttrHAlign + AttrVAlign + [:abbr, :axis, :headers, :scope, :rowspan, :colspan],
93
+ :td => Attrs + AttrHAlign + AttrVAlign + [:abbr, :axis, :headers, :scope, :rowspan, :colspan],
94
+ :h1 => Attrs,
95
+ :h2 => Attrs,
96
+ :h3 => Attrs,
97
+ :h4 => Attrs,
98
+ :h5 => Attrs,
99
+ :h6 => Attrs
100
+ }
101
+
102
+ @tags = @tagset.keys
103
+ @forms = @tags & FORM_TAGS
104
+ @self_closing = @tags & SELF_CLOSING_TAGS
105
+ end
106
+
107
+ # Additional tags found in XHTML 1.0 Transitional
108
+ class XHTMLTransitional
109
+ class << self
110
+ attr_accessor :tags, :tagset, :forms, :self_closing, :doctype
111
+ end
112
+ @doctype = ['-//W3C//DTD XHTML 1.0 Transitional//EN', 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd']
113
+ @tagset = XHTMLStrict.tagset.merge \
114
+ :strike => Attrs,
115
+ :center => Attrs,
116
+ :dir => Attrs + [:compact],
117
+ :noframes => Attrs,
118
+ :basefont => [:id, :size, :color, :face],
119
+ :u => Attrs,
120
+ :menu => Attrs + [:compact],
121
+ :iframe => AttrCore + [:longdesc, :name, :src, :frameborder, :marginwidth, :marginheight, :scrolling, :align, :height, :width],
122
+ :font => AttrCore + AttrI18n + [:size, :color, :face],
123
+ :s => Attrs,
124
+ :applet => AttrCore + [:codebase, :archive, :code, :object, :alt, :name, :width, :height, :align, :hspace, :vspace],
125
+ :isindex => AttrCore + AttrI18n + [:prompt]
126
+
127
+ # Additional attributes found in XHTML 1.0 Transitional
128
+ { :script => [:language],
129
+ :a => [:target],
130
+ :td => [:bgcolor, :nowrap, :width, :height],
131
+ :p => [:align],
132
+ :h5 => [:align],
133
+ :h3 => [:align],
134
+ :li => [:type, :value],
135
+ :div => [:align],
136
+ :pre => [:width],
137
+ :body => [:background, :bgcolor, :text, :link, :vlink, :alink],
138
+ :ol => [:type, :compact, :start],
139
+ :h4 => [:align],
140
+ :h2 => [:align],
141
+ :object => [:align, :border, :hspace, :vspace],
142
+ :img => [:name, :align, :border, :hspace, :vspace],
143
+ :link => [:target],
144
+ :legend => [:align],
145
+ :dl => [:compact],
146
+ :input => [:align],
147
+ :h6 => [:align],
148
+ :hr => [:align, :noshade, :size, :width],
149
+ :base => [:target],
150
+ :ul => [:type, :compact],
151
+ :br => [:clear],
152
+ :form => [:name, :target],
153
+ :area => [:target],
154
+ :h1 => [:align]
155
+ }.each do |k, v|
156
+ @tagset[k] += v
157
+ end
158
+
159
+ @tags = @tagset.keys
160
+ @forms = @tags & FORM_TAGS
161
+ @self_closing = @tags & SELF_CLOSING_TAGS
162
+ end
163
+
164
+ # Additional tags found in XHTML 1.0 Frameset
165
+ class XHTMLFrameset
166
+ class << self
167
+ attr_accessor :tags, :tagset, :forms, :self_closing, :doctype
168
+ end
169
+ @doctype = ['-//W3C//DTD XHTML 1.0 Frameset//EN', 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd']
170
+ @tagset = XHTMLTransitional.tagset.merge \
171
+ :frameset => AttrCore + [:rows, :cols, :onload, :onunload],
172
+ :frame => AttrCore + [:longdesc, :name, :src, :frameborder, :marginwidth, :marginheight, :noresize, :scrolling]
173
+
174
+ @tags = @tagset.keys
175
+ @forms = @tags & FORM_TAGS
176
+ @self_closing = @tags & SELF_CLOSING_TAGS
177
+ end
178
+
179
+ end
data/lib/markaby.rb ADDED
@@ -0,0 +1,39 @@
1
+ # = About lib/markaby.rb
2
+ #
3
+ # By requiring <tt>lib/markaby</tt>, you can load Markaby's dependency (the Builder library,)
4
+ # as well as the full set of Markaby classes.
5
+ #
6
+ # For a full list of features and instructions, see the README.
7
+ $:.unshift File.expand_path(File.dirname(__FILE__))
8
+
9
+ # Markaby is a module containing all of the great Markaby classes that
10
+ # do such an excellent job.
11
+ #
12
+ # * Markaby::Builder: the class for actually calling the Ruby methods
13
+ # which write the HTML.
14
+ # * Markaby::CSSProxy: a class which adds element classes and IDs to
15
+ # elements when used within Markaby::Builder.
16
+ # * Markaby::MetAid: metaprogramming helper methods.
17
+ # * Markaby::Tags: lists the roles of various XHTML tags to help Builder
18
+ # use these tags as they are intended.
19
+ module Markaby
20
+ VERSION = '0.5'
21
+
22
+ class InvalidXhtmlError < StandardError; end
23
+ end
24
+
25
+ unless defined?(Builder)
26
+ require 'rubygems'
27
+ require 'builder'
28
+ end
29
+
30
+ require 'markaby/builder'
31
+ require 'markaby/cssproxy'
32
+ require 'markaby/metaid'
33
+
34
+ module Kernel
35
+ # Shortcut for creating a quick block of Markaby.
36
+ def mab(*args, &block)
37
+ Markaby::Builder.new(*args, &block).to_s
38
+ end
39
+ end
@@ -0,0 +1,2 @@
1
+ class ApplicationController < ActionController::Base
2
+ end
@@ -0,0 +1,37 @@
1
+ class MarkabyController < ApplicationController
2
+ helper :test
3
+
4
+ @@locals = { :monkeys => Monkey.find(:all) }
5
+
6
+ def rescue_action(e) raise e end;
7
+
8
+ def index
9
+ @monkeys = Monkey.find(:all)
10
+ end
11
+
12
+ def create
13
+ flash[:message] = 'Hello World'
14
+ end
15
+
16
+ def broken
17
+ end
18
+
19
+ def multiple_forms
20
+ end
21
+
22
+ def partial_rendering
23
+ render :partial => 'monkeys', :locals => @@locals
24
+ end
25
+
26
+ def partial_rendering_with_stringy_keys_in_local_assigns
27
+ render :partial => 'monkeys', :locals => { 'monkeys' => Monkey.find(:all) }
28
+ end
29
+
30
+ def inline_helper_rendering
31
+ render_markaby(:locals => @@locals) { ul { monkeys.each { |m| li m.name } } }
32
+ end
33
+
34
+ def basic_inline_rendering
35
+ render :inline => mab { ul { Monkey.find(:all).each { |m| li m.name } } }
36
+ end
37
+ end
@@ -0,0 +1,7 @@
1
+ module TestHelper
2
+ def check_ivar_exists(name)
3
+ unless instance_variables.include?(ivar_name = "@#{name}")
4
+ raise "#{ivar_name} does not exist"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ html {
2
+ head {
3
+ title "List 'o Monkeys"
4
+ }
5
+ body {
6
+ ul {
7
+ monkeys.each { |monkey|
8
+ li monkey.name
9
+ }
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,7 @@
1
+ div {
2
+ ul {
3
+ li 'one'
4
+ li 'two'
5
+ li supercalifragilisticexpialidocious
6
+ }
7
+ }
@@ -0,0 +1,9 @@
1
+ unless flash[:message].nil?
2
+ p { flash[:message] }
3
+ end
4
+
5
+ form_tag '/monkeys' do
6
+ div {
7
+ submit_tag 'Save'
8
+ }
9
+ end
@@ -0,0 +1,7 @@
1
+ ul {
2
+ check_ivar_exists :monkeys
3
+
4
+ @monkeys.each { |monkey|
5
+ li monkey.name
6
+ }
7
+ }
@@ -0,0 +1,7 @@
1
+ form_tag '/monkeys', :id => 'monkeys' do
2
+ div { submit_tag 'Save' }
3
+ end
4
+
5
+ form_tag '/bananas', :id => 'bananas' do
6
+ div { submit_tag 'Save' }
7
+ end
@@ -0,0 +1,115 @@
1
+ # Allow customization of the rails framework path
2
+ RAILS_FRAMEWORK_ROOT = (ENV['RAILS_FRAMEWORK_ROOT'] || "#{File.dirname(__FILE__)}/../../../../../../vendor/rails") unless defined?(RAILS_FRAMEWORK_ROOT)
3
+
4
+ # Don't change this file!
5
+ # Configure your app in config/environment.rb and config/environments/*.rb
6
+
7
+ RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
8
+
9
+ module Rails
10
+ class << self
11
+ def boot!
12
+ unless booted?
13
+ preinitialize
14
+ pick_boot.run
15
+ end
16
+ end
17
+
18
+ def booted?
19
+ defined? Rails::Initializer
20
+ end
21
+
22
+ def pick_boot
23
+ (vendor_rails? ? VendorBoot : GemBoot).new
24
+ end
25
+
26
+ def vendor_rails?
27
+ File.exist?(RAILS_FRAMEWORK_ROOT)
28
+ end
29
+
30
+ def preinitialize
31
+ load(preinitializer_path) if File.exist?(preinitializer_path)
32
+ end
33
+
34
+ def preinitializer_path
35
+ "#{RAILS_ROOT}/config/preinitializer.rb"
36
+ end
37
+ end
38
+
39
+ class Boot
40
+ def run
41
+ load_initializer
42
+ Rails::Initializer.run(:set_load_path)
43
+ end
44
+ end
45
+
46
+ class VendorBoot < Boot
47
+ def load_initializer
48
+ require "#{RAILS_FRAMEWORK_ROOT}/railties/lib/initializer"
49
+ Rails::Initializer.run(:install_gem_spec_stubs)
50
+ Rails::GemDependency.add_frozen_gem_path
51
+ end
52
+ end
53
+
54
+ class GemBoot < Boot
55
+ def load_initializer
56
+ self.class.load_rubygems
57
+ load_rails_gem
58
+ require 'initializer'
59
+ end
60
+
61
+ def load_rails_gem
62
+ if version = self.class.gem_version
63
+ gem 'rails', version
64
+ else
65
+ gem 'rails'
66
+ end
67
+ rescue Gem::LoadError => load_error
68
+ $stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
69
+ exit 1
70
+ end
71
+
72
+ class << self
73
+ def rubygems_version
74
+ Gem::RubyGemsVersion rescue nil
75
+ end
76
+
77
+ def gem_version
78
+ if defined? RAILS_GEM_VERSION
79
+ RAILS_GEM_VERSION
80
+ elsif ENV.include?('RAILS_GEM_VERSION')
81
+ ENV['RAILS_GEM_VERSION']
82
+ else
83
+ parse_gem_version(read_environment_rb)
84
+ end
85
+ end
86
+
87
+ def load_rubygems
88
+ require 'rubygems'
89
+ min_version = '1.3.1'
90
+ unless rubygems_version >= min_version
91
+ $stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
92
+ exit 1
93
+ end
94
+
95
+ rescue LoadError
96
+ $stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
97
+ exit 1
98
+ end
99
+
100
+ def parse_gem_version(text)
101
+ $1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
102
+ end
103
+
104
+ private
105
+ def read_environment_rb
106
+ environment_rb = "#{RAILS_ROOT}/config/environment.rb"
107
+ environment_rb = "#{HELPER_RAILS_ROOT}/config/environment.rb" unless File.exists?(environment_rb)
108
+ File.read(environment_rb)
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ # All that for this:
115
+ Rails.boot!