Updated to Builder 2.0 [DHH]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@4260 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
parent
a9e02fd99f
commit
71a570ffd7
|
@ -1,5 +1,7 @@
|
||||||
*SVN*
|
*SVN*
|
||||||
|
|
||||||
|
* Updated to Builder 2.0 [DHH]
|
||||||
|
|
||||||
* Add Array#split for dividing arrays into one or more subarrays by value or block. [Sam Stephenson]
|
* Add Array#split for dividing arrays into one or more subarrays by value or block. [Sam Stephenson]
|
||||||
|
|
||||||
*1.3.1* (April 6th, 2006)
|
*1.3.1* (April 6th, 2006)
|
||||||
|
|
|
@ -14,12 +14,15 @@ module Builder #:nodoc:
|
||||||
# methods (except for <tt>\_\_send__</tt> and <tt>\_\_id__</tt>).
|
# methods (except for <tt>\_\_send__</tt> and <tt>\_\_id__</tt>).
|
||||||
# BlankSlate is useful as a base class when writing classes that
|
# BlankSlate is useful as a base class when writing classes that
|
||||||
# depend upon <tt>method_missing</tt> (e.g. dynamic proxies).
|
# depend upon <tt>method_missing</tt> (e.g. dynamic proxies).
|
||||||
class BlankSlate #:nodoc:
|
class BlankSlate
|
||||||
class << self
|
class << self
|
||||||
|
|
||||||
|
# Hide the method named +name+ in the BlankSlate class. Don't
|
||||||
|
# hide +instance_eval+ or any method beginning with "__".
|
||||||
def hide(name)
|
def hide(name)
|
||||||
undef_method name if
|
undef_method name if
|
||||||
instance_methods.include?(name.to_s) and
|
instance_methods.include?(name.to_s) and
|
||||||
name !~ /^(__|instance_eval)/
|
name !~ /^(__|instance_eval)/
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -29,10 +32,14 @@ end
|
||||||
|
|
||||||
# Since Ruby is very dynamic, methods added to the ancestors of
|
# Since Ruby is very dynamic, methods added to the ancestors of
|
||||||
# BlankSlate <em>after BlankSlate is defined</em> will show up in the
|
# BlankSlate <em>after BlankSlate is defined</em> will show up in the
|
||||||
# list of available BlankSlate methods. We handle this by defining a hook in the Object and Kernel classes that will hide any defined
|
# list of available BlankSlate methods. We handle this by defining a
|
||||||
|
# hook in the Object and Kernel classes that will hide any defined
|
||||||
module Kernel #:nodoc:
|
module Kernel #:nodoc:
|
||||||
class << self
|
class << self
|
||||||
alias_method :blank_slate_method_added, :method_added
|
alias_method :blank_slate_method_added, :method_added
|
||||||
|
|
||||||
|
# Detect method additions to Kernel and remove them in the
|
||||||
|
# BlankSlate class.
|
||||||
def method_added(name)
|
def method_added(name)
|
||||||
blank_slate_method_added(name)
|
blank_slate_method_added(name)
|
||||||
return if self != Kernel
|
return if self != Kernel
|
||||||
|
@ -44,9 +51,12 @@ end
|
||||||
class Object #:nodoc:
|
class Object #:nodoc:
|
||||||
class << self
|
class << self
|
||||||
alias_method :blank_slate_method_added, :method_added
|
alias_method :blank_slate_method_added, :method_added
|
||||||
|
|
||||||
|
# Detect method additions to Object and remove them in the
|
||||||
|
# BlankSlate class.
|
||||||
def method_added(name)
|
def method_added(name)
|
||||||
blank_slate_method_added(name)
|
blank_slate_method_added(name)
|
||||||
return if self != Object
|
return if self != Object
|
||||||
Builder::BlankSlate.hide(name)
|
Builder::BlankSlate.hide(name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
# The XChar library is provided courtesy of Sam Ruby (See
|
||||||
|
# http://intertwingly.net/stories/2005/09/28/xchar.rb)
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------
|
||||||
|
|
||||||
|
# If the Builder::XChar module is not currently defined, fail on any
|
||||||
|
# name clashes in standard library classes.
|
||||||
|
|
||||||
|
module Builder
|
||||||
|
def self.check_for_name_collision(klass, method_name, defined_constant=nil)
|
||||||
|
if klass.instance_methods.include?(method_name)
|
||||||
|
fail RuntimeError,
|
||||||
|
"Name Collision: Method '#{method_name}' is already defined in #{klass}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if ! defined?(Builder::XChar)
|
||||||
|
Builder.check_for_name_collision(String, "to_xs")
|
||||||
|
Builder.check_for_name_collision(Fixnum, "xchr")
|
||||||
|
end
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
module Builder
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
# XML Character converter, from Sam Ruby:
|
||||||
|
# (see http://intertwingly.net/stories/2005/09/28/xchar.rb).
|
||||||
|
#
|
||||||
|
module XChar # :nodoc:
|
||||||
|
|
||||||
|
# See
|
||||||
|
# http://intertwingly.net/stories/2004/04/14/i18n.html#CleaningWindows
|
||||||
|
# for details.
|
||||||
|
CP1252 = { # :nodoc:
|
||||||
|
128 => 8364, # euro sign
|
||||||
|
130 => 8218, # single low-9 quotation mark
|
||||||
|
131 => 402, # latin small letter f with hook
|
||||||
|
132 => 8222, # double low-9 quotation mark
|
||||||
|
133 => 8230, # horizontal ellipsis
|
||||||
|
134 => 8224, # dagger
|
||||||
|
135 => 8225, # double dagger
|
||||||
|
136 => 710, # modifier letter circumflex accent
|
||||||
|
137 => 8240, # per mille sign
|
||||||
|
138 => 352, # latin capital letter s with caron
|
||||||
|
139 => 8249, # single left-pointing angle quotation mark
|
||||||
|
140 => 338, # latin capital ligature oe
|
||||||
|
142 => 381, # latin capital letter z with caron
|
||||||
|
145 => 8216, # left single quotation mark
|
||||||
|
146 => 8217, # right single quotation mark
|
||||||
|
147 => 8220, # left double quotation mark
|
||||||
|
148 => 8221, # right double quotation mark
|
||||||
|
149 => 8226, # bullet
|
||||||
|
150 => 8211, # en dash
|
||||||
|
151 => 8212, # em dash
|
||||||
|
152 => 732, # small tilde
|
||||||
|
153 => 8482, # trade mark sign
|
||||||
|
154 => 353, # latin small letter s with caron
|
||||||
|
155 => 8250, # single right-pointing angle quotation mark
|
||||||
|
156 => 339, # latin small ligature oe
|
||||||
|
158 => 382, # latin small letter z with caron
|
||||||
|
159 => 376, # latin capital letter y with diaeresis
|
||||||
|
}
|
||||||
|
|
||||||
|
# See http://www.w3.org/TR/REC-xml/#dt-chardata for details.
|
||||||
|
PREDEFINED = {
|
||||||
|
38 => '&', # ampersand
|
||||||
|
60 => '<', # left angle bracket
|
||||||
|
62 => '>', # right angle bracket
|
||||||
|
}
|
||||||
|
|
||||||
|
# See http://www.w3.org/TR/REC-xml/#charsets for details.
|
||||||
|
VALID = [
|
||||||
|
[0x9, 0xA, 0xD],
|
||||||
|
(0x20..0xD7FF),
|
||||||
|
(0xE000..0xFFFD),
|
||||||
|
(0x10000..0x10FFFF)
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# Enhance the Fixnum class with a XML escaped character conversion.
|
||||||
|
#
|
||||||
|
class Fixnum #:nodoc:
|
||||||
|
XChar = Builder::XChar if ! defined?(XChar)
|
||||||
|
|
||||||
|
# XML escaped version of chr
|
||||||
|
def xchr
|
||||||
|
n = XChar::CP1252[self] || self
|
||||||
|
n = 42 unless XChar::VALID.find {|range| range.include? n}
|
||||||
|
XChar::PREDEFINED[n] or (n<128 ? n.chr : "&##{n};")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# Enhance the String class with a XML escaped character version of
|
||||||
|
# to_s.
|
||||||
|
#
|
||||||
|
class String #:nodoc:
|
||||||
|
# XML escaped version of to_s
|
||||||
|
def to_xs
|
||||||
|
unpack('U*').map {|n| n.xchr}.join # ASCII, UTF-8
|
||||||
|
rescue
|
||||||
|
unpack('C*').map {|n| n.xchr}.join # ISO-8859-1, WIN-1252
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
require 'builder/blankslate'
|
require 'builder/blankslate'
|
||||||
|
|
||||||
module Builder #:nodoc:
|
module Builder
|
||||||
|
|
||||||
# Generic error for builder
|
# Generic error for builder
|
||||||
class IllegalBlockError < RuntimeError #:nodoc:
|
class IllegalBlockError < RuntimeError #:nodoc:
|
||||||
|
@ -14,7 +14,7 @@ module Builder #:nodoc:
|
||||||
|
|
||||||
# Create an XML markup builder.
|
# Create an XML markup builder.
|
||||||
#
|
#
|
||||||
# out:: Object receiving the markup.1 +out+ must respond to
|
# out:: Object receiving the markup. +out+ must respond to
|
||||||
# <tt><<</tt>.
|
# <tt><<</tt>.
|
||||||
# indent:: Number of spaces used for indentation (0 implies no
|
# indent:: Number of spaces used for indentation (0 implies no
|
||||||
# indentation and no line breaks).
|
# indentation and no line breaks).
|
||||||
|
@ -76,15 +76,15 @@ module Builder #:nodoc:
|
||||||
end
|
end
|
||||||
|
|
||||||
# Append text to the output target. Escape any markup. May be
|
# Append text to the output target. Escape any markup. May be
|
||||||
# used within the markup brackets as:
|
# used within the markup brakets as:
|
||||||
#
|
#
|
||||||
# builder.p { br; text! "HI" } #=> <p><br/>HI</p>
|
# builder.p { |b| b.br; b.text! "HI" } #=> <p><br/>HI</p>
|
||||||
def text!(text)
|
def text!(text)
|
||||||
_text(_escape(text))
|
_text(_escape(text))
|
||||||
end
|
end
|
||||||
|
|
||||||
# Append text to the output target without escaping any markup.
|
# Append text to the output target without escaping any markup.
|
||||||
# May be used within the markup brackets as:
|
# May be used within the markup brakets as:
|
||||||
#
|
#
|
||||||
# builder.p { |x| x << "<br/>HI" } #=> <p><br/>HI</p>
|
# builder.p { |x| x << "<br/>HI" } #=> <p><br/>HI</p>
|
||||||
#
|
#
|
||||||
|
@ -112,11 +112,13 @@ module Builder #:nodoc:
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
require 'builder/xchar'
|
||||||
def _escape(text)
|
def _escape(text)
|
||||||
text.
|
text.to_xs
|
||||||
gsub(%r{&}, '&').
|
end
|
||||||
gsub(%r{<}, '<').
|
|
||||||
gsub(%r{>}, '>')
|
def _escape_quote(text)
|
||||||
|
_escape(text).gsub(%r{"}, '"') # " WART
|
||||||
end
|
end
|
||||||
|
|
||||||
def _capture_outer_self(block)
|
def _capture_outer_self(block)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
#--
|
#--
|
||||||
# Copyright 2004 by Jim Weirich (jim@weirichhouse.org).
|
# Copyright 2004, 2005 by Jim Weirich (jim@weirichhouse.org).
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
||||||
# Permission is granted for use, copying, modification, distribution,
|
# Permission is granted for use, copying, modification, distribution,
|
||||||
|
@ -165,13 +165,23 @@ module Builder
|
||||||
# :target=><em>target_object</em>::
|
# :target=><em>target_object</em>::
|
||||||
# Object receiving the markup. +out+ must respond to the
|
# Object receiving the markup. +out+ must respond to the
|
||||||
# <tt><<</tt> operator. The default is a plain string target.
|
# <tt><<</tt> operator. The default is a plain string target.
|
||||||
|
#
|
||||||
# :indent=><em>indentation</em>::
|
# :indent=><em>indentation</em>::
|
||||||
# Number of spaces used for indentation. The default is no
|
# Number of spaces used for indentation. The default is no
|
||||||
# indentation and no line breaks.
|
# indentation and no line breaks.
|
||||||
|
#
|
||||||
# :margin=><em>initial_indentation_level</em>::
|
# :margin=><em>initial_indentation_level</em>::
|
||||||
# Amount of initial indentation (specified in levels, not
|
# Amount of initial indentation (specified in levels, not
|
||||||
# spaces).
|
# spaces).
|
||||||
#
|
#
|
||||||
|
# :escape_attrs=><b>OBSOLETE</em>::
|
||||||
|
# The :escape_attrs option is no longer supported by builder
|
||||||
|
# (and will be quietly ignored). String attribute values are
|
||||||
|
# now automatically escaped. If you need unescaped attribute
|
||||||
|
# values (perhaps you are using entities in the attribute
|
||||||
|
# values), then give the value as a Symbol. This allows much
|
||||||
|
# finer control over escaping attribute values.
|
||||||
|
#
|
||||||
def initialize(options={})
|
def initialize(options={})
|
||||||
indent = options[:indent] || 0
|
indent = options[:indent] || 0
|
||||||
margin = options[:margin] || 0
|
margin = options[:margin] || 0
|
||||||
|
@ -239,12 +249,13 @@ module Builder
|
||||||
[:version, :encoding, :standalone])
|
[:version, :encoding, :standalone])
|
||||||
end
|
end
|
||||||
|
|
||||||
# Surrounds the given text with a CDATA tag
|
# Insert a CDATA section into the XML markup.
|
||||||
#
|
#
|
||||||
# For example:
|
# For example:
|
||||||
#
|
#
|
||||||
# xml.cdata! "blah blah blah"
|
# xml.cdata!("text to be included in cdata")
|
||||||
# # => <![CDATA[blah blah blah]]>
|
# #=> <![CDATA[text to be included in cdata]]>
|
||||||
|
#
|
||||||
def cdata!(text)
|
def cdata!(text)
|
||||||
_ensure_no_block block_given?
|
_ensure_no_block block_given?
|
||||||
_special("<![CDATA[", "]]>", text, nil)
|
_special("<![CDATA[", "]]>", text, nil)
|
||||||
|
@ -289,10 +300,19 @@ module Builder
|
||||||
return if attrs.nil?
|
return if attrs.nil?
|
||||||
order.each do |k|
|
order.each do |k|
|
||||||
v = attrs[k]
|
v = attrs[k]
|
||||||
@target << %{ #{k}="#{v}"} if v
|
@target << %{ #{k}="#{_attr_value(v)}"} if v
|
||||||
end
|
end
|
||||||
attrs.each do |k, v|
|
attrs.each do |k, v|
|
||||||
@target << %{ #{k}="#{v}"} unless order.member?(k)
|
@target << %{ #{k}="#{_attr_value(v)}"} unless order.member?(k)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def _attr_value(value)
|
||||||
|
case value
|
||||||
|
when Symbol
|
||||||
|
value.to_s
|
||||||
|
else
|
||||||
|
_escape_quote(value.to_s)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue