Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
Macro(3)	      User Contributed Perl Documentation	      Macro(3)

NAME
       HTML::Macro - process HTML templates with loops,	conditionals, macros
       and more!

SYNOPSIS
	 use HTML::Macro;
	 $htm =	new HTML::Macro	('template.html');
	 $htm->print;

	 sub myfunc {
	   $htm->declare ('var', 'missing');
	   $htm->set ('var', 'value');
	   return $htm->process;
	 }

	 ( in template.html ):

	 <html><body>
	   <eval expr="&myfunc">
	     <if def="missing">
	       Message about missing stuff...
	     <else />
	       Var's value is #var#.
	     </if>
	   </eval>
	 </body></html>

DESCRIPTION
       HTML::Macro is a	module to be used behind a web server (in CGI
       scripts). It provides a convenient mechanism for	generating HTML	pages
       by combining "dynamic" data derived from	a database or other
       computation with	HTML templates that represent fixed or "static"
       content of a page.

       There are many different	ways to	accomplish what	HTML::Macro does,
       including ASP, embedded perl, CFML, etc,	etc. The motivation behind
       HTML::Macro is to keep everything that a	graphic	designer wants to play
       with *in	a single HTML template*, and to	keep as	much as	possible of
       what a perl programmer wants to play with *in a perl file*.  Our
       thinking	is that	there are two basically	dissimilar tasks involved in
       producing a dynamic web page: graphic design and	programming. Even if
       one person is responsible for both tasks, it is useful to separate them
       in order	to aid clear thinking and organized work.  I guess you could
       say the main motivation for this	separation is to make it easier	for
       emacs (and other	text processors, including humans) to parse your
       files: it's yucky to have a lot of HTML in a string in your perl	file,
       and it's	yucky to have perl embedded in a special tag in	an HTML	file.

       HTML::Macro began with some simple programming constructs: macro
       expansions, include files, conditionals,	loops and block	quotes.	 Since
       then we've added	very little: only a define tag to allow	setting	values
       and an eval tag to allow	perl function calls in a nested	macro scope.
       Our creed is "less is more, more	or less."

       HTML::Macro variables will look familiar	to C preprocessor users	or
       especially to Cold Fusion people.  They are always surrounded with
       single or double	hash marks: "#"	or "##".  Variables surrounded by
       double hash marks are subject to	html entity encoding; variables	with
       single hash marks are substituted "as is" (like single quotes in	perl
       or UNIX shells).	 Conditionals are denoted by the <if> and <else> tags,
       and loops by the	<loop> tag.  Quoting used to be	done using a <quote>
       tag, but	we now deprecate that in favor of the more familiar CFML
       quoting syntax: <!--- --->.

Basic Usage:
       Create a	new HTML::Macro:

	   $htm	= new HTML::Macro  ('templates/page_template.html', { 'collapse_whitespace' => 1 });

       The first (filename) argument is	optional.  If you do not specify it
       now, you	can do it later, which might be	useful if you want to use this
       HTML::Macro to operate on more than one template.  If you do specify
       the template when the object is created,	the file is read in to memory
       at that time.

       The second (attribute hash) argument is also optional, but you have to
       set it now if you want to set attributes.  See Attributes below for a
       list of attributes you can set.

       Optionally, declare the names of	all the	variables that will be
       substituted on this page.  This has the effect of defining the value ''
       for all these variables.

	 $htm->declare ('var', 'missing');

       Set the values of one or	more variables using HTML::Macro::set.

	 $htm->set ('var', 'value', 'var2', 'value2');

       Note: variable names beginning with an '@' are reserved for internal
       use.

       Get previously-set values using get:

	 $htm->get ('var');  # returns 'value'
	 $htm->get ('blah');  #	returns	undefined

       get also	returns	values from enclosing scopes (see Scope	below).

	 $htm->keys() returns a	list of	all defined macro names.

       Or use HTML::Macro::set_hash to set a whole bunch of values at once.
       Typically used with the value returned from a DBI::fetchrow_hashref.

	 $htm->set_hash	( {'var' => 'value', 'var2' => 'value2'	} );

       Finally,	process	the template and print the result using
       HTML::Macro::print, or save the value return by HTML::Macro::process.

	   open	CACHED_PAGE, '>page.html';
	   print CACHED_PAGE, $htm->process;
	   # or: print CACHED_PAGE, $htm->process ('templates/page_template.html');
	   close CACHED_PAGE;

	   - or	in some	contexts simply:

	   $htm->print;
	   or
	   $htm->print ('test.html');

	   However note	this would not be useful for printing a	cached page since
	   as a	convenience for	use in web applications	HTML::Macro::print prints
	   some	HTTP headers prior to printing the page	itself as returned by
	   HTML::Macro::process.

