1
2
3
4
5
6
7
8
9
10
11
12
13 """HTML formated DocumentTemplates
14
15 $Id: DT_HTML.py 1007 2007-02-10 01:07:28Z stefan $"""
16
17 from DT_String import String, FileMixin
18 import DT_String, re
19 from DT_Util import ParseError, str
20
22 """ This needs to be replaced before 2.4. It's a hackaround. """
23 - def search(self, text, start=0,
24 name_match=re.compile('[\000- ]*[a-zA-Z]+[\000- ]*').match,
25 end_match=re.compile('[\000- ]*(/|end)', re.I).match,
26 start_search=re.compile('[<&]').search,
27 ent_name=re.compile('[-a-zA-Z0-9_.]+').match,
28 ):
29
30 while 1:
31 mo = start_search(text,start)
32 if mo is None: return None
33 s = mo.start(0)
34 if text[s:s+5] == '<!--#':
35 n=s+5
36 e=text.find('-->',n)
37 if e < 0: return None
38 en=3
39
40 mo =end_match(text,n)
41 if mo is not None:
42 l = mo.end(0) - mo.start(0)
43 end=text[n:n+l].strip()
44 n=n+l
45 else: end=''
46
47 elif text[s:s+6] == '<dtml-':
48 e=n=s+6
49 while 1:
50 e=text.find('>',e+1)
51 if e < 0: return None
52 if len(text[n:e].split('"'))%2:
53
54 break
55
56 en=1
57 end=''
58
59 elif text[s:s+7] == '</dtml-':
60 e=n=s+7
61 while 1:
62 e=text.find('>',e+1)
63 if e < 0: return None
64 if len(text[n:e].split('"'))%2:
65
66 break
67
68 en=1
69 end='/'
70
71 else:
72 if text[s:s+5] == '&dtml' and text[s+5] in '.-':
73 n=s+6
74 e=text.find(';',n)
75 if e >= 0:
76 args=text[n:e]
77 l=len(args)
78 mo = ent_name(args)
79 if mo is not None:
80 if mo.end(0)-mo.start(0) == l:
81 d=self.__dict__
82 if text[s+5]=='-':
83 d[1]=d['end']=''
84 d[2]=d['name']='var'
85 d[0]=text[s:e+1]
86 d[3]=d['args']=args+' html_quote'
87 self._start = s
88 return self
89 else:
90 nn=args.find('-')
91 if nn >= 0 and nn < l-1:
92 d[1]=d['end']=''
93 d[2]=d['name']='var'
94 d[0]=text[s:e+1]
95 args=args[nn+1:]+' '+ \
96 args[:nn].replace('.',' ')
97 d[3]=d['args']=args
98 self._start = s
99 return self
100
101 start=s+1
102 continue
103
104 break
105
106 mo = name_match(text,n)
107 if mo is None: return None
108 l = mo.end(0) - mo.start(0)
109
110 a=n+l
111 name=text[n:a].strip()
112
113 args=text[a:e].strip()
114
115 d=self.__dict__
116 d[0]=text[s:e+en]
117 d[1]=d['end']=end
118 d[2]=d['name']=name
119 d[3]=d['args']=args
120 self._start = s
121 return self
122
128
131
132 -class HTML(DT_String.String):
133 """HTML Document Templates
134
135 HTML Document templates use HTML server-side-include syntax,
136 rather than Python format-string syntax. Here's a simple example:
137
138 <!--#in results-->
139 <!--#var name-->
140 <!--#/in-->
141
142 HTML document templates quote HTML tags in source when the
143 template is converted to a string. This is handy when templates
144 are inserted into HTML editing forms.
145 """
146
147 tagre__roles__=()
150
151 parseTag__roles__=()
153 """Parse a tag using an already matched re
154
155 Return: tag, args, command, coname
156
157 where: tag is the tag,
158 args is the tag\'s argument string,
159 command is a corresponding command info structure if the
160 tag is a start tag, or None otherwise, and
161 coname is the name of a continue tag (e.g. else)
162 or None otherwise
163 """
164 tag, end, name, args = match_ob.group(0, 'end', 'name', 'args')
165 args=args.strip()
166 if end:
167 if not command or name != command.name:
168 raise ParseError, ('unexpected end tag', tag)
169 return tag, args, None, None
170
171 if command and name in command.blockContinuations:
172
173 if name=='else' and args:
174
175
176 l=len(args)
177 if not (args==sargs or
178 args==sargs[:l] and sargs[l:l+1] in ' \t\n'):
179 return tag, args, self.commands[name], None
180
181 return tag, args, None, name
182
183 try: return tag, args, self.commands[name], None
184 except KeyError:
185 raise ParseError, ('Unexpected tag', tag)
186
187 SubTemplate__roles__=()
189
190 varExtra__roles__=()
192
193 manage_edit__roles__=()
195 'edit a template'
196 self.munge(data)
197 if REQUEST: return self.editConfirmation(self,REQUEST)
198
199 quotedHTML__roles__=()
200 - def quotedHTML(self,
201 text=None,
202 character_entities=(
203 (('&'), '&'),
204 (("<"), '<' ),
205 ((">"), '>' ),
206 (('"'), '"'))):
207 if text is None: text=self.read_raw()
208 for re,name in character_entities:
209 if text.find(re) >= 0: text=name.join(text.split(re))
210 return text
211
212 errQuote__roles__=()
213 errQuote=quotedHTML
214
217
218
219 management_interface__roles__=()
221 '''Hook to allow public execution of management interface with
222 everything else private.'''
223 return self
224
225 manage_editForm__roles__=()
235
236 manage_editDocument__roles__=()
237 manage__roles__=()
238 manage_editDocument=manage=manage_editForm
239
241 '''\
242 HTML document templates that edit themselves through copy.
243
244 This is to make a distinction from HTML objects that should edit
245 themselves in place.
246 '''
247 copy_class__roles__=()
248 copy_class=HTML
249
250 manage_edit__roles__=()
252 'edit a template'
253 newHTML=self.copy_class(data,self.globals,self.__name__)
254 setattr(PARENTS[1],URL1[URL1.rfind('/')+1:],newHTML)
255 return self.editConfirmation(self,REQUEST)
256
257
259 """\
260 HTML Document templates read from files.
261
262 If the object is pickled, the file name, rather
263 than the file contents is pickled. When the object is
264 unpickled, then the file will be re-read to obtain the string.
265 Note that the file will not be read until the document
266 template is used the first time.
267 """
268 manage_default__roles__=()
270 'Revert to factory defaults'
271 if self.edited_source:
272 self.edited_source=''
273 self._v_cooked=self.cook()
274 if REQUEST: return self.editConfirmation(self,REQUEST)
275
276 manage_editForm__roles__=()
293 manage_editDocument__roles__=()
294 manage__roles__=()
295 manage_editDocument=manage=manage_editForm
296
297 manage_edit__roles__=()
298 - def manage_edit(self,data,
299 PARENTS=[],URL1='',URL2='',REQUEST='', SUBMIT=''):
300 'edit a template'
301 if SUBMIT==FactoryDefaultString: return self.manage_default(REQUEST)
302 if data.find('\r'):
303 data='\n\r'.join(data.split('\r\n'))
304 data='\n'.join(data.split('\n\r'))
305
306 if self.edited_source:
307 self.edited_source=data
308 self._v_cooked=self.cook()
309 else:
310 __traceback_info__=self.__class__
311 newHTML=self.__class__()
312 newHTML.__setstate__(self.__getstate__())
313 newHTML.edited_source=data
314 setattr(PARENTS[1],URL1[URL1.rfind('/')+1:],newHTML)
315 if REQUEST: return self.editConfirmation(self,REQUEST)
316