Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
fixed scoping problem
  • Loading branch information
jlong committed Mar 27, 2006
1 parent d07487a commit 27e1e08
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 33 deletions.
56 changes: 53 additions & 3 deletions radius/DSL-SPEC
Expand Up @@ -160,10 +160,60 @@ This is almost completely implemented:
page.title
end

The short hand form of a tag:
= Shorthand

The short hand form of a tag:

<r:page:title />

Should be the equivalent of saying:
Should be the equivalent of saying:

<r:page><r:title /></r:page>


= Specificity

Given the following tag definitions:

nesting
extra:nesting
parent:child:nesting

And the following in a template:

<r:parent:extra:child:nesting />

The following specificity values should be assigned to each of the tags:

nesting => 1.0.0.0
extra:nesting => 1.0.1.0
parent:child:nesting => 1.1.0.1

Meaning that the parent:child:nesting tag should win. In the case of the following
tag in a template:

<r:parent:child:extra:nesting />

The following specificity values should be assigned to each of the tags:

nesting => 1.0.0.0
extra:nesting => 1.1.0.0
parent:child:nesting => 1.0.1.1

Meaning that extra:nesting would win because it is more "specific".

Values are assigned by assigning point values to each of the tags from right to
left. Given a tag found in a template with nesting four levels deep, the maximum
specificity a tag could be assigned would be:

1.1.1.1

One point for each of the levels. In the first example above, this would be a tag
defined for:

parent:extra:child:nesting

When looking up a tag, specificity values should be calculated for all tags
(which could apply in the current situation), and then the one with the highest
value should be returned.

<r:page><r:title /></r:page>
43 changes: 34 additions & 9 deletions radius/lib/radius.rb
Expand Up @@ -403,17 +403,42 @@ def stack(name, attributes, block)
# Returns a fully qualified tag name based on state of the
# tag binding stack.
def qualified_tag_name(name)
names = @tag_binding_stack.collect { |tag| tag.name }
while names.size > 0 do
round = names.dup
while round.size > 0 do
try = (round + [name]).join(':')
return try if @definitions.has_key? try
round.shift
nesting_parts = @tag_binding_stack.collect { |tag| tag.name }
nesting_parts << name unless nesting_parts.last == name
specific_name = nesting_parts.join(':') # specific_name always has the highest specificity
unless @definitions.has_key? specific_name
possible_matches = @definitions.keys.grep(/(^|:)#{name}$/)
specificity_pairs = possible_matches.collect { |tag| [numeric_specificity(tag, nesting_parts), tag] }
specificity = Hash[*specificity_pairs.flatten]
max = specificity.keys.max
if max != 0
specificity[max]
else
name
end
else
specific_name
end
end

# Returns the specificity for +tag_name+ at nesting defined by +nesting_parts+ as a number.
def numeric_specificity(tag_name, nesting_parts)
nesting_parts = nesting_parts.dup
name_parts = tag_name.split(':')
specificity = 0
value = 1
if nesting_parts.last == name_parts.last
while nesting_parts.size > 0
if nesting_parts.last == name_parts.last
specificity += value
name_parts.pop
end
nesting_parts.pop
value *= 0.1
end
names.pop
specificity = 0 if (name_parts.size > 0)
end
name
specificity
end
end

Expand Down
28 changes: 7 additions & 21 deletions radius/test/radius_test.rb
Expand Up @@ -157,16 +157,14 @@ def test_parse_tag_nesting
assert_parse_output "parent:nesting", "<r:parent:nesting />"
assert_parse_output "extra > nesting", "<r:extra:nesting />"
assert_parse_output "parent * child * nesting", "<r:parent:child:nesting />"
assert_parse_output "parent * child * nesting", "<r:parent><r:child:nesting /></r:parent>"
assert_parse_output "parent > extra > nesting", "<r:parent><r:extra><r:nesting /></r:extra></r:parent>"
assert_parse_output "parent > extra > nesting", "<r:parent:extra:nesting />"
assert_parse_output "parent > child > extra > nesting", "<r:parent><r:child><r:extra><r:nesting /></r:extra></r:child></r:parent>"
assert_parse_output "parent > child > extra > nesting", "<r:parent:child:extra:nesting />"
assert_parse_output "parent:extra:child:nesting", "<r:parent><r:extra><r:child><r:nesting /></r:child></r:extra></r:parent>"
assert_parse_output "parent:extra:child:nesting", "<r:parent:extra:child:nesting />"
assert_parse_output "parent * extra * child * nesting", "<r:parent:extra:child:nesting />"
assert_parse_output "parent > extra > child > extra > nesting", "<r:parent:extra:child:extra:nesting />"
assert_parse_output "parent > extra > child > extra > nesting", "<r:parent><r:extra><r:child><r:extra><r:nesting /></r:extra></r:child></r:extra></r:parent>"
assert_parse_output "extra * parent * child * nesting", "<r:extra:parent:child:nesting />"
assert_parse_output "extra > parent > nesting", "<r:extra><r:parent:nesting /></r:extra>"
assert_parse_output "extra > parent > child > nesting", "<r:extra:parent><r:child:nesting /></r:extra:parent>"
assert_parse_output "extra * parent * child * nesting", "<r:extra:parent><r:child:nesting /></r:extra:parent>"
assert_raises(Radius::UndefinedTagError) { @parser.parse("<r:child />") }
end

Expand Down Expand Up @@ -216,30 +214,18 @@ def test_tag_locals
assert_parse_output 'outer', "<r:outer:var />"
end













def xtest_parse_loops
def test_parse_loops
@item = nil
define_tag "each" do |tag|
result = []
["Larry", "Moe", "Curly"].each do |item|
tag.set_item_for('each:item', item)
tag.locals.item = item
result << tag.expand
end
result.join(tag.attr["between"] || "")
end
define_tag "each:item" do |tag|
tag.item
tag.locals.item
end
assert_parse_output %{Three Stooges: "Larry", "Moe", "Curly"}, %{Three Stooges: <r:each between=", ">"<r:item />"</r:each>}
end
Expand Down

0 comments on commit 27e1e08

Please sign in to comment.