##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""HTML formated DocumentTemplates
$Id: dt_html.py 38178 2005-08-30 21:50:19Z mj $
"""
import re
from zope.documenttemplate.dt_string import String
from zope.documenttemplate.dt_util import ParseError
class DTMLRegExClass:
def search(self, text, start=0,
name_match=re.compile('[\0- ]*[a-zA-Z]+[\0- ]*').match,
start_search=re.compile('[<&]').search,
ent_name=re.compile('[-a-zA-Z0-9_.]+').match
):
while True:
mo = start_search(text, start)
if mo is None:
return None
s = mo.start(0)
if text[s:s+6] == '', e+1)
if e < 0:
return None
if len(text[n:e].split('"'))%2:
# check for even number of "s inside
break
en = 1
end = ''
elif text[s:s+7] == '',e+1)
if e < 0:
return None
if len(text[n:e].split('"'))%2:
# check for even number of "s inside
break
en=1
end='/'
else:
if text[s:s+5] == '&dtml' and text[s+5] in '.-':
n=s+6
e=text.find(';', n)
if e >= 0:
args=text[n:e]
l=len(args)
mo = ent_name(args)
if mo is not None and mo.end(0)-mo.start(0) == l:
d=self.__dict__
if text[s+5] == '-':
d[1] = d['end'] = ''
d[2] = d['name'] = 'var'
d[0] = text[s:e+1]
d[3] = d['args'] = args + ' html_quote'
self._start = s
return self
else:
nn=args.find('-')
if nn >= 0 and nn < l-1:
d[1]=d['end']=''
d[2]=d['name']='var'
d[0]=text[s:e+1]
args=(args[nn+1:]+' '+
args[:nn].replace('.', ' '))
d[3]=d['args']=args
self._start = s
return self
start = s + 1
continue
break
mo=name_match(text,n)
if mo is None:
return None
l = mo.end(0) - mo.start(0)
a=n+l
name=text[n:a].strip()
args=text[a:e].strip()
d=self.__dict__
d[0]=text[s:e+en]
d[1]=d['end']=end
d[2]=d['name']=name
d[3]=d['args']=args
self._start = s
return self
def group(self, *args):
get=self.__dict__.get
if len(args)==1:
return get(args[0])
return tuple(map(get, args))
def start(self, *args):
return self._start
class HTML(String):
"""HTML Document Templates
HTML Document templates use HTML server-side-include syntax,
rather than Python format-string syntax. Here's a simple example:
HTML document templates quote HTML tags in source when the
template is converted to a string. This is handy when templates
are inserted into HTML editing forms.
"""
def tagre(self):
return DTMLRegExClass()
def parseTag(self, tagre, command=None, sargs=''):
"""Parse a tag using an already matched re
Return: tag, args, command, coname
where: tag is the tag,
args is the tag\'s argument string,
command is a corresponding command info structure if the
tag is a start tag, or None otherwise, and
coname is the name of a continue tag (e.g. else)
or None otherwise
"""
tag, end, name, args, =tagre.group(0, 'end', 'name', 'args')
args=args.strip()
if end:
if not command or name != command.name:
raise ParseError('unexpected end tag', tag)
return tag, args, None, None
if command and name in command.blockContinuations:
if name=='else' and args:
# Waaaaaah! Have to special case else because of
# old else start tag usage. Waaaaaaah!
l=len(args)
if not (args==sargs or
args==sargs[:l] and sargs[l:l+1] in ' \t\n'):
return tag, args, self.commands[name], None
return tag, args, None, name
try: return tag, args, self.commands[name], None
except KeyError:
raise ParseError('Unexpected tag', tag)
def SubTemplate(self, name):
return HTML('', __name__=name)
def varExtra(self,tagre):
return 's'
def quotedHTML(self,
text=None,
character_entities=(
(('&'), '&'),
(("<"), '<' ),
((">"), '>' ),
(('"'), '"'))): #"
if text is None:
text=self.read_raw()
for re, name in character_entities:
if text.find(re) >= 0:
text = name.join(text.split(re))
return text
errQuote = quotedHTML
def __str__(self):
return self.quotedHTML()