Forum: Ruby tagz-5.0.0

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Ara H. (Guest)
on 2009-03-24 06:33
(Received via mailing list)
NAME

   tagz.rb

SYNOPSIS

   require Tagz

   include Tagz.globally

   a_(:href => "/foo"){ "bar" }  #=>  <a href="/foo">bar</a>

DESCRIPTION

   tagz.rb is generates html, xml, or any sgml variant like a small
ninja
   running across the backs of a herd of giraffes swatting of heads
like a
   mark-up weedwacker.  weighing in at less than 300 lines of code
tagz.rb adds
   an html/xml/sgml syntax to ruby that is both unobtrusive, safe, and
available
   globally to objects without the need for any builder or superfluous
objects.
   tagz.rb is designed for applications that generate html to be able
to do so
   easily in any context without heavyweight syntax or scoping issues,
like a
   ninja sword through butter.

FEATURES

   - use as a library or mixin

   - simple, clean and consistent mark-up that is easy to visually
     distinguish from other ruby methods

   - auto-compatibility with rails/actionview

   - ability to independently open and close tagz in markup

   - intelligent auto-escaping of both attributes and content for both
html
     and xml

   - validate your html/xml with 'ruby -c' syntax check

   - generally bitchin

   - no lame method_missing approach that prevents tagz like 'type'
from being
     generated

RAILS

   in config/environment.rb

     require 'tagz'

   in a helper

     def list_of_users
       ul_(:class => 'users'){
         @users.each{|user| li_{ user }}
       }
     end

   in a view

     <%=
       table_{
         rows.each do |row|
           tr_{
             row.each do |cell|
               td_{ cell }
             end
           }
         end
       }
     %>

   in a controller

     def ajax_responder
       text =
         tagz{
           table_{
             rows.each do |row|
               tr_{
                 row.each do |cell|
                   td_{ cell }
                 end
               }
             end
           }
         }

       render :text => text
     end

INSTALL

   gem install tagz

HISTORY
   5.0.0
     - introduce better escaping for attributes using xchar.rb approach
     - indroduce smart escaping for content
     - make Tagz.globally kick ass more hard
     - note that this version is not backward compatibile if you were
relying
       on tagz never escaping any content should be an ok upgrade for
most
       applications

   4.6.0
     - fix a bug with self closing tagz that had crept in 1.0.0 ->
4.2.0.  thx
       jeremy hinegardner

     - added tests from 1.0.0 back into svn

   4.4.0
     - remove dependancy on cgi lib, tagz is now completely standalone

   4.3.0
     - detect rails and auto-include into ActionController::Base and
include
       globally into ActionView::Base

   4.2.0
     - general lib cleanup
     - introduction of dual-mixin technique (Tagz.globally)
     - few small bug fixes
     - ninja tales

SAMPLES

   <========< samples/a.rb >========>

   ~ > cat samples/a.rb

     #
     # in the simplest case tagz generates html using a syntax which
safely mixes
     # in to any object
     #

     require 'tagz'
     include Tagz.globally

     class GiraffeModel
       def link
         a_(:href => "/giraffe/neck/42"){ "whack!" }
       end
     end

     puts GiraffeModel.new.link

   ~ > ruby samples/a.rb

     <a href="/giraffe/neck/42">whack!</a>


   <========< samples/b.rb >========>

   ~ > cat samples/b.rb

     #
     # tagz.rb mixes quite easily with your favourite templating
engine, avoiding
     # the need for '<% rows.each do |row| %> ... <% row.each do |
cell| %> '
     # madness and other types of logic to be coded in the templating
language,
     # leaving templating to template engines and logic and looping to
ruby -
     # unencumbered by extra funky syntax.  in rails tagz will
automatically be
     # available in your erb templates.
     #

     require 'tagz'
     include Tagz.globally

     require 'erb'

     rows = %w( a b c ), %w( 1 2 3 )

     template = ERB.new <<-ERB
       <html>
         <body>
           <%=
             table_{
               rows.each do |row|
                 tr_{
                   row.each do |cell|
                     td_{ cell }
                   end
                 }
               end
             }
           %>
         </body>
       </html>
     ERB

     puts template.result(binding)


   ~ > ruby samples/b.rb

       <html>
         <body>
           <table><tr><td>a</td><td>b</td><td>c</td></tr><tr><td>1</
td><td>2</td><td>3</td></tr></table>
         </body>
       </html>


   <========< samples/c.rb >========>

   ~ > cat samples/c.rb

     #
     # once you've learned to generate html using tagz you're primed
to generate
     # xml too
     #

     require 'tagz'
     include Tagz.globally

     doc =
       xml_{
         giraffe_{ 'large' }
         ninja_{ 'small' }
       }

     puts doc

   ~ > ruby samples/c.rb

     <xml><giraffe>large</giraffe><ninja>small</ninja></xml>


   <========< samples/d.rb >========>

   ~ > cat samples/d.rb

     #
     # tagz.rb doesn't cramp your style, allowing even invalid html to
be
     # generated.  note the use of the 'tagz' method, which can be
used both to
     # capture output and to append content to the top of the stack.
     #

     require 'tagz'
     include Tagz.globally

     def header
       tagz{
         html_
           body_(:class => 'ninja-like', :id => 'giraffe-slayer')

           ___ "<!-- this is the header -->"
       }
     end

     def footer
       tagz{
         ___ "<!-- this is the footer -->"

         body_
           html_
       }
     end

     puts header, footer

   ~ > ruby samples/d.rb

     <html><body class="ninja-like" id="giraffe-slayer">
     <!-- this is the header -->

     <!-- this is the footer -->
     <body><html>


   <========< samples/e.rb >========>

   ~ > cat samples/e.rb

     #
     # tagz.rb allows a safer method of mixin which requires any tagz
methods to be
     # insider a tagz block - tagz generating methods outside a tagz
block with
     # raise an error if tagz is included this way.  also notice that
the error is
     # reported from where it was raised - not from the bowels of the
the tagz.rb
     # lib.
     #

     require 'tagz'
     include Tagz

     puts tagz{
      html_{ 'works only in here' }
     }

     begin
       html_{ 'not out here' }
     rescue Object => e
       p :backtrace => e.backtrace
     end


   ~ > ruby samples/e.rb

     <html>works only in here</html>
     {:backtrace=>["samples/e.rb:17"]}


   <========< samples/f.rb >========>

   ~ > cat samples/f.rb

     #
     # tagz.rb can generate really compact html.  this is great to
save bandwidth
     # but can sometimes make reading the generated html a bit rough.
of course
     # using tidy or the dom inspector in firebug obviates the issue;
nevertheless
     # it's sometime nice to break things up a little.  you can use
'tagz << "\n"'
     # or the special shorthand '__' or '___' to accomplish this
     #

     require 'tagz'
     include Tagz.globally

     html =
       div_{
         span_{ true }
         __
         span_{ false }  # hey ryan, i fixed this ;-)
         ___

         ___ 'foo & escaped bar'
       }

     puts html

   ~ > ruby samples/f.rb

     <div><span>true</span>
     <span>false</span>

     foo & escaped bar
     </div>


   <========< samples/g.rb >========>

   ~ > cat samples/g.rb

     # tagz gives you low-level control of the output and makes even
dashersized
     # xml tagz easy enough to work with
     #

     require 'tagz'
     include Tagz.globally

     xml =
       root_{
         tagz__('foo-bar', :key => 'foo&bar'){ 'content' }

         tagz__('bar-foo')
         tagz.concat 'content'
         tagz.concat tagz.escape('foo&bar')
         __tagz('bar-foo')
       }

     puts xml


   ~ > ruby samples/g.rb

     <root><foo-bar key="foo&amp;bar">content</foo-bar><bar-
foo>contentfoo&amp;bar</bar-foo></root>




a @ http://codeforpeople.com/
Thomas S. (Guest)
on 2009-03-24 06:52
(Received via mailing list)
On Mar 24, 12:30 am, "ara.t.howard" <removed_email_address@domain.invalid> 
wrote:

>    - no lame method_missing approach that prevents tagz like 'type'  
> from being
>      generated

If you are not using method_missing than I take it one can't use it to
generate arbitrary XML?

T.
Ara H. (Guest)
on 2009-03-24 07:02
(Received via mailing list)
On Mar 23, 2009, at 10:48 PM, trans wrote:

>
>
> On Mar 24, 12:30 am, "ara.t.howard" <removed_email_address@domain.invalid> wrote:
>
>>    - no lame method_missing approach that prevents tagz like 'type'
>> from being
>>      generated
>
> If you are not using method_missing than I take it one can't use it to
> generate arbitrary XML?



it uses method_missing, just not in a lame way ;-)

cfp:~ > ruby -r tagz -e' include Tagz.globally; puts
anything_{ you_{ want_{ "can be generated" } } } '
<anything><you><want>can be generated</want></you></anything>


cfp:~ > ruby -r tagz -e' include Tagz.globally; raises_an_error{} '
-e:1: undefined method `raises_an_error' for main:Object (NoMethodError)



it is also very clever


cfp:~ > cat a.rb
require 'tagz'
include Tagz.globally

a = this_{ is_{ '<escaped>' } }
puts a

b = this_{ is_not_double_escaped_{ a } }
puts b



cfp:~ > ruby a.rb
<this><is>&lt;escaped&gt;</is></this>
<this><is_not_double_escaped><this><is>&lt;escaped&gt;</is></this></
is_not_double_escaped></this>


cheers.



a @ http://codeforpeople.com/
Brian C. (Guest)
on 2009-03-24 12:43
Ara Howard wrote:
>    tagz.rb is generates html, xml, or any sgml variant like a small
> ninja
>    running across the backs of a herd of giraffes swatting of heads
> like a
>    mark-up weedwacker.

Looks interesting.

Aside: people looking at this might also be interested in HAML. Several
of your examples look very similar to how I use HAML with Sinatra.

>    in a helper
>
>      def list_of_users
>        ul_(:class => 'users'){
>          @users.each{|user| li_{ user }}
>        }
>      end

    def list_of_users
      haml :_list_of_users
    end

    ...
    @@ _list_of_users
    %ul{:class=>'users'}
      - @users.each do |user|
        %li&= user

Alternatively it can be done inline:

    def list_of_users
      haml <<HAML
  %ul{:class=>'users'}
    - @users.each do |user|
      %li&= user
  HAML
    end

>    in a view
>
>      <%=
>        table_{
>          rows.each do |row|
>            tr_{
>              row.each do |cell|
>                td_{ cell }
>              end
>            }
>          end
>        }
>      %>

    %table
      - rows.each do |row|
        %tr
          - row.each do |cell|
            %td&= cell

>    in a controller
>
>      def ajax_responder
>        text =
>          tagz{
>            table_{
>              rows.each do |row|
>                tr_{
>                  row.each do |cell|
>                    td_{ cell }
>                  end
>                }
>              end
>            }
>          }
>
>        render :text => text
>      end

     def ajax_responder
       haml :_ajax_table
     end

     ...
     @@ _ajax_table
     %table
       - rows.each do |row|
         %tr
           - row.each do |cell|
             %td&= cell

I can see that tagz works particularly well where you want to generate
HTML snippets directly inline with your code. The inline form of HAML is
a bit icky because it needs to align with the left-hand edge. You could
fix this with a helper, but I prefer partials because they are easily
precompiled and cached.

Regards,

Brian.
Ara H. (Guest)
on 2009-03-24 16:58
(Received via mailing list)
On Mar 24, 2009, at 4:40 AM, Brian C. wrote:

> Several
> of your examples look very similar to how I use HAML with Sinatra.

you mean combining erb with the dsl i assume?

>           - row.each do |cell|
>             %td&= cell
>
> I can see that tagz works particularly well where you want to generate
> HTML snippets directly inline with your code. The inline form of
> HAML is
> a bit icky because it needs to align with the left-hand edge. You
> could
> fix this with a helper, but I prefer partials because they are easily
> precompiled and cached.



i've used this

     def unindent! s
       indent = nil
       s.each do |line|
         next if line =~ %r/^\s*$/
         indent = line[%r/^\s*/] and break
       end
       s.gsub! %r/^#{ indent }/, "" if indent
       s
     end

     def unindent s
       unindent! "#{ s }"
     end


to get around that 'left hand side' issue.

cheers!

a @ http://codeforpeople.com/
Brian C. (Guest)
on 2009-03-24 17:46
Ara Howard wrote:
> you mean combining erb with the dsl i assume?

At a lower level, the use of hashes to represent attributes is
strikingly similar. e.g.

    a_(:href => "/foo"){ "bar" }

compared to HAML:

    %a{:href => "/foo"} bar
or
    %a{:href => "/foo"}= "bar"

HAML lets you put any Ruby expression inside %a{...} which returns a
hash. Of course, tagz is real Ruby code, whereas HAML is its own
language.

The other thing which struck me was your use of nesting to build tables.
HAML really excels here, and the indentation-driven syntax means you
don't have to balance the closing parts. Somehow I find this more
natural for web page templates than for code.

> i've used this
>
>      def unindent! s

Yes, that's the sort of thing I was thinking of. HAML like this would
still need to go via a compilation phase each time it is executed,
whereas tagz is just run. Hence the benefit to keeping HAML snippets
separate and cached.

Regards,

Brian.
matt neuburg (Guest)
on 2009-03-24 19:00
(Received via mailing list)
ara.t.howard <removed_email_address@domain.invalid> wrote:

> > If you are not using method_missing than I take it one can't use it to
> > generate arbitrary XML?
>
> it uses method_missing, just not in a lame way ;-)

Not in a lame way, but in a way that means it can't be used in some
architectures. This is a very simplified version of what I'm really
doing, but it shows the problem. I'm using Builder like this:

require 'rubygems'
require 'builder'
require 'erb'

class BindingMaker
  def get_binding; binding; end
  def do_your_thing
    s = ""
    Builder::XmlMarkup.new(:target => s).div(testing)
    puts s
  end
  def testing
    "it worked"
  end
end

ERB.new("<% do_your_thing %>").result(BindingMaker.new.get_binding)
#=><div>it worked</div>

I'd like to switch to Tagz here but its method_missing isn't coming back
to my BindingMaker to resolve unrecognized terminology:

require 'rubygems'
require 'tagz'
require 'erb'

class BindingMaker
  def get_binding; binding; end
  def do_your_thing
    puts Tagz {div_ {testing()}}
  end
  def testing
    "it worked"
  end
end

ERB.new("<% do_your_thing %>").result(BindingMaker.new.get_binding)
#=> NoMethodError: undefined method 'testing' for Tagz:Module

m.
Ara H. (Guest)
on 2009-03-24 19:06
(Received via mailing list)
On Mar 24, 2009, at 9:43 AM, Brian C. wrote:

>    %a{:href => "/foo"} bar
> don't have to balance the closing parts. Somehow I find this more
> natural for web page templates than for code.


gotcha.

one thing i *really* like about tagz, for real mark-up coding, is that
i can use % in vim to match open/close tags in vim (or whatever your
fav is) and also can use 'ruby -c' to validate my markup.  because it
is valid ruby code you get all the ruby goodness and ruby editor
goodness for free.  it was a side effect i hadn't intended when
writing it but have grown to rely on - sorta like tab completion: i
just can't go back to visually scanning to make sure xml is balanced
and correct ;-)  my goal is generally to factor out enough tagz so my
erb templates fit on one screen and then i just trust tagz/ruby for
the rest.

cheers.

a @ http://codeforpeople.com/
Martin DeMello (Guest)
on 2009-03-24 19:13
(Received via mailing list)
On Tue, Mar 24, 2009 at 10:32 PM, ara.t.howard 
<removed_email_address@domain.invalid>
wrote:
> sorta like tab completion: i just can't go back to visually scanning to make
> sure xml is balanced and correct ;-)  my goal is generally to factor out

matchit.vim :)

martin
Ara H. (Guest)
on 2009-03-24 19:17
(Received via mailing list)
On Mar 24, 2009, at 10:56 AM, matt neuburg wrote:

> I'd like to switch to Tagz here but its method_missing isn't coming
> back
> to my BindingMaker to resolve unrecognized terminology:

you are trying too hard ;-)


cfp:~ > cat a.rb
require 'rubygems'
require 'tagz'
require 'erb'

class BindingMaker
   include Tagz.globally

   def get_binding; binding; end

   def do_your_thing
     puts div_{ testing }
   end

   def testing
     "it worked"
   end
end

ERB.new("<% do_your_thing %>").result(BindingMaker.new.get_binding)
# <div>it worked</div>


cfp:~ > ruby a.rb
<div>it worked</div>



tagz can be used as a library, like you were using it, but in that
case you need to be explicit about the receiver.  tagz is much simpler
to use in it's primary capacity - as mix-in - it is in this way that
completely POLS sgml generation and context/binding sensitivity can be
had.  the binding hack traditional builders use is there precisely to
disambiguate between contexts - tagz simply avoids the issue
altogether.  that's what i meant by 'lame': it's totally open, and yet
in a separate context with the builder pattern.


kind regards.



a @ http://codeforpeople.com/
Ara H. (Guest)
on 2009-03-24 19:18
(Received via mailing list)
On Mar 24, 2009, at 11:09 AM, Martin DeMello wrote:

> matchit.vim :)

i use that actually - but it really really crawls on large xml docs
with syntax hl off.  with tagz you just need a { another } and then to
bounce on the % key.

a @ http://codeforpeople.com/
Brian C. (Guest)
on 2009-03-24 19:56
Ara Howard wrote:
> one thing i *really* like about tagz, for real mark-up coding, is that
> i can use % in vim to match open/close tags in vim (or whatever your
> fav is) and also can use 'ruby -c' to validate my markup.
...
> i just can't go back to visually scanning to make sure xml is balanced
> and correct ;-)

With HAML, such validation isn't necessary: it always generates
well-formed XML, and there are no close tags to match.

You can write invalid HAML of course. The standalone 'haml' command-line
tool would probably validate it, but I haven't felt the need. My
controller tests flag if the HAML fails to compile.

What you *do* need with HAML is an editor which will indent/outdent a
block by two spaces - I use joe - but this is a commonly-needed edit
operation for Ruby code anyway.
matt neuburg (Guest)
on 2009-03-24 20:50
(Received via mailing list)
ara.t.howard <removed_email_address@domain.invalid> wrote:

> you are trying too hard ;-)

Well, it wouldn't be the first time!

> class BindingMaker
>    include Tagz.globally
>
> tagz can be used as a library, like you were using it, but in that
> case you need to be explicit about the receiver.  tagz is much simpler
> to use in it's primary capacity - as mix-in

Sorry, I knew about this approach and was avoiding it. I think it was
the term "globally" that had me scared off. This usually means, uh,
globally. But thanks to your hint, I see it is just an include like any
other. So what I really want to do is more like this:

b = BindingMaker.new
class << b; include Tagz.globally; end

This way I can use Tagz in that instance of the BindingMaker and nothing
else in my universe is affected. This should be perfect! Thx for the
nudge - m.
Ara H. (Guest)
on 2009-03-24 21:33
(Received via mailing list)
On Mar 24, 2009, at 12:46 PM, matt neuburg wrote:

> Sorry, I knew about this approach and was avoiding it. I think it was
> the term "globally" that had me scared off. This usually means, uh,
> globally. But thanks to your hint, I see it is just an include like
> any
> other. So what I really want to do is more like this:

yeah.  i means 'globally' in the target scope.  aka - a_{} works
outside the tagz{} context


> b = BindingMaker.new
> class << b; include Tagz.globally; end
>
> This way I can use Tagz in that instance of the BindingMaker and
> nothing
> else in my universe is affected. This should be perfect! Thx for the
> nudge - m.


clever!


a @ http://codeforpeople.com/
Andrew S. Townley (Guest)
on 2009-03-25 11:15
(Received via mailing list)
Hi Ara,

On Tue, 2009-03-24 at 13:30 +0900, ara.t.howard wrote:
>
>      generated
>

How does tagz handle namespaces?  I have to say that what you've done
here looks very impressive, and it seems to be exactly the kind of thing
I was looking for.  However, I need to make sure it has support for
namespaces, both for elements and for attributes before I can start
using it in anger.

Any examples/thoughts on how this could be done?

Cheers,

ast
Ara H. (Guest)
on 2009-03-25 16:28
(Received via mailing list)
On Mar 25, 2009, at 3:11 AM, Andrew S. Townley wrote:

> How does tagz handle namespaces?  I have to say that what you've done
> here looks very impressive, and it seems to be exactly the kind of
> thing
> I was looking for.  However, I need to make sure it has support for
> namespaces, both for elements and for attributes before I can start
> using it in anger.
>
> Any examples/thoughts on how this could be done?
>
> Cheers,

nothing explicit, but it'd be pretty simple to make some helper
methods using this technique

   >> send('foo:bar_', 'bar:foo' => 42){}
   => "<foo:bar bar:foo=\"42\"/>"

i'll mull on that.

a @ http://codeforpeople.com/
James G. (Guest)
on 2009-03-25 17:25
(Received via mailing list)
On Mar 25, 2009, at 9:23 AM, ara.t.howard wrote:

>> Any examples/thoughts on how this could be done?
>>
>> Cheers,
>
> nothing explicit, but it'd be pretty simple to make some helper
> methods using this technique
>
>  >> send('foo:bar_', 'bar:foo' => 42){}
>  => "<foo:bar bar:foo=\"42\"/>"
>
> i'll mull on that.

It might be neat to add some more dynamic method magic for this, like:

   foo_in_bar_ { … }

I realize that's a bad example in case you really have a tag with that
name, but you get the idea.

James Edward G. II
Tim P. (Guest)
on 2009-03-25 17:43
(Received via mailing list)
On Wed, Mar 25, 2009 at 9:21 AM, James G. <removed_email_address@domain.invalid>
wrote:
>>>
>> i'll mull on that.
>
> It might be neat to add some more dynamic method magic for this, like:
>
>  foo_in_bar_ { … }
>
> I realize that's a bad example in case you really have a tag with that name,
> but you get the idea.
>

Set the $KCODE and use a unicode character as the separator for
namespaces ...

$KCODE = 'u'
foo¦bar_('bar:foo' => 42)   #=> "<foo:bar bar:foo=\"42\">"


Blessings,
TwP
Ryan D. (Guest)
on 2009-03-25 20:58
(Received via mailing list)
On Mar 25, 2009, at 08:39 , Tim P. wrote:

> Set the $KCODE and use a unicode character as the separator for
> namespaces ...
>
> $KCODE = 'u'
> foo¦bar_('bar:foo' => 42)   #=> "<foo:bar bar:foo=\"42\">"

*brain asplodes*
Andrew S. Townley (Guest)
on 2009-03-25 22:21
(Received via mailing list)
On Wed, 2009-03-25 at 23:23 +0900, ara.t.howard wrote:
> >
> > Cheers,
>
> nothing explicit, but it'd be pretty simple to make some helper
> methods using this technique
>
>    >> send('foo:bar_', 'bar:foo' => 42){}
>    => "<foo:bar bar:foo=\"42\"/>"
>
> i'll mull on that.

Thanks.

If you had to register the namespaces first in some kind of tagz
registry, maybe you could do something by handling the NameError when
you did:

foo.bar_('bar:foo' => 42)

If it had registered a namespace prefix of foo, then it'd just "do the
right thing", otherwise, you'd get the normal name error.  This would
probably be the most logical syntax, but it's way beyond my Ruby magical
abilities to figure out how to actually make it work.

Still, I think it'd be the most readable of the proposed approaches...
I don't want to have to find unicode characters on my keyboard! :)

Cheers,

ast
Sean O. (Guest)
on 2009-03-25 23:02
(Received via mailing list)
On Tue, Mar 24, 2009 at 6:46 PM, matt neuburg 
<removed_email_address@domain.invalid> wrote:
>
> b = BindingMaker.new
> class << b; include Tagz.globally; end
>

FYI, you could do this instead:

  b.extend(Tagz.globally)

Regards,
Sean
Ara H. (Guest)
on 2009-03-26 02:20
(Received via mailing list)
On Mar 25, 2009, at 9:21 AM, James G. wrote:

> It might be neat to add some more dynamic method magic for this, like:
>
>  foo_in_bar_ { … }
>
> I realize that's a bad example in case you really have a tag with
> that name, but you get the idea.



i actually did that with xx at one point.

i think that, or some proxy object is the way to go.


a @ http://codeforpeople.com/
Ara H. (Guest)
on 2009-03-26 02:21
(Received via mailing list)
On Mar 25, 2009, at 9:39 AM, Tim P. wrote:

> Set the $KCODE and use a unicode character as the separator for
> namespaces ...
>
> $KCODE = 'u'
> foo¦bar_('bar:foo' => 42)   #=> "<foo:bar bar:foo=\"42\">"

wow.

clever!

a @ http://codeforpeople.com/
Andrew S. Townley (Guest)
on 2009-03-26 02:29
(Received via mailing list)
On Thu, 2009-03-26 at 09:16 +0900, ara.t.howard wrote:
>
> i actually did that with xx at one point.
>
> i think that, or some proxy object is the way to go.

I think in order to do namespaces correctly, you'd still need some kind
of registry, and some way to control emitting the namespace declarations
and prefixes at the right time.

There would still be times when you'd want to suppress it (like the
default case), but at the "top" of the relevant element (like the
document's root node), you'd want to be able to have it emit the
declarations.

Of course, (really dreaming now), but it would be _really_cool_ if it
could manage the nested scopes automatically and ensure that you'd spit
out all of the required namespaces used by all of the nested scopes....

I know I'm not making your day here... :)
Ara H. (Guest)
on 2009-03-26 02:34
(Received via mailing list)
On Mar 25, 2009, at 2:17 PM, Andrew S. Townley wrote:

> probably be the most logical syntax, but it's way beyond my Ruby
> magical
> abilities to figure out how to actually make it work.
>
> Still, I think it'd be the most readable of the proposed approaches...
> I don't want to have to find unicode characters on my keyboard! :)
>
> Cheers,

how about this


cfp:~ > cat a.rb
require 'rubygems'
require 'tagz'

class Namespace
   def initialize &block
     @ns = block.call.to_s
     @context = block
     @self = eval 'self', block
   end

   instance_methods.each{|m| undef_method if m[%r/__/]}

   def method_missing m, *a, &b
     if m.to_s[%r/^_|_$/]
       @self.send("#{ @ns }:#{ m }", *a, &b)
     else
       "#{ @ns }:#{ m }"
     end
   end
end

include Tagz.globally

a = Namespace.new{ :a }
b = Namespace.new{ :b }

xml =
   a.root_{
     a.foo_(b.bar => 'bar'){ 'content' }
     b.bar_(a.foo => 'foo'){ 'content' }
   }

puts xml



cfp:~ > ruby a.rb
<a:root><a:foo b:bar="bar">content</a:foo><b:bar a:foo="foo">content</
b:bar></a:root>






a @ http://codeforpeople.com/
Andrew S. Townley (Guest)
on 2009-03-26 02:43
(Received via mailing list)
On Thu, 2009-03-26 at 09:30 +0900, ara.t.howard wrote:
> > If it had registered a namespace prefix of foo, then it'd just "do the
> how about this
I like it, but would change it a bit to allow you to initialize the
namespace URI.  Not sure what you'd do with a default namespace
declaration...

>
> cfp:~ > cat a.rb
> require 'rubygems'
> require 'tagz'
>
> class Namespace
>    def initialize(nsuri) &block
       @nsuri = nsuri
>      else
> xml =
> <a:root xmlns:a="..." xmlns:b="..."><a:foo b:bar="bar">content</a:foo><b:bar 
a:foo="foo">content</
> b:bar></a:root>
>

What do you think?
Andrew S. Townley (Guest)
on 2009-03-26 13:47
(Received via mailing list)
On Thu, 2009-03-26 at 09:30 +0900, ara.t.howard wrote:
>
> how about this
>

Apologies.  Forgot to say thanks for your help.  Your suggestion is
probably good enough for what I need to do, and I can try to manage the
namespace declarations manually somehow, or actually implement part of
what I suggested.

Looking forward to getting started with tagz!

Cheers,

ast
Ara H. (Guest)
on 2009-03-26 19:32
(Received via mailing list)
On Mar 26, 2009, at 5:43 AM, Andrew S. Townley wrote:

> ast
if that's the case i might roll something like that into tagz.

i'll post any other ideas i have here - really appreciate the feedback!

cheers.

a @ http://codeforpeople.com/
jonty (Guest)
on 2009-03-27 00:51
(Received via mailing list)
I have been using haml out of necessity recently (sinatra), erb is too
much like hard work.
I find that haml is deeply frustrating as getting the whitespace right
to nest things properly is, quite frankly, a pain.
Markaby used the right sort of syntax I think and therefore I am
mightily intrigued by Tagz.

Is it fast??

Thankyou Ara - I will try it our tomorrow.
Ara H. (Guest)
on 2009-03-27 04:39
(Received via mailing list)
On Mar 26, 2009, at 4:47 PM, jonty wrote:

> I have been using haml out of necessity recently (sinatra), erb is
> too much like hard work.
> I find that haml is deeply frustrating as getting the whitespace
> right to nest things properly is, quite frankly, a pain.
> Markaby used the right sort of syntax I think and therefore I am
> mightily intrigued by Tagz.
>
> Is it fast??


it's fairly fast, but not as fast as erb.

it's faster that builder or rexml for xml though.

i actually find mixing erb and tagz is the best approach.  my erb
templates are generally < 100 lines and look something like


<title> foobar </title>

<%=

   ul_(:class => 'pretty'{
     @records.each do |record|
       li_{ record.name }
     end
   }

%>

in erb...


when that gets to ugly i factor or helpers that look like this

def the_list
   ul_(:class => 'pretty'{
     @records.each do |record|
       li_{ record.name }
     end
   }
end

and then tagz really starts to shine - you can stay in erb for the
designer friendly bits and use straight tagz or factored out tagz for
the logic bits.


cheers.

a @ http://codeforpeople.com/
Ryan D. (Guest)
on 2009-03-27 05:15
(Received via mailing list)
On Mar 26, 2009, at 15:47 , jonty wrote:

> I have been using haml out of necessity recently (sinatra), erb is
> too much like hard work.
> I find that haml is deeply frustrating as getting the whitespace
> right to nest things properly is, quite frankly, a pain.
> Markaby used the right sort of syntax I think and therefore I am
> mightily intrigued by Tagz.
>
> Is it fast??

http://blog.zenspider.com/2009/02/tagz-vs-markabyb...
Andrew S. Townley (Guest)
on 2009-03-27 13:20
(Received via mailing list)
On Fri, 2009-03-27 at 02:28 +0900, ara.t.howard wrote:
> On Mar 26, 2009, at 5:43 AM, Andrew S. Townley wrote:
> if that's the case i might roll something like that into tagz.

That would be fantastic.

> i'll post any other ideas i have here - really appreciate the feedback!

I'm looking at trying to figure out how to do the emit stuff, and I
think that the Namespace class should certainly be part of Tagz.

New would do something similar to your example, but with also adding the
Namespace URI, e.g. (example from
http://www.w3schools.com/Xforms/xforms_namespace.asp)

include Tagz.globally

xhtml = Tagz::Namespace.new(:xhtml => "http://www.w3.org/1999/xhtml")
xf = Tagz::Namespace.new(:xf => "http://www.w3.org/2002/xforms")

etc.

I tried to do this based on the example you provided, but I'm getting an
error I don't understand.  I'm sure it's due to scoping issues, but I've
no idea how to fix it.

I also discovered that output of empty elements doesn't behave as I'd
expect.  If you do

empty_element_

you get "<empty_element>"

rather than "<empty_element/>"

I think this can be fixed easily with a check to see if the value of
tagz is empty on line 62.

Any ideas as to what's going on?

excalibur$ cat /tmp/a.rb
require 'rubygems'
require 'tagz'

class Namespace
  def initialize hash, &block
     @prefix, @uri = hash.inject([]) { |a, (k, v)| a << k << v }
     @context = block
     @self = eval 'self', block
  end

  instance_methods.each{|m| undef_method if m[%r/__/]}

  def emit_ns
    { "xmlns:#{ @prefix }".to_sym => "#{@uri}" }
  end

  def method_missing m, *a, &b
    if m.to_s[%r/^_|_$/]
      @self.send("#{ @prefix }:#{ m }", *a, &b)
    else
      "#{ @prefix }:#{ m }"
    end
  end
end

include Tagz.globally

xhtml = Namespace.new(:xhtml => "http://www.w3.org/1999/xhtml")
xf = Namespace.new(:xf => "http://www.w3.org/2002/xforms")

puts xhtml.emit_ns.inspect
puts xf.emit_ns.inspect

# BUG!!
puts empty_element_

doc =
  xhtml.html_(xhmtl.emit_ns, xf.emit_ns) {
    xhtml.head_{
       xhtml.title_ "Important Document"
       xf.model_{
         xf.instance_{
           person_{
             fname_
             lname_
           }
         }
       }
       xf.submission(:id => "form1", :method => "get", :action =>
"doit.jsp")
    }
    xhtml.body_{
      "..."
    }
  }
excalibur$ ruby /tmp/a.rb
{:"xmlns:xhtml"=>"http://www.w3.org/1999/xhtml"}
{:"xmlns:xf"=>"http://www.w3.org/2002/xforms"}
<empty_element>
/tmp/a.rb:38: undefined local variable or method `xhmtl' for
#<Object:0x7f1e7ce77358 @tagz=nil> (NameError)
Andrew S. Townley (Guest)
on 2009-03-27 14:26
(Received via mailing list)
Apologies for the typo earlier.  I think I have it mostly working now,
but it would need a couple of changes in Tagz to do what I want with the
ns declarations and to fix the empty element handling.

Here's the examples:

cat /tmp/a.rb
require 'rubygems'
require 'tagz'

class Namespace
  def initialize hash, &block
    if hash.is_a? Hash
      @prefix, @uri = hash.inject([]) { |a, (k, v)| a << k << v }
    else
      @prefix = nil
      @uri = hash
    end
    @context = block
    @self = eval 'super()', block
  end

  instance_methods.each{|m| undef_method if m[%r/__/]}

  def emit_ns
    if !@prefix.nil?
      return { "xmlns:#{ @prefix }".to_sym => @uri }
    else
      return { :xmlns => @uri }
    end
  end

  def method_missing m, *a, &b
    if m.to_s[%r/^_|_$/] && !@prefix.nil?
      @self.send("#{ @prefix }:#{ m }", *a, &b)
    else
      if @prefix.nil?
        "#{ super }"
      else
        "#{ @prefix }:#{ m }"
      end
    end
  end

end

include Tagz.globally

xhtml = Namespace.new(:xhtml => "http://www.w3.org/1999/xhtml")
xf = Namespace.new(:xf => "http://www.w3.org/2002/xforms")
default = Namespace.new("http://www.w3.org/1999/xhtml")

puts xhtml.emit_ns.inspect
puts xf.emit_ns.inspect
puts default.emit_ns.inspect

xml =
  default.html_(default.emit_ns) {
    a_ "link", :href => "uri"
  }

puts "\nDefault namespace example"
puts xml
puts


# BUG!!
puts empty_element_


xml =
  xhtml.html_{
    xhtml.foo_(xhtml.bar => 'bar') { 'content' }
    xf.bar_(xf.foo => 'foo') { 'content' }
  }

puts
puts xml

nsdecls = xhtml.emit_ns.merge xf.emit_ns
puts nsdecls.inspect

a = Namespace.new(:a => "uri_a")
simple =
doc =
# want to do this:
# xhtml.html_(xhtml.emit_ns, xf.emit_ns) {
  xhtml.html_(nsdecls) {
    xhtml.head_{
       xhtml.title_ "Important Document"
       xf.model_{
         xf.instance_{
           person_{
             fname_
             lname_
           }
         }
       }
       xf.submission(:id => "form1", :method => "get", :action =>
"doit.jsp")
    }
    xhtml.body_{
      "..."
    }
  }

puts "\nXForms example"
puts doc



excalibur$ ruby /tmp/a.rb
{:"xmlns:xhtml"=>"http://www.w3.org/1999/xhtml"}
{:"xmlns:xf"=>"http://www.w3.org/2002/xforms"}
{:xmlns=>"http://www.w3.org/1999/xhtml"}

