Html Tag Generation

K

Karsten Meier

Hello Ruby People

I'm working on a project which translates programming examples from the
perl cookbook to several other languages
(http://pleac.sourceforge.net/)
There is a problem for which I currently have only a ugly solution:
(Section "19.8 Formatting Lists and Tables with HTML Shortcuts")

To create the following html:
# <OL><LI>red</LI> <LI>blue</LI> <LI>green</LI></OL>

in perl you can write:
use CGI qw:)standard :html3)
print ol( li([ qw(red blue green)]) );

With the ruby cgi module, I need to write:
require 'cgi'
cgi = CGI.new('html4')
print cgi.ol{ %w(red blue green).collect{|color|
cgi.li{color}}
}

There ruby solution has two problems:
1) because the methods like CGI::li() take a block as parameter, we can not
use a list as content parameter:
cgi.li{%w(red blue green)} returns "<LI>redbluegreen</LI>" instead of
"<LI>red</LI> <LI>blue</LI> <LI>green</LI>"

2) we need to write cgi.li{..} instead of just li(..)

The result is that the scripts looks more confusing than the solution
with perls cgi module.
(In most other cases the ruby solutions looks better)

So my questions are:
Are there better ways to use the cgi module which I'm not aware of?
Or is there a better module to use for html generation, preferable in
the standard lib?


Regards

Karsten Meier
 
G

gabriele renzi

Karsten Meier ha scritto:

There ruby solution has two problems:
1) because the methods like CGI::li() take a block as parameter, we can not
use a list as content parameter:
cgi.li{%w(red blue green)} returns "<LI>redbluegreen</LI>" instead of
"<LI>red</LI> <LI>blue</LI> <LI>green</LI>"

2) we need to write cgi.li{..} instead of just li(..)
The result is that the scripts looks more confusing than the solution
with perls cgi module.
(In most other cases the ruby solutions looks better)

So my questions are:
Are there better ways to use the cgi module which I'm not aware of?
Or is there a better module to use for html generation, preferable in
the standard lib?


Regards

Karsten Meier



alternatively you could use:=> "<OL>foo</OL>"


which is even more confusing maybe..
B
ut makes me think:
maybe the element_init should be called on the various HTML mixins
#included and #extended methods ?
 
P

Phlip

Karsten said:
I'm working on a project which translates programming examples from the
perl cookbook to several other languages
(http://pleac.sourceforge.net/)

Then why you are not using Perl?

<a beat>

;-)
To create the following html:
# <OL><LI>red</LI> <LI>blue</LI> <LI>green</LI></OL>

in perl you can write:
use CGI qw:)standard :html3)
print ol( li([ qw(red blue green)]) );

Ruby/CGI might have a bigger problem. I could not find a way to make it
produce XHTML. A project should test its complex features, and XHTML tests
super-easy when XPath queries out target details. But Ruby/CGI writes tags
like <input>, not <input/>.

For MiniRubyWiki, I just rolled my own:

class XhtmlGenerator

def initialize(stream)
@stream = stream
end

def balance_(tag, attributes, pretty = "\n")
write(pretty)
write("<")
write(tag)
write(" " + attributes) if ! attributes.nil? and attributes != ''
write(">")
write(pretty)

begin
yield()
ensure
write(pretty)
write("</")
write(tag)
write(">")
write(pretty)
end
end

def small(attributes = '')
balance_('small', attributes, '') { yield() }
end

def em(attributes = '')
balance_('em', attributes, '') { yield() }
end

def table(attributes = '')
balance_('table', ' summary="cosmetic table"' + attributes) { yield() }
end

def form(attributes = '')
balance_('form', attributes) { yield() }
end

def th(attributes = nil)
balance_('th', attributes) { yield() }
end

def td(attributes = nil)
balance_('td', attributes, '') { yield() }
end

def tr(attributes = nil)
balance_('tr', attributes) { yield() }
end

def h1(attributes = nil)
balance_('h1', attributes, '') { yield() }
end

def body(attributes = nil)
balance_('body', attributes) { yield() }
end

def head(attributes = nil)
balance_('head', attributes) { yield() }
end

def title(attributes = nil)
balance_('title', attributes, '') { yield() }
end