Macro Expansion
       HTML::Macro::process attempts to	perform	a substitution on any word
       beginning and ending with single	or double hashmarks (#)	, such as
       ##NAME##.  A word is any	sequence of alphanumerics and underscores.  If
       the HTML::Macro has a matching variable,	its value is substituted for
       the word	in the template	everywhere it appears.	A matching variable is
       determined based	on a case-folding match	with precedence	as follows:
       exact match, lower case match, upper case match.	 HTML::Macro macro
       names are case sensitive	in the sense that you may define distinct
       macros whose names differ only by case.	However, matching is case-
       insensitive and follows the above precedence rules.  So :

	   $htm->set ('Name', 'Mike', 'NAME', 'MIKE', 'name', 'mike');

       results in the following	substitutions:

	   Name	=> Mike
	   NAME	=> MIKE
	   name	=> mike
	   NAme	=> mike	(same for any other string differing from 'name' only by case).

       If no value is found for	a macro	name, no substitution is performed,
       and this	is not treated as an error.  This allows templates to be
       processed in more than one pass.	 Possibly it would be useful to	be
       able to request notification if any variables are not matched, or to
       request unmatched variables be mapped to	an empty string.  However the
       convenience seems to be outweighed by the benefit of consistency	since
       it easy to get confused if things like undefined	variables are handled
       differently at different	times.

       A typical usage is to stuff all the values returned from
       DBI::fetchrow_hashref into an HTML::Macro.  Then	SQL column names are
       to be mapped to template	variables.  Databases have different case
       conventions for column names; providing the case	insensitivity and
       stripping the underscores allows	templates to be	written	in a portable
       fashion while preserving	an upper-case convention for template
       variables.

   HTML	entity quoting
       Variables surrounded by double delimiters (##) are subject to HTML
       entity encoding.	 That is, >, <,	& and "" occuring in the variables
       value are replaced by their corresponding HTML entities.	 Variables
       surrounded by single delimiters are not quoted; they are	substituted
       "as is"

Conditionals
       Conditional tags	take one of the	following forms:

       <if expr="perl expression">
	HTML block 1 <else/>
	HTML block 2 </if>

       or

       <if expr="perl expression">
	HTML block 1 <else>
	HTML block 2 </else> </if>

       or simply

       <if expr="perl expression">
	HTML block 1 </if>

       Conditional tags	are processed by evaluating the	value of the "expr"
       attribute as a perl expression.	The entire conditional tag structure
       is replaced by the HTML in the first block if the expression is true,
       or the second block (or nothing if there	is no else clause) if the
       expressin is false.

       Conditional expressions are subject to variable substitution, allowing
       for constructs such as:

       You have	#NUM_ITEMS# item<if "#NUM_THINGS# > 1">s</if> in your basket.

   ifdef
       HTML::Macro also	provides the <if def="variable-name"> conditional.
       This construct evaluates	to true	if variable-name is defined and	has a
       true value.  It might have been better to name this something different
       like <if	set="variable">	? Sometimes there is a need for	if (defined
       (variable)) in the perl sense.  Also we occasionally want <if
       ndef="var"> but just use	<if def="var"><else/> instead which seems
       adequate	if a little clumsy.

File Interpolation
       It is often helpful to structure	HTML by	separating commonly-used
       chunks (headers,	footers, etc) into separate files.  HTML::Macro
       provides	the <include />	tag for	this purpose.  Markup such as <include
       file="file.html"	/> gets	replaced by the	contents of file.html, which
       is itself subject to evaluation by HTML::Macro.	If the "asis"
       attribute is present: <include/ file="quoteme.html" asis>, the file is
       included	"as is"; without any further evaluation.

       HTML::Macro also	supports an include path.  This	allows common "part"
       files to	be placed in a single central directory.
       HTML::Macro::push_incpath adds to the path, as in $htm->push_incpath
       ("/path/to/include/files").  The	current	directory (of the file being
       processed) is always checked first, followed by each directory on the
       incpath.	 When paths are	added to the incpath they are always converted
       to absolute paths, relative to the working directory of the invoking
       script.	Thus, if your script is	running	in "/cgi-bin" and calls
       push_incpath("include"),	this adds "/cgi-bin/include" to	the incpath.
       (Note that HTML::Macro never calls chdir	as part	of an effort to	be
       thread-safe).

       Also note that during the processing of an included file, the folder in
       which the included file resides is pushed on to the incpath.  This
       means that relative includes work as you	would expect in	included
       files; a	file found in a	directory relative to the included file	takes
       precedence over one found in a directory	relative to the	including file
       (or HTML::Macros	global incpath).

Loops
	   The <loop> tag and the corresponding	HTML::Macro::Loop object provide
       for repeated blocks of HTML, with subsequent iterations evaluated in
       different contexts.  Typically you will want to select rows from	a database
       (lines from a file, files from a	directory, etc), and present each
       iteration in succession using identical markup.	You do this by creating	a
       <loop> tag in your template file	containing the markup to be repeated, and
       by creating a correspondingly named Loop	object attached	to the HTML::Macro
       and containing all the data to be interpolated.	Note: this requires all
       data to be fetched and stored before it is applied to the template; there
       is no facility for streaming data.  For the intended use	this is	not a
       problem.	 However it militates against using HTML::Macro	for text
       processing of very large	datasets.

	 <loop id="people">
	   <tr><td>#first_name#	#last_name#</td><td>#email#</td></tr>
	 </loop>

	   The loop tag	allows the single attribute "id" which can be any
	   identifier.	Loop tags may be nested.  If during processing no matching
	   loop	object is found, a warning is produced and the tag is simply
	   ignored.

	 $htm =	new HTML::Macro;
	 $loop = $htm->new_loop('people', 'id',	'first_name', 'last_name', 'email');
	 $loop->push_array (1, 'frank',	'jones', 'frank@hotmail.com');

	 Create	a loop object using HTML::Macro::new_loop (or
	 HTML::Macro::Loop::new_loop for a nested loop).  The first argument is
	 the id	of the loop and	must match the id attribute of a tag in	the
	 template (the match is	case sensitive).  The remaining	arguments are the
	 names of loop variables.

	 Append	loop iterations	(rows) by calling push_array with an array of
	 values	corresponding to the loop variables declared when the loop was
	 created.

	 An alternative	is to use push_hash, which is analogous	to
       HTML::Macro::set_hash; it sets up multiple variable substitutions.  If you
       use push_hash you don't have to declare the names of the	variables when you
       create the loop object.	This allows them to be taken out of a hash and
       bound late, for example by names	returned in a database query.

	 pushall_arrays	is a shortcut that allows a number of loop iterations to
       be pushed at once.  It is typically used	in conjunction with
       DBI::selectall_arrayref.

	 is_empty returns a true value iff the loop has	at least one row.

	 keys returns a	list of	variable names defined in the (last row	of the)
	 loop.

Eval
	 <eval expr="perl expression"> ... </eval>

	 You can evaluate arbitrary perl expressions (as long as you can place
	 them in an XML	attribute between double quotes!).  The	expression is
	 subject to macro substition, placed in	a block	and invoked as an
	 anonymous function whose single argument is an	HTML::Macro object
	 representing the nested scope.	 Any values set	in the perl expression
	 thus affect the markup	inside the eval	tag.  The perl is evaluated after
	 setting the package to	the HTML::Macro	caller's package.

	 Note: typically we only use this to make a function call, and it would
	 probably be more efficient to optimize	for that case -	look for the
	 special case <eval function=""> to be implemented soon.  Also we might
	 like to provide a singleton eval that would operate in	the current scope:
	 <eval function="perl_function"	/>.

Scope
       Each of the tags	include, eval and loop introduce a nested "local"
       lexical scope.  Within a	nested scope, a	macro definition overrides any
       same-named macro	in the enclosing scope and the value of	the macro
       outside the nested scope	is unaffected.	This is	generally the expected
       behavior	and makes it possible to write modular code.

       Sometimes desirable to set values at a global scope when	operating in a
       nested scope.  You do this using	set_global.  set_global	is totally
       analogous to set, but sets values in the	outermost scope, whatever the
       current scope.

       Another related function	is set_ovalue.	Set_ovalue sets	values in a
       parallel	scope that takes precedence over the default scope (think
       "overridding" value).  We use set_ovalue	to place request variables in
       a privileged scope so that their	values override	values fetched from
       the datbase.  Each nested lexical scope really contains two name	spaces
       - values	and ovalues, with ovalues taking precedence.  However, an
       inner scope always takes	precedence over	an outer scope.

       element Variable	substitution within a loop follows the rule that loop
       keys take precedence over "global" variables set	by the enclosing page
       (or any outer loop(s)).

Define
       You can set the value of	a variable using the <define />	tag which
       requires	two attributes:	name and value.	 This is only occasionally
       useful since mostly we set variable values in perl.  An example might
       be setting a value that is constant in an outer context but variable in
       an inner	context, such as a navigation state:

       <define name="nav_state"	value="about" /> <include file="nav.html" />

       We might	want a more convenient syntax for this such as

       <define variable="value"	/>

       but this	seems somehow contravening the XML ideal since it would	allow
       arbitrary attributes; we	could never write any sort of DTD or schema.
       And this	whole feature is so little used	that it	doesn't	seem worth it.

Quoting
       For inserting block quotes in your markup that will be completely
       removed during macro processing,	use <!--- --->.

       Also note that all macro	and tag	processing can be inhibited by the use
       of the "<quote>"	tag.  Any markup enclosed by <quote> ... </quote> is
       passed on as-is.	 However please	don't rely on this as it is not	all
       that useful and may go away.  The only real use for this	was to support
       a pre-processing	phase that could generate templates.  A	new feature
       supports	this better: any of the	HTML::Macro tags may be	written	with a
       trailing	underscore, as in <if_ expr="..."> ... </if_>.	Tags such as
       this are	processed only if the preference variable '@precompile'	is
       set, in which case unadorned tags are ignored.

Attributes
       These are user-controllable attributes that affect the operation	of
       HTML::Macro in one way or another.

       debug

       Set to a	true value, produces various diagnostic	information on STDERR.
       Default is false.

       precompile

       If set, (only) tags with	trailing underscores will be processed.
       Default is false.

       collapse_whitespace, collapse_blanklines

	If you set '@collapse_whitespace' the processor	will collapse all
	 adjacent whitespace (including	line terminators) to a single space.  An
	 exception is made for markup appearing	within <textarea>, <pre> and
	 <quote> tags.	Similarly, setting '@collapse_blank_lines' (and	not
	 '@collapse_whitespace', which takes precedence), will cause adjacent line
	 terminators to	be collapsed to	a single newline character.  We	use the
	 former	for a final pass in order to produce efficient HTML, the latter
	 for the preprocessor, to improve the readability of generated HTML with a
	 lot of	blank lines in it.  Default for	both is	false.

       cache_files

       If set, files are read into and retrieved from an in-memory cache to
       improve performance for long-lived applications such as mod_perl	and
       for situations in which the same	file is	read repeatedly	during the
       processing of a single template.	 This definitely helped	in a scenario
       involving an include in side a loop, but	it's not immediately clear why
       given that the operating	system is probably caching recently-read files
       in memory anyway.  The cache checks file	modification times and reloads
       when a file changes.  There is currently	no limit to file cache size,
       which should definitely get changed.

Idiosyncracies
       For hysterical reasons HTML::Macro allows a certain kind	of non-XML;
       singleton tags are allowed to be	written	with the trailing slash
       immediately following the tag and separated from	the closing > by white
       space.  EG:

	   <include/ file="foo"> is OK

       whereas XML calls for

	   <include file="foo" /> (which is also allowed here).

       HTML::Macro is copyright	(c) 2000-2004 by Michael Sokolov and
       Interactive Factory (sm).  Some rights may be reserved.	This program
       is free software; you can redistribute it and/or	modify it under	the
       same terms as Perl itself.

AUTHOR
       Michael Sokolov,	sokolov@ifactory.com

SEE ALSO HTML::Macro::Loop
       perl(1).

perl v5.32.1			  2010-05-30			      Macro(3)

NAME | SYNOPSIS | DESCRIPTION | Basic Usage: | Macro Expansion | Conditionals | File Interpolation | Loops | Eval | Scope | Define | Quoting | Attributes | Idiosyncracies | AUTHOR | SEE ALSO HTML::Macro::Loop

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=HTML::Macro&sektion=3&manpath=FreeBSD+13.0-RELEASE+and+Ports>

home | help