Default namespace example
<html xmlns="http://www.w3.org/1999/xhtml"><a href="uri">link</a></html>

<empty_element>

<xhtml:html><xhtml:foo xhtml:bar="bar">content</xhtml:foo><xf:bar
xf:foo="foo">content</xf:bar></xhtml:html>
{:"xmlns:xhtml"=>"http://www.w3.org/1999/xhtml",
:"xmlns:xf"=>"http://www.w3.org/2002/xforms"}

XForms example
<xhtml:html xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms"><xhtml:head><xhtml:...
Document</xhtml:title><xf:model><xf:instance><person><fname><lname></person></xf:instance></xf:model></xhtml:head><xhtml:body>...</xhtml:body></xhtml:html>
Ara H. (Guest)
on 2009-03-27 16:45
(Received via mailing list)
On Mar 27, 2009, at 5:16 AM, Andrew S. Townley wrote:

>
> I also discovered that output of empty elements doesn't behave as I'd
> expect.  If you do
>
> empty_element_
>
> you get "<empty_element>"
>
> rather than "<empty_element/>"

this by design.

it's a false assumption that one never needs to separate opening and
ending tags wrt to scopes

(from the samples)


     <========< samples/d.rb >========>

   ~ > cat samples/d.rb

     #
     # tagz.rb doesn't cramp your style, allowing even invalid html to