def xhtml()
write('<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
')
attributes = 'xmlns="http://www.w3.org/1999/xhtml"'
balance_('html', attributes) { yield() }
end

def a_href(path, stuff = nil)
attributes = "href=\"#{path}\""
attributes += " " + stuff if stuff
balance_('a', attributes, '') { yield() }
end

def textarea(attributes)
balance_('textarea', attributes, '') { yield() }
end

def nbsp()
write('&nbsp;')
end

def space()
write(' ')
end

def endl()
write("\n")
end

def write(q)
@stream.write(q)
end

end

That provides this:

x = XhtmlGenerator.new()
....
x.xhtml() {
titleStuff()

style = "style=\"margin-left: 0.5cm; margin-right: 0.5cm;
margin-top: 0.2cm\""

x.body("bgcolor=\"#eeeeee\" text=\"black\" " + style) {
formatFileBody(x, searchTags) {
wikiFrame(x, contents)
}
}
}
There ruby solution has two problems:
1) because the methods like CGI::li() take a block as parameter, we can not
use a list as content parameter:
cgi.li{%w(red blue green)} returns "<LI>redbluegreen</LI>" instead of
"<LI>red</LI> <LI>blue</LI> <LI>green</LI>"

2) we need to write cgi.li{..} instead of just li(..)

myList.each{|n| x.li(n)}
The result is that the scripts looks more confusing than the solution
with perls cgi module.

Perl uses the design technique Yet Another Parser Hack to distinguish arrays
and scalars as parameters. You could enhance my def li() to detect array
arguments (using clean elegant reflection, not YAPH), and then iterate thru
the array.
 
J

James Britt

Phlip said:
Ruby/CGI might have a bigger problem. I could not find a way to make it
produce XHTML. A project should test its complex features, and XHTML tests
super-easy when XPath queries out target details. But Ruby/CGI writes tags
like <input>, not <input/>.

That's HTML for you.

For MiniRubyWiki, I just rolled my own:


Did you consider using Builder::XmlMarkup?

http://onestepback.org/index.cgi/Tech/Ruby/BuilderObjects.rdoc


James
--

http://www.ruby-doc.org
http://www.rubyxml.com
http://catapult.rubyforge.com
http://orbjson.rubyforge.com
http://ooo4r.rubyforge.com
http://www.jamesbritt.com
 
C

Chris Pine

I use a pretty low-tech trick myself, but it works pretty well. Just
a few methods and a couple of variables:

@page = []
@depth = 0

# Outputs string to page being generated.
def puts string
@page << ' '*@depth+string
end


# Plain old paragraph.
def para (attributes = {}, &block)
method_missing:)p, attributes, &block)
end


# Centered paragraph.
def parac (attributes = {}, &block)
attributes[:style] = 'text-align: center'
para(attributes, &block)
end


# Makes a generic tag; I never defined the "html" method,
# or "head" or "body" or "h1" or "br"... so they all use
# this code to build the appropriate tag. (I couldn't do
# this with the "p" tag, since "p" *is* defined as a method
# so I used "para" and "parac" above.
def method_missing (methodSymbol, attributes = {})
methodName = methodSymbol.to_s

attribString = ''
attributes.each do |key, val|
raise methodName+' '+attributes.inspect if (key.nil? || val.nil?)
attribString += ' '+key.to_s+'="'+val+'"'
end
if (!block_given?)
puts '<'+methodName+attribString+' />'
else
puts '<'+methodName+attribString+'>'
@depth += 1
blockReturn = yield
puts blockReturn if (blockReturn.kind_of?(String))
@depth -= 1
puts '</'+methodName+'>'
end
nil
end


This does a pretty good job of making readable html. To use it:

html do
head do
link:)rel=>'stylesheet', :type=>'text/css', :href=>'local.css')
title do
'pine.fm &mdash; ' + theTitle
end
end
body do
div:)id=>'headerBar') do
...

and so on. You can, of course, use {,} instead of do,end. It also
allows for <br /> style tags by calling the tag with a string instead
of a block.

Nothing too fancy, but it serves me well,

Chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,152
Latest member
LorettaGur
Top