rxhp 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/rxhp/attribute_validator.rb +89 -28
- data/lib/rxhp/composable_element.rb +4 -0
- data/lib/rxhp/constants.rb +9 -2
- data/lib/rxhp/data/html/attributes.rb +4 -4
- data/lib/rxhp/element.rb +39 -5
- data/lib/rxhp/error.rb +6 -0
- data/lib/rxhp/fragment.rb +1 -0
- data/lib/rxhp/html.rb +12 -0
- data/lib/rxhp/html_element.rb +22 -12
- data/lib/rxhp/html_self_closing_element.rb +4 -1
- data/lib/rxhp/html_singleton_element.rb +13 -4
- data/lib/rxhp/scope.rb +51 -27
- data/lib/rxhp/tags/html_tag.rb +3 -0
- metadata +19 -38
@@ -1,7 +1,25 @@
|
|
1
1
|
require 'rxhp/error'
|
2
2
|
|
3
3
|
module Rxhp
|
4
|
+
# Provide support for limiting or requiring attributes.
|
5
|
+
#
|
6
|
+
# Attributes can be:
|
7
|
+
# * whitelisted (see {ClassMethods#accept_attributes})
|
8
|
+
# * required (see {ClassMethods#require_attributes})
|
9
|
+
#
|
10
|
+
# Requiring an attribute automaticaly whitelists it.
|
11
|
+
#
|
12
|
+
# To use:
|
13
|
+
# * +include+ this module
|
14
|
+
# * whitelist/require attributes as appropriate
|
15
|
+
# * call {#validate_attributes!} from wherever seems appropriate - such
|
16
|
+
# {Rxhp::Element#validate!}
|
17
|
+
#
|
18
|
+
# Subclasses will automatically have validated attributes, and will
|
19
|
+
# copy the rules from their parent class. Additional attributes can be
|
20
|
+
# accepted or required in subclasses without affecting the parent class.
|
4
21
|
module AttributeValidator
|
22
|
+
# Indicates that a provided attribute was not whitelisted.
|
5
23
|
class UnacceptableAttributeError < ValidationError
|
6
24
|
attr_reader :element, :attribute, :value
|
7
25
|
def initialize element, attribute, value
|
@@ -10,6 +28,7 @@ module Rxhp
|
|
10
28
|
end
|
11
29
|
end
|
12
30
|
|
31
|
+
# Indicates that a required attribute was not provided.
|
13
32
|
class MissingRequiredAttributeError < ValidationError
|
14
33
|
attr_reader :element, :attribute
|
15
34
|
def initialize element, attribute
|
@@ -18,6 +37,13 @@ module Rxhp
|
|
18
37
|
end
|
19
38
|
end
|
20
39
|
|
40
|
+
# Whether or not the attributes are acceptable.
|
41
|
+
#
|
42
|
+
# If you need more details than just "it's invalid", call
|
43
|
+
# {#validate_attributes!} instead and examine the exceptions it raises.
|
44
|
+
#
|
45
|
+
# @return whether or not the attributes are all whitelisted, and all
|
46
|
+
# required attributes are provided.
|
21
47
|
def valid_attributes?
|
22
48
|
begin
|
23
49
|
self.validate_attributes!
|
@@ -27,6 +53,14 @@ module Rxhp
|
|
27
53
|
end
|
28
54
|
end
|
29
55
|
|
56
|
+
# Check if attributes are valid, and raise an exception if they're not.
|
57
|
+
#
|
58
|
+
# @raise {MissingRequiredAttributeError} if an attribute that is
|
59
|
+
# required was not provided.
|
60
|
+
# @raise {UnacceptableAttributeError} if a non-whitelisted attribute
|
61
|
+
# was provided.
|
62
|
+
# @return [true] if the attribute are all valid, and all required
|
63
|
+
# attributes are provided.
|
30
64
|
def validate_attributes!
|
31
65
|
# Check for required attributes
|
32
66
|
self.class.required_attributes.each do |matcher|
|
@@ -72,6 +106,56 @@ module Rxhp
|
|
72
106
|
end
|
73
107
|
end
|
74
108
|
|
109
|
+
module ClassMethods
|
110
|
+
attr_accessor :acceptable_attributes, :required_attributes
|
111
|
+
# Accept all attributes matching the specified pattern.
|
112
|
+
#
|
113
|
+
# @param pattern can be a:
|
114
|
+
# +Symbol+:: must equal the attribute name after converting to a
|
115
|
+
# +String+, and replacing underscores with hyphens.
|
116
|
+
# +Object+:: must match the attribute name with +===+.
|
117
|
+
# +Array+:: the members must be a any of the above that matches the
|
118
|
+
# attribute name.
|
119
|
+
# +Hash+:: the key can be any of the above that matches the
|
120
|
+
# attribute name; the value is matched against the
|
121
|
+
# attribute value in the same way.
|
122
|
+
# @example
|
123
|
+
# accept_attribute 'id'
|
124
|
+
# accept_attribute /^data-/
|
125
|
+
# accept_attributes ['href', 'src']
|
126
|
+
# accept_attributes ({ 'type' => ['checkbox', 'text', 'submit'] })
|
127
|
+
def accept_attributes pattern
|
128
|
+
acceptable_attributes.push pattern
|
129
|
+
end
|
130
|
+
alias :accept_attribute :accept_attributes
|
131
|
+
|
132
|
+
# Require an attribute matching the specified pattern.
|
133
|
+
#
|
134
|
+
# @param pattern accepts the same values as {#accept_attributes}
|
135
|
+
def require_attributes pattern
|
136
|
+
accept_attributes pattern
|
137
|
+
required_attributes.push pattern
|
138
|
+
end
|
139
|
+
alias :require_attribute :require_attributes
|
140
|
+
|
141
|
+
# Accept any attributes whatsoever.
|
142
|
+
def accept_all_attributes
|
143
|
+
accept_attributes Object
|
144
|
+
end
|
145
|
+
|
146
|
+
private
|
147
|
+
|
148
|
+
def inherited(subklass) # @Private @api
|
149
|
+
Rxhp::AttributeValidator.inherited(subklass)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
def self.name_from_symbol symbol
|
156
|
+
symbol.to_s.gsub('_', '-')
|
157
|
+
end
|
158
|
+
|
75
159
|
def self.match_value? matcher, value
|
76
160
|
if matcher == String
|
77
161
|
return (value.is_a? String) || (value.is_a? Symbol)
|
@@ -91,34 +175,18 @@ module Rxhp
|
|
91
175
|
end
|
92
176
|
end
|
93
177
|
|
94
|
-
|
95
|
-
symbol.to_s.gsub('_', '-')
|
96
|
-
end
|
97
|
-
|
178
|
+
# Include class methods, and initialize class variables.
|
98
179
|
def self.included(klass)
|
99
180
|
klass.extend(ClassMethods)
|
100
|
-
class << klass
|
101
|
-
attr_accessor :acceptable_attributes, :required_attributes
|
102
|
-
def accept_attributes matcher
|
103
|
-
acceptable_attributes.push matcher
|
104
|
-
end
|
105
|
-
alias :accept_attribute :accept_attributes
|
106
|
-
|
107
|
-
def require_attributes matcher
|
108
|
-
accept_attributes matcher
|
109
|
-
required_attributes.push matcher
|
110
|
-
end
|
111
|
-
alias :require_attribute :require_attributes
|
112
|
-
|
113
|
-
def accept_all_attributes
|
114
|
-
accept_attributes Object
|
115
|
-
end
|
116
|
-
end
|
117
181
|
|
118
182
|
klass.acceptable_attributes = []
|
119
183
|
klass.required_attributes = []
|
120
184
|
end
|
121
185
|
|
186
|
+
# Make subclasses validated too.
|
187
|
+
#
|
188
|
+
# Their accept/require lists will be copied from their superclass, but
|
189
|
+
# can be modified separately.
|
122
190
|
def self.inherited(subklass)
|
123
191
|
subklass.class_eval do
|
124
192
|
include Rxhp::AttributeValidator
|
@@ -126,12 +194,5 @@ module Rxhp
|
|
126
194
|
subklass.acceptable_attributes = subklass.superclass.acceptable_attributes.dup
|
127
195
|
subklass.required_attributes = subklass.superclass.required_attributes.dup
|
128
196
|
end
|
129
|
-
|
130
|
-
module ClassMethods
|
131
|
-
def inherited(subklass)
|
132
|
-
Rxhp::AttributeValidator.inherited(subklass)
|
133
|
-
end
|
134
|
-
|
135
|
-
end
|
136
197
|
end
|
137
198
|
end
|
@@ -12,6 +12,8 @@ module Rxhp
|
|
12
12
|
class ComposableElement < Rxhp::Element
|
13
13
|
include Rxhp::AttributeValidator
|
14
14
|
|
15
|
+
# Check that there are no detectable problems, such as invalid
|
16
|
+
# attributes.
|
15
17
|
def validate!
|
16
18
|
super
|
17
19
|
validate_attributes!
|
@@ -33,6 +35,8 @@ module Rxhp
|
|
33
35
|
end
|
34
36
|
|
35
37
|
# Implement this method - return an Rxhp::Element subclass.
|
38
|
+
#
|
39
|
+
# @yieldreturn child elements
|
36
40
|
def compose
|
37
41
|
raise NotImplementedError.new
|
38
42
|
end
|
data/lib/rxhp/constants.rb
CHANGED
@@ -1,10 +1,17 @@
|
|
1
1
|
module Rxhp
|
2
|
-
#
|
2
|
+
# Render 'nice' HTML
|
3
|
+
# @example
|
4
|
+
# <div><p>foo<br>bar</p></div>
|
3
5
|
HTML_FORMAT = :html
|
6
|
+
# Render ugly, but valid HTML
|
7
|
+
# @example
|
8
|
+
# <div><p>foo<br>bar</div>
|
4
9
|
TINY_HTML_FORMAT = :tiny_html
|
10
|
+
# Render XHTML
|
11
|
+
# @example
|
12
|
+
# <div><p>foo<br />bar</p></div>
|
5
13
|
XHTML_FORMAT = :xhtml
|
6
14
|
|
7
|
-
# Doctypes
|
8
15
|
HTML_5 = "<!DOCTYPE html>\n"
|
9
16
|
HTML_4_01_TRANSITIONAL = <<EOF
|
10
17
|
<!DOCTYPE HTML PUBLIC
|
@@ -2,10 +2,10 @@ require 'uri'
|
|
2
2
|
|
3
3
|
module Rxhp
|
4
4
|
module Html
|
5
|
-
# Given ['foo', 'bar', 'baz']
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
5
|
+
# Given +['foo', 'bar', 'baz']+, match:
|
6
|
+
# * +'foo'+
|
7
|
+
# * +'bar baz'+
|
8
|
+
# * +'foo bar baz'+
|
9
9
|
# etc.
|
10
10
|
def self.token_list tokens
|
11
11
|
token = tokens.join('|')
|
data/lib/rxhp/element.rb
CHANGED
@@ -9,18 +9,31 @@ module Rxhp
|
|
9
9
|
# error at render-time :p
|
10
10
|
class Element
|
11
11
|
include ::Rxhp::Scope
|
12
|
-
|
12
|
+
# A name => value map of attributes.
|
13
|
+
attr_accessor :attributes
|
14
|
+
# A list of child elements of this one.
|
15
|
+
attr_accessor :children
|
13
16
|
|
17
|
+
# Construct a new element with no children.
|
14
18
|
def initialize attributes = {}
|
15
19
|
@attributes = attributes
|
16
20
|
@children = Array.new
|
17
21
|
validate!
|
18
22
|
end
|
19
23
|
|
24
|
+
# Whether or not this element has any child element.
|
20
25
|
def children?
|
21
26
|
!children.empty?
|
22
27
|
end
|
23
28
|
|
29
|
+
# Whether there are any detectable problems with this element.
|
30
|
+
#
|
31
|
+
# See {AttributeValidator} for an example.
|
32
|
+
#
|
33
|
+
# You probably don't want to override this function in your subclasses;
|
34
|
+
# instead, you probably want to change {#validate!} to recognize your
|
35
|
+
# validations - all this does is check that it {#validate!} executes
|
36
|
+
# without raising a {ValidationError}.
|
24
37
|
def valid?
|
25
38
|
begin
|
26
39
|
validate!
|
@@ -30,6 +43,9 @@ module Rxhp
|
|
30
43
|
end
|
31
44
|
end
|
32
45
|
|
46
|
+
# Check that this element is valid.
|
47
|
+
#
|
48
|
+
# @raise Rxhp::ValidationError if a problem is found.
|
33
49
|
def validate!
|
34
50
|
# no-op
|
35
51
|
end
|
@@ -37,15 +53,23 @@ module Rxhp
|
|
37
53
|
# Return a flat HTML string for this element and all its' decendants.
|
38
54
|
#
|
39
55
|
# You probably don't want to implement this yourself - interesting
|
40
|
-
# implementations are in
|
41
|
-
#
|
56
|
+
# implementations are in {Fragment}, {HtmlElement}, and
|
57
|
+
# {ComposableElement}.
|
58
|
+
#
|
59
|
+
# Valid options include:
|
60
|
+
# +:pretty+:: add whitespace to make the output more readable. Defaults
|
61
|
+
# to true.
|
62
|
+
# +:indent+:: how many spaces to use to indent when +:pretty+ is true.
|
63
|
+
# +:format+:: See {Rxhp} for values. Default is {Rxhp::HTML_FORMAT}
|
64
|
+
# +:skip_doctype+:: Self explanatory. Defaults to false.
|
65
|
+
# +:doctype+:: See {Rxhp} for values. Default is {Rxhp::HTML_5}
|
42
66
|
def render options = {}
|
43
67
|
raise NotImplementedError.new
|
44
68
|
end
|
45
69
|
|
46
70
|
# Called when something that isn't an element is found in the tree.
|
47
71
|
#
|
48
|
-
# Implemented in
|
72
|
+
# Implemented in {HtmlElement}.
|
49
73
|
def render_string string, options
|
50
74
|
raise NotImplementedError.new
|
51
75
|
end
|
@@ -58,7 +82,11 @@ module Rxhp
|
|
58
82
|
flattened_children.map{ |child| render_child(child, options) }.join
|
59
83
|
end
|
60
84
|
|
61
|
-
# Fill default options
|
85
|
+
# Fill default render options.
|
86
|
+
#
|
87
|
+
# These are as defined for {#render}, with the addition of a
|
88
|
+
# +:depth+ value of 0. Other values aren't guaranteed to stay fixed,
|
89
|
+
# check source for current values.
|
62
90
|
def fill_options options
|
63
91
|
{
|
64
92
|
:pretty => true,
|
@@ -85,6 +113,12 @@ module Rxhp
|
|
85
113
|
end
|
86
114
|
end
|
87
115
|
|
116
|
+
# Normalize the children.
|
117
|
+
#
|
118
|
+
# For example, turn +['foo', 'bar']+ into +['foobar']+.
|
119
|
+
#
|
120
|
+
# This is needed to stop things like pretty printing adding extra
|
121
|
+
# whitespace between the two strings.
|
88
122
|
def flattened_children
|
89
123
|
no_frags = []
|
90
124
|
children.each do |node|
|
data/lib/rxhp/error.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
1
|
module Rxhp
|
2
|
+
# Base class for runtime errors from Rxhp.
|
3
|
+
#
|
4
|
+
# Most exceptions in Rxhp are actually subclasses of {Rxhp::ScriptError},
|
5
|
+
# which is not a subclass of this.
|
2
6
|
class Error < ::StandardError
|
3
7
|
end
|
4
8
|
|
9
|
+
# Base class for script errors from Rxhp.
|
5
10
|
class ScriptError < ::ScriptError
|
6
11
|
end
|
7
12
|
|
13
|
+
# Base class for element correctness errors from Rxhp.
|
8
14
|
class ValidationError < Rxhp::ScriptError
|
9
15
|
end
|
10
16
|
end
|
data/lib/rxhp/fragment.rb
CHANGED
@@ -6,6 +6,7 @@ module Rxhp
|
|
6
6
|
# Can be used like an array, or if you just need something that acts like
|
7
7
|
# an element - this is used internally as the root of all render trees.
|
8
8
|
class Fragment < Element
|
9
|
+
# Call {#render_children}
|
9
10
|
def render options = {}
|
10
11
|
self.render_children(options)
|
11
12
|
end
|
data/lib/rxhp/html.rb
CHANGED
@@ -2,7 +2,19 @@ require 'rxhp/data/html/attributes'
|
|
2
2
|
require 'rxhp/data/html/tags'
|
3
3
|
|
4
4
|
module Rxhp
|
5
|
+
# Namespace for all HTML-related classes and methods.
|
6
|
+
#
|
7
|
+
# Most of RXhp is for generic trees; everything that is HTML or XML
|
8
|
+
# specific is defined here, or in {HtmlElement} and its subclasses.
|
5
9
|
module Html
|
10
|
+
# Add a child node.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# include Rxhp::Html
|
14
|
+
# p do
|
15
|
+
# text 'foo'
|
16
|
+
# text 'bar'
|
17
|
+
# end
|
6
18
|
def fragment x
|
7
19
|
Rxhp::Scope.current.children.push x
|
8
20
|
end
|
data/lib/rxhp/html_element.rb
CHANGED
@@ -10,30 +10,38 @@ module Rxhp
|
|
10
10
|
#
|
11
11
|
# To use:
|
12
12
|
# 1. subclass
|
13
|
-
# 2. define tag_name
|
14
|
-
# 3. call Rxhp::Scope.define_element('foo', Foo) to register
|
15
|
-
#
|
13
|
+
# 2. define {#tag_name}
|
14
|
+
# 3. call +Rxhp::Scope.define_element('foo', Foo, MyModule)+ to register
|
15
|
+
# the class
|
16
|
+
# ... or just add a +define_tag+ line to html.rb.
|
16
17
|
#
|
17
18
|
# There's another two base classes for special types of html elements:
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
19
|
+
# {HtmlSelfClosingElement}::: elements where in HTML, the closing tag is
|
20
|
+
# optional - for example, <p> and <li>
|
21
|
+
# {HtmlSingletonElement}::: not only is the closing tag optional, but
|
22
|
+
# child elements are forbidden - for example,
|
23
|
+
# <br> and <img>
|
22
24
|
#
|
23
|
-
# These can also be defined via Rxhp::Html#define_tag
|
25
|
+
# These can also be defined via {Rxhp::Html#define_tag}
|
24
26
|
#
|
25
27
|
# If you're making a custom element that's purely server-side (i.e. is
|
26
|
-
# just composed of HTML elements), you want to subclass
|
27
|
-
# instead.
|
28
|
+
# just composed of HTML elements), you want to subclass
|
29
|
+
# {ComposableElement} instead.
|
28
30
|
class HtmlElement < Element
|
29
31
|
include Rxhp::AttributeValidator
|
30
32
|
accept_attributes Rxhp::Html::GLOBAL_ATTRIBUTES
|
31
33
|
accept_attributes Rxhp::Html::GLOBAL_EVENT_HANDLERS
|
32
34
|
|
35
|
+
# Literal string to include in render output.
|
36
|
+
#
|
37
|
+
# For example, +'html'+ will lead to +'<html>...</html>'+.
|
33
38
|
def tag_name
|
34
39
|
raise NotImplementedError.new
|
35
40
|
end
|
36
41
|
|
42
|
+
# Check that the element usage does nto have detectable errors.
|
43
|
+
#
|
44
|
+
# At the moment, this just checks for attribute correctness.
|
37
45
|
def validate!
|
38
46
|
super
|
39
47
|
validate_attributes!
|
@@ -42,7 +50,7 @@ module Rxhp
|
|
42
50
|
# Render the element.
|
43
51
|
#
|
44
52
|
# Pays attention to the formatter type, doctype, pretty print options,
|
45
|
-
# etc.
|
53
|
+
# etc. See {Element#render} for options.
|
46
54
|
def render options = {}
|
47
55
|
validate!
|
48
56
|
options = fill_options(options)
|
@@ -66,7 +74,9 @@ module Rxhp
|
|
66
74
|
end
|
67
75
|
end
|
68
76
|
|
69
|
-
#
|
77
|
+
# Render child elements.
|
78
|
+
#
|
79
|
+
# Increases the depth count for the sake of pretty printing.
|
70
80
|
def render_children options = {}
|
71
81
|
child_options = options.dup
|
72
82
|
child_options[:depth] += 1
|
@@ -4,11 +4,14 @@ module Rxhp
|
|
4
4
|
# Base class for HTML elements where the closing tag is optional, but
|
5
5
|
# there can still be children.
|
6
6
|
#
|
7
|
-
# For example,
|
7
|
+
# For example, +</p>+ is optional in HTML, but required in XHTML.
|
8
8
|
# This will change whether they're included or not based on the selected
|
9
9
|
# render format.
|
10
10
|
class HtmlSelfClosingElement < HtmlElement
|
11
11
|
protected
|
12
|
+
# Render a close tag if appropriate.
|
13
|
+
#
|
14
|
+
# The close tag is appropriate if we're outputting nice HTML, or XHTML.
|
12
15
|
def render_close_tag options
|
13
16
|
super if options[:format] != Rxhp::TINY_HTML_FORMAT
|
14
17
|
end
|
@@ -4,22 +4,31 @@ require 'rxhp/error'
|
|
4
4
|
module Rxhp
|
5
5
|
# Superclass for all HTML elements that should never have children.
|
6
6
|
#
|
7
|
-
# This is enforced. Examples include
|
7
|
+
# This is enforced. Examples include +<br>+, +<img>+ etc
|
8
8
|
#
|
9
9
|
# There is never a close tag:
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
10
|
+
# * in HTML it would be optional (and meaningless) anyway
|
11
|
+
# * people don't expect to see them
|
12
|
+
# * in XHTML, the opening tag will have been self closing.
|
13
13
|
class HtmlSingletonElement < HtmlElement
|
14
|
+
# Exception indicating that you gave a singleton element children.
|
15
|
+
#
|
16
|
+
# For example, +<br>foo</br>+ is invalid.
|
14
17
|
class HasChildrenError < Rxhp::ValidationError
|
15
18
|
end
|
16
19
|
|
20
|
+
# Check that there are no child elements.
|
21
|
+
#
|
22
|
+
# @raises {HasChildrenError}
|
17
23
|
def validate!
|
18
24
|
super
|
19
25
|
raise HasChildrenError.new unless children.empty?
|
20
26
|
end
|
21
27
|
|
22
28
|
protected
|
29
|
+
# Skip the closing tag.
|
30
|
+
#
|
31
|
+
# In XHTML mode, {#render_open_tag} should have made it self-closing.
|
23
32
|
def render_close_tag options
|
24
33
|
nil
|
25
34
|
end
|
data/lib/rxhp/scope.rb
CHANGED
@@ -1,52 +1,82 @@
|
|
1
|
+
require 'continuation' unless RUBY_VERSION =~ /^1\.8\./
|
1
2
|
module Rxhp
|
2
3
|
autoload :Fragment, 'rxhp/fragment'
|
3
4
|
# A place for factory methods to be defined.
|
4
5
|
#
|
5
|
-
# These are methods like Rxhp::Scope#h1 which creates an
|
6
|
-
#
|
6
|
+
# These are methods like +Rxhp::Scope#h1+ which creates an instance of
|
7
|
+
# +Rxhp::Html::H1+.
|
7
8
|
#
|
8
9
|
# The actual HTML classes are defined in rxhp/html.rb
|
9
10
|
#
|
10
11
|
module Scope
|
11
12
|
# Helper function to append a child to the current context.
|
12
|
-
#
|
13
|
+
#
|
14
|
+
# @example Here's one I made earlier
|
13
15
|
# inner = body { 'hi' }
|
14
16
|
# html do
|
15
17
|
# fragment inner
|
16
18
|
# end
|
19
|
+
#
|
20
|
+
# @example Multiple +String+ children
|
21
|
+
# p do
|
22
|
+
# text 'foo'
|
23
|
+
# text 'bar'
|
24
|
+
# end
|
17
25
|
def fragment x
|
18
26
|
Rxhp::Scope.current.children.push x
|
19
27
|
end
|
20
28
|
alias :frag :fragment
|
21
29
|
alias :text :fragment
|
22
30
|
|
31
|
+
# The element nesting scope.
|
32
|
+
#
|
33
|
+
# @example
|
34
|
+
# Rxhp::Scope.current.should be_a Rxhp::Fragment
|
35
|
+
# html.do
|
36
|
+
# Rxhp::Scope.current.should be_a Rxhp::Html::Html
|
37
|
+
# body do
|
38
|
+
# Rxhp::Scope.current.should be_a Rxhp::Html::Body
|
39
|
+
# end
|
40
|
+
# end
|
23
41
|
def self.current
|
24
|
-
|
42
|
+
callcc do |cc|
|
43
|
+
begin
|
44
|
+
throw(:rxhp_parent, cc)
|
45
|
+
rescue NameError, ArgumentError
|
46
|
+
Rxhp::Fragment.new
|
47
|
+
end
|
48
|
+
end
|
25
49
|
end
|
26
50
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
51
|
+
# Set the value of {#current} for a block, and call it.
|
52
|
+
#
|
53
|
+
# Used by {#define_element}
|
54
|
+
def self.with_parent parent, &block
|
55
|
+
# push element onto the render stack...
|
56
|
+
cc = catch(:rxhp_parent) do
|
57
|
+
# ... and call the block with that new stack
|
58
|
+
block.call
|
59
|
+
nil
|
34
60
|
end
|
35
|
-
|
61
|
+
cc.call(parent) if cc
|
36
62
|
end
|
37
63
|
|
38
|
-
# Define
|
64
|
+
# Define a factory method that takes a block, with a scope.
|
65
|
+
#
|
66
|
+
# @param [String] name is the name of the method to define
|
67
|
+
# @param [Class] klass is the {Element} subclass to construct
|
68
|
+
# @param [Module] namespace is where to define the method
|
39
69
|
#
|
40
|
-
#
|
70
|
+
# @example
|
71
|
+
# define_element tag, Tag
|
72
|
+
# tag
|
41
73
|
# tag 'content'
|
42
|
-
# tag
|
43
|
-
# tag
|
44
|
-
# tag(:attribute=>'value') do
|
45
|
-
# content
|
74
|
+
# tag(:attribute => value)
|
75
|
+
# tag('content', :attribute => 'value')
|
76
|
+
# tag(:attribute => 'value') do
|
77
|
+
# text 'content'
|
46
78
|
# end
|
47
|
-
|
48
|
-
# tag (:attribute => value)
|
49
|
-
def self.define_element name, klass, namespace
|
79
|
+
def self.define_element name, klass, namespace = Kernel
|
50
80
|
impl = Proc.new do |*args, &block|
|
51
81
|
# Yay for faking named parameters as a hash :p
|
52
82
|
children = nil
|
@@ -101,11 +131,5 @@ module Rxhp
|
|
101
131
|
# end
|
102
132
|
(class <<namespace; self; end).send(:define_method, name, impl)
|
103
133
|
end
|
104
|
-
|
105
|
-
private
|
106
|
-
|
107
|
-
def self.stack
|
108
|
-
Thread.current[:rxhp_scope_stack] ||= []
|
109
|
-
end
|
110
134
|
end
|
111
135
|
end
|
data/lib/rxhp/tags/html_tag.rb
CHANGED
metadata
CHANGED
@@ -1,33 +1,23 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: rxhp
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 1
|
9
|
-
- 1
|
10
|
-
version: 0.1.1
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Fred Emmott
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
date: 2012-01-23 00:00:00 Z
|
12
|
+
date: 2012-01-26 00:00:00.000000000Z
|
19
13
|
dependencies: []
|
20
|
-
|
21
14
|
description: An object-oriented validating HTML template system
|
22
|
-
email:
|
15
|
+
email:
|
23
16
|
- rxhp-gem@fredemmott.co.uk
|
24
17
|
executables: []
|
25
|
-
|
26
18
|
extensions: []
|
27
|
-
|
28
19
|
extra_rdoc_files: []
|
29
|
-
|
30
|
-
files:
|
20
|
+
files:
|
31
21
|
- lib/rxhp/attribute_validator.rb
|
32
22
|
- lib/rxhp/composable_element.rb
|
33
23
|
- lib/rxhp/constants.rb
|
@@ -45,36 +35,27 @@ files:
|
|
45
35
|
- lib/rxhp.rb
|
46
36
|
homepage: https://github.com/fredemmott/rxhp
|
47
37
|
licenses: []
|
48
|
-
|
49
38
|
post_install_message:
|
50
39
|
rdoc_options: []
|
51
|
-
|
52
|
-
require_paths:
|
40
|
+
require_paths:
|
53
41
|
- lib
|
54
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
43
|
none: false
|
56
|
-
requirements:
|
57
|
-
- -
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
|
60
|
-
|
61
|
-
- 0
|
62
|
-
version: "0"
|
63
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
49
|
none: false
|
65
|
-
requirements:
|
66
|
-
- -
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
|
69
|
-
segments:
|
70
|
-
- 0
|
71
|
-
version: "0"
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
72
54
|
requirements: []
|
73
|
-
|
74
55
|
rubyforge_project:
|
75
56
|
rubygems_version: 1.8.6
|
76
57
|
signing_key:
|
77
58
|
specification_version: 3
|
78
59
|
summary: An object-oriented validating HTML template system
|
79
60
|
test_files: []
|
80
|
-
|
61
|
+
has_rdoc:
|