be
     # generated.  note the use of the 'tagz' method, which can be
used both to
     # capture output and to append content to the top of the stack.
     #

     require 'tagz'
     include Tagz.globally

     def header
       tagz{
         html_
           body_(:class => 'ninja-like', :id => 'giraffe-slayer')

           ___ "<!-- this is the header -->"

             div_(:class => 'content')
       }
     end

     def footer
       tagz{
         ___ "<!-- this is the footer -->"

             _div
           _body
         _html
       }
     end

     puts header, footer

   ~ > ruby samples/d.rb

     <html><body class="ninja-like" id="giraffe-slayer">
     <!-- this is the header -->
     <div class="content">

     <!-- this is the footer -->
     </div></body></html>






however, one can use a bang to indicate a tag should be close even if
it has not content

cfp:~/src/ruby/tagz/tagz-5.1.0 > ruby -r tagz -e 'puts
Tagz{ element_! }'
<element/>


alternatively you can pass an empty block, which is the style i prefer

cfp:~/src/ruby/tagz/tagz-5.1.0 > ruby -r tagz -e 'puts
Tagz{ element_{} }'
<element/>



i'll look into your namespace stuff.


cheers.




a @ http://codeforpeople.com/
Andrew S. Townley (Guest)
on 2009-03-27 16:57
(Received via mailing list)
On Fri, 2009-03-27 at 23:41 +0900, ara.t.howard wrote:
> > rather than "<empty_element/>"
>
> this by design.

Fair enough.

> it's a false assumption that one never needs to separate opening and
> ending tags wrt to scopes

It wasn't an assumption I was making.  The assumption I *was* making was
that the library was biased to ensuring you had well-formed & correct
mark-up.  To me, I'd see the need to separate scopes to be something I'd
want to explicitly request rather than the other way around.

Not a big deal now that I know about the bang operator.

Cheers,

ast
jonty (Guest)
on 2009-03-27 17:01
(Received via mailing list)
Have tried it out this morning - I am delighted with it - natural ruby
style, fast (see
http://blog.zenspider.com/2009/02/tagz-vs-markabyb... )

Is there a forum / user group or anything for it? I spotted one or two
issues I'd like to discuss somewhere
is this list the best place?

Getting it to work with Sinatra was interesting - I had to setup ruby
methods as views, because it is not yet incorporated
 as a templating engine by Sinatra, but that works fine. Any plans to
fit it into Sinatra like the other templating engines?

But many thanks Ara.
Ara H. (Guest)
on 2009-03-27 19:49
(Received via mailing list)
On Mar 27, 2009, at 8:53 AM, Andrew S. Townley wrote:

> It wasn't an assumption I was making.  The assumption I *was* making
> was
> that the library was biased to ensuring you had well-formed & correct
> mark-up.  To me, I'd see the need to separate scopes to be something
> I'd
> want to explicitly request rather than the other way around.

there is actually one other important usecase  br_  etc, and other
html4 tags.  just fyi.

a @ http://codeforpeople.com/
Andrew S. Townley (Guest)
on 2009-03-27 20:07
(Received via mailing list)
On Sat, 2009-03-28 at 02:42 +0900, ara.t.howard wrote:
> html4 tags.  just fyi.
Who uses HTML4 anymore???? ;)

..maybe an XML vs. HTML mode to switch them?

but I take your point.
Florian G. (Guest)
on 2009-03-27 20:16
(Received via mailing list)
On Mar 27, 2009, at 7:03 PM, Andrew S. Townley wrote:
>
> Who uses HTML4 anymore???? ;)


Actually, there are enough reasons for sticking with HTML. Especially
interesting is the point how most Browsers consume XHTML, to be found
in [1], section "HTML-compatible XHTML".

Regards,
Florian

[1]: http://webkit.org/blog/68/understanding-html-xml-and-xhtml/
--
Florian G.

smtp:   removed_email_address@domain.invalid
jabber: removed_email_address@domain.invalid
gpg:    533148E2
Andrew S. Townley (Guest)
on 2009-03-27 20:31
(Received via mailing list)
On Sat, 2009-03-28 at 03:12 +0900, Florian G. wrote:
> On Mar 27, 2009, at 7:03 PM, Andrew S. Townley wrote:
> >
> > Who uses HTML4 anymore???? ;)
>
>
> Actually, there are enough reasons for sticking with HTML. Especially
> interesting is the point how most Browsers consume XHTML, to be found
> in [1], section "HTML-compatible XHTML".

Hi Florian,

I hadn't seen this article, but I'm quite familiar with the differences.
Generating (X)HTML with Tagz will be handy, but it isn't my primary
interest.

I want a really slick tool/syntax for generating complex XML documents
using multiple namespaces and processing instructions.  I've been doing
this in various ways for several years, and nearly all of them suck --
equally and in different ways.

One of the things I used to sorta like was Jakarta's Element
Construction Set (ECS), but it was more  complicated than it needed to
be because of Java's syntax issues.  I've also tried custom templates,
various approaches to fragments, various templating languages, etc.,
etc....

Tagz is the first thing I've seen (accidentally, I might add) that
finally allowed me to write quasi-markup in code vs. the other way
around.  It's also quite timely, because I once again need to generate a
bunch of XML, but this time I'm using Ruby and it's looking like I'll be
adopting Tagz across the board for what I'm doing.

I'd already started doing embedded mark-up and was thinking about trying
to fold in one of the template engines.  Then I saw Ara's announcement
and thought "Hallelujah!  At last, a decent syntax for doing this!"

Hopefully, the namespace PI stuff will make it into an official release
at some stage.  I can live with the (from an XML perspective) backwards
view of element closure, because I understand where Ara (and probably
most of you) are coming from and what the main interest in a library
like this is.

As sick as it is, thanks to Tagz, I'm actually sorta excited about
writing code to generate XML instead of feeling the usual sense of
tedium, dread and pending frustration.

If I ever meet Ara, I'm buying him a pint! :)

Cheers,

ast
Florian G. (Guest)
on 2009-03-27 20:43
(Received via mailing list)
On Mar 27, 2009, at 7:27 PM, Andrew S. Townley wrote:

> Hi Florian,
>
> I hadn't seen this article, but I'm quite familiar with the
> differences.
> Generating (X)HTML with Tagz will be handy, but it isn't my primary
> interest.

All the better :). It's just that I see a lot of aggressive talk against
HTML from people that don't really know the striking differences
between both.

>
> I want a really slick tool/syntax for generating complex XML documents
> using multiple namespaces and processing instructions.  I've been
> doing
> this in various ways for several years, and nearly all of them suck --
> equally and in different ways.

That would be great. I haven't used many tools, but I know your problem.

> Tagz is the first thing I've seen (accidentally, I might add) that
> finally allowed me to write quasi-markup in code vs. the other way
> around.  It's also quite timely, because I once again need to
> generate a
> bunch of XML, but this time I'm using Ruby and it's looking like
> I'll be
> adopting Tagz across the board for what I'm doing.

Well, I already liked builder, but tagz has a fine way of circumventing
the problems that plague builder.

> If I ever meet Ara, I'm buying him a pint! :)

Somebody made someone happy ;).

Regards,
Florian

--
Florian G.

smtp:   removed_email_address@domain.invalid
jabber: removed_email_address@domain.invalid
gpg:    533148E2
Ara H. (Guest)
on 2009-03-27 22:20
(Received via mailing list)
On Mar 27, 2009, at 12:27 PM, Andrew S. Townley wrote:

> I want a really slick tool/syntax for generating complex XML documents
> using multiple namespaces and processing instructions.  I've been
> doing
> this in various ways for several years, and nearly all of them suck --
> equally and in different ways.

this may interest you - i wrote it before tagz

http://codeforpeople.com/lib/ruby/xx/xx-2.0.0/README

quite a while back

a @ http://codeforpeople.com/
Andrew S. Townley (Guest)
on 2009-03-27 22:29
(Received via mailing list)
On Sat, 2009-03-28 at 05:16 +0900, ara.t.howard wrote:
> http://codeforpeople.com/lib/ruby/xx/xx-2.0.0/README
>
> quite a while back

I can see the family resemblance! :)

Still, I think I'd prefer to go with Tagz + the Namespace and processing
instruction support I proposed (or something similar).

Is there a reason you think this might be more suitable?
Ara H. (Guest)
on 2009-03-27 23:17
(Received via mailing list)
On Mar 27, 2009, at 2:25 PM, Andrew S. Townley wrote:

> Is there a reason you think this might be more suitable?

it ensures valid xml and supports some xml-ish stuff.  otherwise i
just found it too constraining to use.

a @ http://codeforpeople.com/
This topic is locked and can not be replied to.