Details

Applies to
moin-1.6
Purpose

have moin output valid XHTML 1.0 output, as described in FeatureRequests/ValidXHTMLOutput

Description
Summary of changes:
  1. the following elements with EMPTY content model, while properly generated starting from user markup, where generated without the closing tag in some place in the code. They are now correctly generated as empty XML elements (e.g. <foo />).

    • hr
    • img
    • input
    • link
    • meta
    • param
  2. the 'disabled' attribute must have a value when outputting xml. Now it is properly generated as 'disabled="disabled"' as required by the XHTML specifications.
  3. escaped '&' characters in verbatim javascript snippets and hyperlink endpoints

  4. do not rely on browsers for automatically closing <p> tags generated from wiki markup

  5. change DOCTYPE string on sent document to be XHTML 1.0, changed bottom page link label claiming the page is valid XHTML 1.0

Note: applying this patch will not make Moin output always valid XHTML 1.0, but it will fix a lot of common issues. I (StefanoZacchiroli) am working on testing the whole legacy Moin installation so that all pages in the distribution are output as valid XHTML 1.0, but I'm not there yet. I will keep this patch updated. Help is more than welcome.

Patch

   1 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/action/AttachFile.py moin-dev/MoinMoin/action/AttachFile.py
   2 --- moin-dev.orig/MoinMoin/action/AttachFile.py	2006-06-21 10:25:45.000000000 +0200
   3 +++ moin-dev/MoinMoin/action/AttachFile.py	2006-06-16 16:02:42.000000000 +0200
   4 @@ -371,7 +371,7 @@
   5                  scriptName, pagename_quoted,
   6                  action_name, wikiutil.url_quote_plus(file))
   7  
   8 -            request.write(u'<link rel="Appendix" title="%s" href="%s">\n' % (
   9 +            request.write(u'<link rel="Appendix" title="%s" href="%s" />\n' % (
  10                  wikiutil.escape(file), wikiutil.escape(url)))
  11  
  12  
  13 @@ -402,15 +402,15 @@
  14      request.write('<h2>' + _("Edit drawing") + '</h2>')
  15      request.write("""
  16  <p>
  17 -<img src="%(pngpath)s%(timestamp)s">
  18 +<img src="%(pngpath)s%(timestamp)s" />
  19  <applet code="CH.ifa.draw.twiki.TWikiDraw.class"
  20 -        archive="%(pubpath)s/twikidraw.jar" width="640" height="480">
  21 -<param name="drawpath" value="%(drawpath)s">
  22 -<param name="pngpath"  value="%(pngpath)s">
  23 -<param name="savepath" value="%(savelink)s">
  24 -<param name="basename" value="%(basename)s">
  25 -<param name="viewpath" value="%(pagelink)s">
  26 -<param name="helppath" value="%(helplink)s">
  27 +        archive="%(pubpath)s/twikidraw.jar" width="640" height="480" />
  28 +<param name="drawpath" value="%(drawpath)s" />
  29 +<param name="pngpath"  value="%(pngpath)s" />
  30 +<param name="savepath" value="%(savelink)s" />
  31 +<param name="basename" value="%(basename)s" />
  32 +<param name="viewpath" value="%(pagelink)s" />
  33 +<param name="helppath" value="%(helplink)s" />
  34  <strong>NOTE:</strong> You need a Java enabled browser to edit the drawing example.
  35  </applet>
  36  </p>""" % {
  37 @@ -450,14 +450,14 @@
  38  <form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
  39  <dl>
  40  <dt>%(upload_label_file)s</dt>
  41 -<dd><input type="file" name="file" size="50"></dd>
  42 +<dd><input type="file" name="file" size="50" /></dd>
  43  <dt>%(upload_label_rename)s</dt>
  44 -<dd><input type="text" name="rename" size="50" value="%(rename)s"></dd>
  45 +<dd><input type="text" name="rename" size="50" value="%(rename)s" /></dd>
  46  </dl>
  47  <p>
  48 -<input type="hidden" name="action" value="%(action_name)s">
  49 -<input type="hidden" name="do" value="upload">
  50 -<input type="submit" value="%(upload_button)s">
  51 +<input type="hidden" name="action" value="%(action_name)s" />
  52 +<input type="hidden" name="do" value="upload" />
  53 +<input type="submit" value="%(upload_button)s" />
  54  </p>
  55  </form>
  56  """ % {
  57 @@ -471,7 +471,7 @@
  58  })
  59  
  60  #<dt>%(upload_label_mime)s</dt>
  61 -#<dd><input type="text" name="mime" size="50"></dd>
  62 +#<dd><input type="text" name="mime" size="50" /></dd>
  63  #    'upload_label_mime': _('MIME Type (optional)'),
  64  
  65  
  66 @@ -780,7 +780,7 @@
  67      mt = wikiutil.MimeType(filename=filename)
  68      if mt.major == 'image':
  69          timestamp = htdocs_access(request) and "?%s" % time.time() or ''
  70 -        request.write('<img src="%s%s" alt="%s">' % (
  71 +        request.write('<img src="%s%s" alt="%s" />' % (
  72              getAttachUrl(pagename, filename, request, escaped=1), timestamp, wikiutil.escape(filename, 1)))
  73          return
  74      elif mt.major == 'text':
  75 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/action/backup.py moin-dev/MoinMoin/action/backup.py
  76 --- moin-dev.orig/MoinMoin/action/backup.py	2006-06-21 10:25:45.000000000 +0200
  77 +++ moin-dev/MoinMoin/action/backup.py	2006-06-16 16:02:42.000000000 +0200
  78 @@ -92,15 +92,15 @@
  79  
  80      request.write("""
  81  <form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
  82 -<input type="hidden" name="action" value="backup">
  83 -<input type="hidden" name="do" value="backup">
  84 -<input type="submit" value="%(backup_button)s">
  85 +<input type="hidden" name="action" value="backup" />
  86 +<input type="hidden" name="do" value="backup" />
  87 +<input type="submit" value="%(backup_button)s" />
  88  </form>
  89  
  90  <form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
  91 -<input type="hidden" name="action" value="backup">
  92 -<input type="hidden" name="do" value="restore">
  93 -<input type="submit" value="%(restore_button)s">
  94 +<input type="hidden" name="action" value="backup" />
  95 +<input type="hidden" name="do" value="restore" />
  96 +<input type="submit" value="%(restore_button)s" />
  97  </form>
  98  """ % {
  99      'baseurl': request.getScriptname(),
 100 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/action/DeletePage.py moin-dev/MoinMoin/action/DeletePage.py
 101 --- moin-dev.orig/MoinMoin/action/DeletePage.py	2006-06-21 10:25:45.000000000 +0200
 102 +++ moin-dev/MoinMoin/action/DeletePage.py	2006-06-16 16:02:42.000000000 +0200
 103 @@ -61,7 +61,7 @@
 104      <tr>
 105          <td class="label"><label>%(comment_label)s</label></td>
 106          <td class="content">
 107 -            <input type="text" name="comment" maxlength="80">
 108 +            <input type="text" name="comment" maxlength="80" />
 109          </td>
 110      </tr>
 111      <tr>
 112 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/action/Despam.py moin-dev/MoinMoin/action/Despam.py
 113 --- moin-dev.orig/MoinMoin/action/Despam.py	2006-06-21 10:25:45.000000000 +0200
 114 +++ moin-dev/MoinMoin/action/Despam.py	2006-06-16 16:02:42.000000000 +0200
 115 @@ -84,9 +84,9 @@
 116  </table>
 117  <p>
 118  <form method="post" action="%s/%s">
 119 -<input type="hidden" name="action" value="Despam">
 120 -<input type="hidden" name="editor" value="%s">
 121 -<input type="submit" name="ok" value="%s">
 122 +<input type="hidden" name="action" value="Despam" />
 123 +<input type="hidden" name="editor" value="%s" />
 124 +<input type="submit" name="ok" value="%s" />
 125  </form>
 126  </p>
 127  ''' % (request.getScriptname(), wikiutil.quoteWikinameURL(pagename),
 128 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/action/fckdialog.py moin-dev/MoinMoin/action/fckdialog.py
 129 --- moin-dev.orig/MoinMoin/action/fckdialog.py	2006-06-21 10:25:45.000000000 +0200
 130 +++ moin-dev/MoinMoin/action/fckdialog.py	2006-06-16 16:12:57.000000000 +0200
 131 @@ -21,8 +21,8 @@
 132  <html>
 133   <head>
 134    <title>Insert Macro</title>
 135 -  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 136 -  <meta content="noindex,nofollow" name="robots">
 137 +  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 138 +  <meta content="noindex,nofollow" name="robots" />
 139    <script src="%s/applets/FCKeditor/editor/dialog/common/fck_dialog_common.js" type="text/javascript"></script>  
 140    <script language="javascript">
 141  
 142 @@ -178,8 +178,8 @@
 143  <html>
 144   <head>
 145    <title>Insert Page Link</title>
 146 -  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 147 -  <meta content="noindex,nofollow" name="robots">
 148 +  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 149 +  <meta content="noindex,nofollow" name="robots" />
 150   </head>
 151   <body scroll="no" style="OVERFLOW: hidden">
 152    <table height="100%%" cellSpacing="0" cellPadding="0" width="100%%" border="0">
 153 @@ -273,8 +273,8 @@
 154   *   Frederico Caldeira Knabben (fredck@fckeditor.net)
 155  -->
 156  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
 157 -<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
 158 -<meta name="robots" content="index,nofollow">
 159 +<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
 160 +<meta name="robots" content="index,nofollow" />
 161  <html>
 162   <head>
 163    <title>Link Properties</title>
 164 @@ -299,17 +299,17 @@
 165       <tr>
 166        <td>
 167         <form action=%(action)s method="GET">
 168 -       <input type="hidden" name="action" value="fckdialog">
 169 -       <input type="hidden" name="dialog" value="link">
 170 -       <input type="hidden" id="basepage" name="basepage" value="%(basepage)s">
 171 +       <input type="hidden" name="action" value="fckdialog" />
 172 +       <input type="hidden" name="dialog" value="link" />
 173 +       <input type="hidden" id="basepage" name="basepage" value="%(basepage)s" />
 174         <table cellSpacing="0" cellPadding="0" align="center" border="0">
 175          <tr>
 176           <td>
 177            <span fckLang="PageDlgName">Page Name</span><br>
 178 -          <input id="txtPagename" name="pagename" size="30" value="%(name)s">
 179 +          <input id="txtPagename" name="pagename" size="30" value="%(name)s" />
 180           </td>
 181           <td valign="bottom">
 182 -           <input id=btnSearchpage type="submit" value="Search">
 183 +           <input id=btnSearchpage type="submit" value="Search" />
 184           </td>
 185          </tr>
 186          %(page_list)s
 187 @@ -330,7 +330,7 @@
 188            <select id="sctInterwiki" size="1">
 189            %(interwiki)s
 190            </select>:
 191 -          <input id="txtInterwikipagename"></input>
 192 +          <input id="txtInterwikipagename" />
 193           </td>
 194          </tr>
 195         </table>
 196 @@ -426,8 +426,8 @@
 197   *   Frederico Caldeira Knabben (fredck@fckeditor.net)
 198  -->
 199  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
 200 -<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
 201 -<meta name="robots" content="index,nofollow">
 202 +<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
 203 +<meta name="robots" content="index,nofollow" />
 204  <html>
 205   <head>
 206    <title>Attachment Properties</title>
 207 @@ -444,13 +444,13 @@
 208       <tr>
 209        <td>
 210         <form action=%(action)s method="GET">
 211 -       <input type="hidden" name="action" value="fckdialog">
 212 -       <input type="hidden" name="dialog" value="attachment">
 213 +       <input type="hidden" name="action" value="fckdialog" />
 214 +       <input type="hidden" name="dialog" value="attachment" />
 215         <table cellSpacing="0" cellPadding="0" align="center" border="0">
 216          <tr>
 217           <td>
 218            <span fckLang="AttachmentDlgName">Attachment Name</span><br>
 219 -          <input id="txtAttachmentname" name="pagename" size="30" value="%(name)s">
 220 +          <input id="txtAttachmentname" name="pagename" size="30" value="%(name)s" />
 221           </td>
 222          </tr>
 223         </table>
 224 @@ -518,7 +518,7 @@
 225       <tr>
 226        <td colspan=2>
 227         <div id="divChkLink">
 228 -        <input id="chkLink" type="checkbox"> Link to
 229 +        <input id="chkLink" type="checkbox" /> Link to
 230         </div>
 231        </td>
 232      </table>
 233 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/action/__init__.py moin-dev/MoinMoin/action/__init__.py
 234 --- moin-dev.orig/MoinMoin/action/__init__.py	2006-06-21 10:25:45.000000000 +0200
 235 +++ moin-dev/MoinMoin/action/__init__.py	2006-06-16 16:02:42.000000000 +0200
 236 @@ -115,11 +115,11 @@
 237          buttons = self.make_buttons()
 238          buttons_html = []
 239          for button in buttons:
 240 -            buttons_html.append('<input type="submit" name="%s" value="%s">' % button)
 241 +            buttons_html.append('<input type="submit" name="%s" value="%s" />' % button)
 242          buttons_html = "".join(buttons_html)
 243          
 244          if self.use_ticket:
 245 -            ticket_html = '<input type="hidden" name="ticket" value="%s">' % wikiutil.createTicket()
 246 +            ticket_html = '<input type="hidden" name="ticket" value="%s" />' % wikiutil.createTicket()
 247          else:
 248              ticket_html = ''
 249              
 250 @@ -134,7 +134,7 @@
 251          form_html = '''
 252  %(error_html)s
 253  <form method="post" action="">
 254 -<input type="hidden" name="action" value="%(actionname)s">
 255 +<input type="hidden" name="action" value="%(actionname)s" />
 256  %(ticket_html)s
 257  %(user_html)s
 258  </form>''' % d
 259 @@ -599,7 +599,7 @@
 260              request.write('<pre>')
 261              for line in lines:
 262                  if line[0] == "@":
 263 -                    request.write('<hr>')
 264 +                    request.write('<hr />')
 265                  request.write(wikiutil.escape(line)+'\n')
 266              request.write('</pre>')
 267  
 268 @@ -669,7 +669,7 @@
 269              Column('rev', label='#', align='right'),
 270              Column('mtime', label=_('Date'), align='right'),
 271              Column('size',  label=_('Size'), align='right'),
 272 -            Column('diff', label='<input type="submit" value="%s">' % (_("Diff"))),
 273 +            Column('diff', label='<input type="submit" value="%s" />' % (_("Diff"))),
 274              Column('editor', label=_('Editor'), hidden=not request.cfg.show_names),
 275              Column('comment', label=_('Comment')),
 276              Column('action', label=_('Action')),
 277 @@ -721,7 +721,7 @@
 278                      rchecked = ''
 279                  else:
 280                      lchecked = rchecked = ''
 281 -                diff = '<input type="radio" name="rev1" value="%d"%s><input type="radio" name="rev2" value="%d"%s>' % (rev,lchecked,rev,rchecked)
 282 +                diff = '<input type="radio" name="rev1" value="%d"%s /><input type="radio" name="rev2" value="%d"%s />' % (rev,lchecked,rev,rchecked)
 283                  comment = line.comment
 284                  if not comment and line.action.find('/REVERT') != -1:
 285                          comment = _("Revert to revision %(rev)d.") % {'rev': int(line.extra)}
 286 @@ -785,7 +785,7 @@
 287          # into the page view itself, and not in this form.
 288          request.write('<form method="GET" action="">\n')
 289          request.write('<div id="page-history">\n')
 290 -        request.write('<input type="hidden" name="action" value="diff">\n')
 291 +        request.write('<input type="hidden" name="action" value="diff" />\n')
 292  
 293          history_table = DataBrowserWidget(request)
 294          history_table.setData(history)
 295 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/action/PackagePages.py moin-dev/MoinMoin/action/PackagePages.py
 296 --- moin-dev.orig/MoinMoin/action/PackagePages.py	2006-06-21 10:25:45.000000000 +0200
 297 +++ moin-dev/MoinMoin/action/PackagePages.py	2006-06-16 16:02:42.000000000 +0200
 298 @@ -141,25 +141,25 @@
 299          form = '''
 300  %(error)s
 301  <form method="post" action="">
 302 -<input type="hidden" name="action" value="%(action)s">
 303 +<input type="hidden" name="action" value="%(action)s" />
 304  <table>
 305      <tr>
 306          <td class="label"><label>%(newname_label)s</label></td>
 307          <td class="content">
 308 -            <input type="text" name="packagename" value="package.zip">
 309 +            <input type="text" name="packagename" value="package.zip" />
 310          </td>
 311      </tr>
 312      <tr>
 313          <td class="label"><label>%(list_label)s</label></td>
 314          <td class="content">
 315 -            <input type="text" name="pagelist" maxlength="80">
 316 +            <input type="text" name="pagelist" maxlength="80" />
 317          </td>
 318      </tr>
 319      <tr>
 320          <td></td>
 321          <td class="buttons">
 322 -            <input type="submit" name="submit" value="%(package)s">
 323 -            <input type="submit" name="cancel" value="%(cancel)s">
 324 +            <input type="submit" name="submit" value="%(package)s" />
 325 +            <input type="submit" name="cancel" value="%(cancel)s" />
 326          </td>
 327      </tr>
 328  </table>
 329 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/action/RenamePage.py moin-dev/MoinMoin/action/RenamePage.py
 330 --- moin-dev.orig/MoinMoin/action/RenamePage.py	2006-06-21 10:25:45.000000000 +0200
 331 +++ moin-dev/MoinMoin/action/RenamePage.py	2006-06-16 16:02:42.000000000 +0200
 332 @@ -73,13 +73,13 @@
 333      <tr>
 334          <td class="label"><label>%(newname_label)s</label></td>
 335          <td class="content">
 336 -            <input type="text" name="newpagename" value="%(pagename)s">
 337 +            <input type="text" name="newpagename" value="%(pagename)s" />
 338          </td>
 339      </tr>
 340      <tr>
 341          <td class="label"><label>%(comment_label)s</label></td>
 342          <td class="content">
 343 -            <input type="text" name="comment" maxlength="80">
 344 +            <input type="text" name="comment" maxlength="80" />
 345          </td>
 346      </tr>
 347      <tr>
 348 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/action/SpellCheck.py moin-dev/MoinMoin/action/SpellCheck.py
 349 --- moin-dev.orig/MoinMoin/action/SpellCheck.py	2006-06-21 10:25:45.000000000 +0200
 350 +++ moin-dev/MoinMoin/action/SpellCheck.py	2006-06-16 16:02:42.000000000 +0200
 351 @@ -191,12 +191,12 @@
 352          # add a form containing the bad words
 353          if own_form:
 354              msg = msg + ('<form method="post" action="">\n'
 355 -                         '<input type="hidden" name="action" value="%s">\n') % action_name
 356 +                         '<input type="hidden" name="action" value="%s" />\n') % action_name
 357          
 358 -        checkbox = '<input type="checkbox" name="newwords" value="%(word)s">%(word)s&nbsp;&nbsp;'
 359 +        checkbox = '<input type="checkbox" name="newwords" value="%(word)s" />%(word)s&nbsp;&nbsp;'
 360          msg = msg + (
 361              " ".join(map(lambda w, cb=checkbox: cb % {'word': wikiutil.escape(w),}, badwords)) +
 362 -            '<p><input type="submit" name="button_newwords" value="%s"></p>' %
 363 +            '<p><input type="submit" name="button_newwords" value="%s" /></p>' %
 364                  _('Add checked words to dictionary')
 365          )
 366          if own_form:
 367 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/action/SubscribeUser.py moin-dev/MoinMoin/action/SubscribeUser.py
 368 --- moin-dev.orig/MoinMoin/action/SubscribeUser.py	2006-06-21 10:25:45.000000000 +0200
 369 +++ moin-dev/MoinMoin/action/SubscribeUser.py	2006-06-16 16:02:42.000000000 +0200
 370 @@ -22,9 +22,9 @@
 371  
 372      request.write("""
 373  <form action="" method="POST" enctype="multipart/form-data">
 374 -<input type="hidden" name="action" value="SubscribeUser">
 375 -Enter user names (comma separated): <input type="text" name="users" size="50">
 376 -<input type="submit" value="Subscribe">
 377 +<input type="hidden" name="action" value="SubscribeUser" />
 378 +Enter user names (comma separated): <input type="text" name="users" size="50" />
 379 +<input type="submit" value="Subscribe" />
 380  </form>
 381  """)
 382      request.theme.send_footer(pagename)
 383 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/formatter/text_html.py moin-dev/MoinMoin/formatter/text_html.py
 384 --- moin-dev.orig/MoinMoin/formatter/text_html.py	2006-06-21 10:25:45.000000000 +0200
 385 +++ moin-dev/MoinMoin/formatter/text_html.py	2006-06-16 18:01:13.000000000 +0200
 386 @@ -29,9 +29,6 @@
 387  _self_closing_tags = Set(['area', 'base', 'br', 'col', 'frame', 'hr', 'img', 'input',
 388                            'isindex', 'link', 'meta', 'param'])
 389  
 390 -# We only open those tags and let the browser auto-close them:
 391 -_auto_closing_tags = Set(['p'])
 392 -
 393  # These are the elements which generally should cause an increase in the
 394  # indention level in the html souce code.
 395  _indenting_tags = Set(['ol', 'ul', 'dl', 'li', 'dt', 'dd', 'tr', 'td'])
 396 @@ -372,7 +369,7 @@
 397          @rtype: string
 398          @return: closing tag as a string
 399          """
 400 -        if tag in _self_closing_tags or tag in _auto_closing_tags:
 401 +        if tag in _self_closing_tags:
 402              # This tag was already closed
 403              tagstr = ''
 404          elif tag in _blocks:
 405 @@ -633,7 +630,7 @@
 406              linktext = _('Upload new attachment "%(filename)s"')
 407              return wikiutil.link_tag(
 408                  self.request,
 409 -                ('%s?action=AttachFile&rename=%s' %
 410 +                ('%s?action=AttachFile&amp;rename=%s' %
 411                   (wikiutil.quoteWikinameURL(pagename),
 412                    wikiutil.url_quote_plus(fname))),
 413                  linktext % {'filename': self.text(fname)})
 414 @@ -651,7 +648,7 @@
 415              linktext = _('Upload new attachment "%(filename)s"')
 416              return wikiutil.link_tag(
 417                  self.request,
 418 -                ('%s?action=AttachFile&rename=%s' %
 419 +                ('%s?action=AttachFile&amp;rename=%s' %
 420                   (wikiutil.quoteWikinameURL(pagename),
 421                    wikiutil.url_quote_plus(fname))),
 422                  linktext % {'filename': self.text(fname)})
 423 @@ -681,14 +678,14 @@
 424              linktext = _('Create new drawing "%(filename)s"')
 425              return wikiutil.link_tag(
 426                  self.request,
 427 -                ('%s?action=AttachFile&rename=%s%s' %
 428 +                ('%s?action=AttachFile&amp;rename=%s%s' %
 429                   (wikiutil.quoteWikinameURL(pagename),
 430                    wikiutil.url_quote_plus(fname),
 431 -                  drawing and ('&drawing=%s' % wikiutil.url_quote(drawing)) or '')),
 432 +                  drawing and ('&amp;drawing=%s' % wikiutil.url_quote(drawing)) or '')),
 433                  linktext % {'filename': self.text(fname)})
 434  
 435          mappath = AttachFile.getFilename(self.request, pagename, drawing + u'.map')
 436 -        edit_link = ('%s?action=AttachFile&rename=%s&drawing=%s' % (
 437 +        edit_link = ('%s?action=AttachFile&amp;rename=%s&amp;drawing=%s' % (
 438              wikiutil.quoteWikinameURL(pagename),
 439              wikiutil.url_quote_plus(fname),
 440              wikiutil.url_quote(drawing)))
 441 @@ -710,8 +707,8 @@
 442                  map = re.sub('href\s*=\s*"((?!%TWIKIDRAW%).+?)"', r'href="\1" alt="\1" title="\1"', map)
 443                  # add in edit links plus alt and title attributes
 444                  map = map.replace('%TWIKIDRAW%"', edit_link + '" alt="' + _('Edit drawing %(filename)s') % {'filename': self.text(fname)} + '" title="' + _('Edit drawing %(filename)s') % {'filename': self.text(fname)} + '"')
 445 -                # unxml, because 4.01 concrete will not validate />
 446 -                map = map.replace('/>', '>')
 447 +                # ensure at least 1 space exists, backward compatibility with html
 448 +                map = map.replace('/>', ' />')
 449                  return (map + self.image(
 450                      alt=drawing,
 451                      src=AttachFile.getAttachUrl(
 452 @@ -871,6 +868,7 @@
 453      # Use by code area
 454      _toggleLineNumbersScript = """
 455  <script type="text/javascript">
 456 +<![CDATA[
 457  function isnumbered(obj) {
 458    return obj.childNodes.length && obj.firstChild.childNodes.length && obj.firstChild.firstChild.className == 'LineNumber';
 459  }
 460 @@ -918,6 +916,7 @@
 461    }
 462    return false;
 463  }
 464 +]]
 465  </script>
 466  """
 467      
 468 @@ -957,8 +956,10 @@
 469              if self._code_area_state[1] >= 0:
 470                  toggleLineNumbersLink = r'''
 471  <script type="text/javascript">
 472 +<![CDATA[
 473  document.write('<a href="#" onclick="return togglenumber(\'%s\', %d, %d);" \
 474                  class="codenumbers">%s<\/a>');
 475 +]]>
 476  </script>
 477  ''' % (self._code_area_state[0], self._code_area_state[2], self._code_area_state[3],
 478         _("Toggle line numbers"))
 479 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/macro/__init__.py moin-dev/MoinMoin/macro/__init__.py
 480 --- moin-dev.orig/MoinMoin/macro/__init__.py	2006-06-21 10:25:46.000000000 +0200
 481 +++ moin-dev/MoinMoin/macro/__init__.py	2006-06-16 16:02:42.000000000 +0200
 482 @@ -170,10 +170,10 @@
 483          if type == "fullsearch":
 484              boxes = [
 485                  u'<br>',
 486 -                u'<input type="checkbox" name="context" value="160" checked="checked">',
 487 +                u'<input type="checkbox" name="context" value="160" checked="checked" />',
 488                  _('Display context of search results'),
 489                  u'<br>',
 490 -                u'<input type="checkbox" name="case" value="1">',
 491 +                u'<input type="checkbox" name="case" value="1" />',
 492                  _('Case-sensitive searching'),
 493                  ]
 494              boxes = u'\n'.join(boxes)
 495 @@ -184,10 +184,10 @@
 496          html = [
 497              u'<form method="get" action="">',
 498              u'<div>',
 499 -            u'<input type="hidden" name="action" value="fullsearch">',
 500 -            u'<input type="hidden" name="titlesearch" value="%i">' % type,
 501 -            u'<input type="text" name="value" size="30" value="%s">' % default,
 502 -            u'<input type="submit" value="%s">' % button,
 503 +            u'<input type="hidden" name="action" value="fullsearch" />',
 504 +            u'<input type="hidden" name="titlesearch" value="%i" />' % type,
 505 +            u'<input type="text" name="value" size="30" value="%s" />' % default,
 506 +            u'<input type="submit" value="%s" />' % button,
 507              boxes,
 508              u'</div>',
 509              u'</form>',    
 510 @@ -206,9 +206,9 @@
 511          html = [
 512              u'<form method="get" action="">',
 513              u'<div>',
 514 -            u'<input type="hidden" name="action" value="goto">',
 515 -            u'<input type="text" name="target" size="30">',
 516 -            u'<input type="submit" value="%s">' % _("Go To Page"),
 517 +            u'<input type="hidden" name="action" value="goto" />',
 518 +            u'<input type="text" name="target" size="30" />',
 519 +            u'<input type="submit" value="%s" />' % _("Go To Page"),
 520              u'</div>',
 521              u'</form>',
 522              ]
 523 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/macro/NewPage.py moin-dev/MoinMoin/macro/NewPage.py
 524 --- moin-dev.orig/MoinMoin/macro/NewPage.py	2006-06-21 10:25:46.000000000 +0200
 525 +++ moin-dev/MoinMoin/macro/NewPage.py	2006-06-16 16:02:42.000000000 +0200
 526 @@ -87,18 +87,18 @@
 527          # TODO: better abstract this using the formatter
 528          html = [
 529              u'<form class="macro" method="get" action=""><div>',
 530 -            u'<input type="hidden" name="action" value="newpage">',
 531 -            u'<input type="hidden" name="parent" value="%s">' % wikiutil.escape(parent, 1),
 532 -            u'<input type="hidden" name="template" value="%s">' % wikiutil.escape(template, 1),
 533 -            u'<input type="hidden" name="nametemplate" value="%s">' % wikiutil.escape(nametemplate,1),
 534 +            u'<input type="hidden" name="action" value="newpage" />',
 535 +            u'<input type="hidden" name="parent" value="%s" />' % wikiutil.escape(parent, 1),
 536 +            u'<input type="hidden" name="template" value="%s" />' % wikiutil.escape(template, 1),
 537 +            u'<input type="hidden" name="nametemplate" value="%s" />' % wikiutil.escape(nametemplate,1),
 538          ]
 539          
 540          if requires_input:
 541              html += [
 542 -                u'<input type="text" name="pagename" size="30">',
 543 +                u'<input type="text" name="pagename" size="30" />',
 544              ]
 545          html += [
 546 -            u'<input type="submit" value="%s">' % wikiutil.escape(label, 1),
 547 +            u'<input type="submit" value="%s" />' % wikiutil.escape(label, 1),
 548              u'</div></form>',
 549              ]
 550          return self.formatter.rawHTML('\n'.join(html))
 551 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/macro/TeudView.py moin-dev/MoinMoin/macro/TeudView.py
 552 --- moin-dev.orig/MoinMoin/macro/TeudView.py	2006-06-21 10:25:46.000000000 +0200
 553 +++ moin-dev/MoinMoin/macro/TeudView.py	2006-06-16 16:02:42.000000000 +0200
 554 @@ -53,7 +53,7 @@
 555                      pagename, path, modparts[pathidx])
 556                  if pathidx < pathlen:
 557                      navigation = navigation + '.'
 558 -        navigation = navigation + '<hr size="1">'
 559 +        navigation = navigation + '<hr size="1" />'
 560      else:
 561          # generate index
 562          xmlstr = xmldoc.xml.document(None, encoding=config.charset)
 563 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/multiconfig.py moin-dev/MoinMoin/multiconfig.py
 564 --- moin-dev.orig/MoinMoin/multiconfig.py	2006-06-21 10:25:46.000000000 +0200
 565 +++ moin-dev/MoinMoin/multiconfig.py	2006-06-20 14:30:09.000000000 +0200
 566 @@ -260,10 +260,10 @@
 567      hosts_deny = []
 568      
 569      html_head = ''
 570 -    html_head_queries = '''<meta name="robots" content="noindex,nofollow">\n'''
 571 -    html_head_posts   = '''<meta name="robots" content="noindex,nofollow">\n'''
 572 -    html_head_index   = '''<meta name="robots" content="index,follow">\n'''
 573 -    html_head_normal  = '''<meta name="robots" content="index,nofollow">\n'''
 574 +    html_head_queries = '''<meta name="robots" content="noindex,nofollow" />\n'''
 575 +    html_head_posts   = '''<meta name="robots" content="noindex,nofollow" />\n'''
 576 +    html_head_index   = '''<meta name="robots" content="index,follow" />\n'''
 577 +    html_head_normal  = '''<meta name="robots" content="index,nofollow" />\n'''
 578      html_pagetitle = None
 579  
 580      interwiki_preferred = [] # list of wiki names to show at top of interwiki list
 581 @@ -293,7 +293,7 @@
 582      page_credits = [
 583          '<a href="http://moinmoin.wikiwikiweb.de/">MoinMoin Powered</a>',
 584          '<a href="http://www.python.org/">Python Powered</a>',
 585 -        '<a href="http://validator.w3.org/check?uri=referer">Valid HTML 4.01</a>',
 586 +        '<a href="http://validator.w3.org/check/referer">Valid XHTML 1.0</a>',
 587          ]
 588      page_footer1 = ''
 589      page_footer2 = ''
 590 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/PageEditor.py moin-dev/MoinMoin/PageEditor.py
 591 --- moin-dev.orig/MoinMoin/PageEditor.py	2006-06-21 10:25:45.000000000 +0200
 592 +++ moin-dev/MoinMoin/PageEditor.py	2006-06-16 16:02:42.000000000 +0200
 593 @@ -299,7 +299,7 @@
 594          self.request.write(unicode(html.INPUT(type="hidden", name="action", value="edit")))
 595  
 596          # Send revision of the page our edit is based on
 597 -        self.request.write('<input type="hidden" name="rev" value="%d">' % (rev,))
 598 +        self.request.write('<input type="hidden" name="rev" value="%d" />' % (rev,))
 599  
 600          # Save backto in a hidden input
 601          backto = form.get('backto', [None])[0]
 602 @@ -308,7 +308,7 @@
 603  
 604          # button bar
 605          button_spellcheck = (SpellCheck and
 606 -            '<input class="button" type="submit" name="button_spellcheck" value="%s" onClick="flgChange = false;">'
 607 +            '<input class="button" type="submit" name="button_spellcheck" value="%s" onClick="flgChange = false;" />'
 608                  % _('Check Spelling')) or ''
 609  
 610          save_button_text = _('Save Changes')
 611 @@ -325,19 +325,19 @@
 612  
 613  
 614          self.request.write('''
 615 -<input class="button" type="submit" name="button_save" value="%s" onClick="flgChange = false;">
 616 -<input class="button" type="submit" name="button_preview" value="%s" onClick="flgChange = false;">
 617 +<input class="button" type="submit" name="button_save" value="%s" onClick="flgChange = false;" />
 618 +<input class="button" type="submit" name="button_preview" value="%s" onClick="flgChange = false;" />
 619  ''' % (save_button_text, _('Preview'),))
 620          
 621          if not (self.request.cfg.editor_force and self.request.cfg.editor_default == 'text'):
 622              self.request.write('''
 623 -<input id="switch2gui" style="display: none;" class="button" type="submit" name="button_switch" value="%s">
 624 +<input id="switch2gui" style="display: none;" class="button" type="submit" name="button_switch" value="%s" />
 625  ''' % (_('GUI Mode'),))
 626              
 627          self.request.write('''
 628  %s
 629 -<input class="button" type="submit" name="button_cancel" value="%s">
 630 -<input type="hidden" name="editor" value="text">
 631 +<input class="button" type="submit" name="button_cancel" value="%s" />
 632 +<input type="hidden" name="editor" value="text" />
 633  ''' % (button_spellcheck, cancel_button_text,))
 634  
 635          # Add textarea with page text
 636 @@ -364,7 +364,7 @@
 637          self.request.write("<p>")
 638          self.request.write(_("Comment:"),
 639              ' <input id="editor-comment" type="text" name="comment" value="%s" maxlength="80"'
 640 -            ' onChange="flgChange = true;" onKeyPress="flgChange = true;">' % (
 641 +            ' onChange="flgChange = true;" onKeyPress="flgChange = true;" />' % (
 642                  wikiutil.escape(kw.get('comment', ''), 1), ))
 643          self.request.write("</p>")
 644  
 645 @@ -382,7 +382,7 @@
 646          if self.cfg.mail_enabled:
 647              self.request.write('''
 648  &nbsp;
 649 -<input type="checkbox" name="trivial" id="chktrivial" value="1" %(checked)s>
 650 +<input type="checkbox" name="trivial" id="chktrivial" value="1" %(checked)s />
 651  <label for="chktrivial">%(label)s</label> ''' % {
 652                  'checked': ('', 'checked')[form.get('trivial',['0'])[0] == '1'],
 653                  'label': _("Trivial change"),
 654 @@ -390,7 +390,7 @@
 655  
 656          self.request.write('''
 657  &nbsp;
 658 -<input type="checkbox" name="rstrip" id="chkrstrip" value="1" %(checked)s>
 659 +<input type="checkbox" name="rstrip" id="chkrstrip" value="1" %(checked)s />
 660  <label for="chkrstrip">%(label)s</label>
 661  ''' % {
 662              'checked': ('', 'checked')[form.get('rstrip',['0'])[0] == '1'],
 663 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/PageGraphicalEditor.py moin-dev/MoinMoin/PageGraphicalEditor.py
 664 --- moin-dev.orig/MoinMoin/PageGraphicalEditor.py	2006-06-21 10:25:45.000000000 +0200
 665 +++ moin-dev/MoinMoin/PageGraphicalEditor.py	2006-06-16 16:02:42.000000000 +0200
 666 @@ -206,7 +206,7 @@
 667          self.request.write(unicode(html.INPUT(type="hidden", name="action", value="edit")))
 668  
 669          # Send revision of the page our edit is based on
 670 -        self.request.write('<input type="hidden" name="rev" value="%d">' % (rev,))
 671 +        self.request.write('<input type="hidden" name="rev" value="%d" />' % (rev,))
 672  
 673          # Save backto in a hidden input
 674          backto = form.get('backto', [None])[0]
 675 @@ -215,7 +215,7 @@
 676  
 677          # button bar
 678          button_spellcheck = (SpellCheck and
 679 -            '<input class="button" type="submit" name="button_spellcheck" value="%s">'
 680 +            '<input class="button" type="submit" name="button_spellcheck" value="%s" />'
 681                  % _('Check Spelling')) or ''
 682  
 683          save_button_text = _('Save Changes')
 684 @@ -231,12 +231,12 @@
 685              }, '</em></p>')
 686  
 687          self.request.write('''
 688 -<input class="button" type="submit" name="button_save" value="%s">
 689 -<input class="button" type="submit" name="button_preview" value="%s">
 690 -<input class="button" type="submit" name="button_switch" value="%s">
 691 +<input class="button" type="submit" name="button_save" value="%s" />
 692 +<input class="button" type="submit" name="button_preview" value="%s" />
 693 +<input class="button" type="submit" name="button_switch" value="%s" />
 694  %s
 695 -<input class="button" type="submit" name="button_cancel" value="%s">
 696 -<input type="hidden" name="editor" value="gui">
 697 +<input class="button" type="submit" name="button_cancel" value="%s" />
 698 +<input type="hidden" name="editor" value="gui" />
 699  ''' % (save_button_text, _('Preview'), _('Text mode'), button_spellcheck, cancel_button_text,))
 700  
 701          self.sendconfirmleaving() # TODO update state of flgChange to make this work, see PageEditor
 702 @@ -295,7 +295,7 @@
 703  """)
 704          self.request.write("<p>")
 705          self.request.write(_("Comment:"),
 706 -            ' <input id="editor-comment" type="text" name="comment" value="%s" maxlength="80">' % (
 707 +            ' <input id="editor-comment" type="text" name="comment" value="%s" maxlength="80" />' % (
 708                  wikiutil.escape(kw.get('comment', ''), 1), ))
 709          self.request.write("</p>")
 710  
 711 @@ -312,7 +312,7 @@
 712          if self.cfg.mail_enabled:
 713              self.request.write('''
 714  &nbsp;
 715 -<input type="checkbox" name="trivial" id="chktrivial" value="1" %(checked)s>
 716 +<input type="checkbox" name="trivial" id="chktrivial" value="1" %(checked)s />
 717  <label for="chktrivial">%(label)s</label> ''' % {
 718                  'checked': ('', 'checked')[form.get('trivial',['0'])[0] == '1'],
 719                  'label': _("Trivial change"),
 720 @@ -320,7 +320,7 @@
 721  
 722          self.request.write('''
 723  &nbsp;
 724 -<input type="checkbox" name="rstrip" id="chkrstrip" value="1" %(checked)s>
 725 +<input type="checkbox" name="rstrip" id="chkrstrip" value="1" %(checked)s />
 726  <label for="chkrstrip">%(label)s</label>
 727  </p> ''' % {
 728              'checked': ('', 'checked')[form.get('rstrip',['0'])[0] == '1'],
 729 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/Page.py moin-dev/MoinMoin/Page.py
 730 --- moin-dev.orig/MoinMoin/Page.py	2006-06-21 10:25:45.000000000 +0200
 731 +++ moin-dev/MoinMoin/Page.py	2006-06-16 16:02:42.000000000 +0200
 732 @@ -1226,7 +1226,7 @@
 733                  # user-defined form preview?
 734                  # TODO: check if this is also an RTL form - then add ui_lang_attr
 735                  if pi_formtext:
 736 -                    pi_formtext.append('<input type="hidden" name="fieldlist" value="%s">\n' %
 737 +                    pi_formtext.append('<input type="hidden" name="fieldlist" value="%s" />\n' %
 738                          "|".join(pi_formfields))
 739                      pi_formtext.append('</form></table>\n')
 740                      pi_formtext.append(_(
 741 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/script/export/dump.py moin-dev/MoinMoin/script/export/dump.py
 742 --- moin-dev.orig/MoinMoin/script/export/dump.py	2006-06-21 10:25:46.000000000 +0200
 743 +++ moin-dev/MoinMoin/script/export/dump.py	2006-06-16 16:12:36.000000000 +0200
 744 @@ -18,17 +18,17 @@
 745  from MoinMoin.action import AttachFile
 746  
 747  url_prefix = "."
 748 -logo_html = '<img src="logo.png">'
 749 +logo_html = '<img src="logo.png" />'
 750  HTML_SUFFIX = ".html"
 751  
 752 -page_template = u'''<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
 753 -<html>
 754 +page_template = u'''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 755 +<html xmlns="http://www.w3.org/1999/xhtml">
 756  <head>
 757 -<meta http-equiv="content-type" content="text/html; charset=%(charset)s">
 758 +<meta http-equiv="content-type" content="text/html; charset=%(charset)s" />
 759  <title>%(pagename)s</title>
 760 -<link rel="stylesheet" type="text/css" media="all" charset="utf-8" href="%(theme)s/css/common.css">
 761 -<link rel="stylesheet" type="text/css" media="screen" charset="utf-8" href="%(theme)s/css/screen.css">
 762 -<link rel="stylesheet" type="text/css" media="print" charset="utf-8" href="%(theme)s/css/print.css">
 763 +<link rel="stylesheet" type="text/css" media="all" charset="utf-8" href="%(theme)s/css/common.css" />
 764 +<link rel="stylesheet" type="text/css" media="screen" charset="utf-8" href="%(theme)s/css/screen.css" />
 765 +<link rel="stylesheet" type="text/css" media="print" charset="utf-8" href="%(theme)s/css/print.css" />
 766  </head>
 767  <body>
 768  <table>
 769 @@ -41,12 +41,12 @@
 770  </td>
 771  </tr>
 772  </table>
 773 -<hr>
 774 +<hr />
 775  <div id="page">
 776  <h1 id="title">%(pagename)s</h1>
 777  %(pagehtml)s
 778  </div>
 779 -<hr>
 780 +<hr />
 781  %(timestamp)s
 782  </body>
 783  </html>
 784 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/stats/hitcounts.py moin-dev/MoinMoin/stats/hitcounts.py
 785 --- moin-dev.orig/MoinMoin/stats/hitcounts.py	2006-06-21 10:25:48.000000000 +0200
 786 +++ moin-dev/MoinMoin/stats/hitcounts.py	2006-06-16 16:02:42.000000000 +0200
 787 @@ -41,7 +41,7 @@
 788      data = {'url': page.url(request, querystr, escape=0)}
 789      data.update(request.cfg.chart_options)
 790      result = ('<img src="%(url)s" width="%(width)d" height="%(height)d"'
 791 -              ' alt="hitcounts chart">') % data
 792 +              ' alt="hitcounts chart" />') % data
 793  
 794      return result
 795  
 796 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/stats/pagesize.py moin-dev/MoinMoin/stats/pagesize.py
 797 --- moin-dev.orig/MoinMoin/stats/pagesize.py	2006-06-21 10:25:48.000000000 +0200
 798 +++ moin-dev/MoinMoin/stats/pagesize.py	2006-06-16 16:02:42.000000000 +0200
 799 @@ -38,7 +38,7 @@
 800      data = {'url': page.url(request, querystr, escape=0)}
 801      data.update(request.cfg.chart_options)
 802      result = ('<img src="%(url)s" width="%(width)d" height="%(height)d"'
 803 -              ' alt="pagesize chart">') % data
 804 +              ' alt="pagesize chart" />') % data
 805      return result
 806  
 807  
 808 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/stats/useragents.py moin-dev/MoinMoin/stats/useragents.py
 809 --- moin-dev.orig/MoinMoin/stats/useragents.py	2006-06-21 10:25:48.000000000 +0200
 810 +++ moin-dev/MoinMoin/stats/useragents.py	2006-06-16 16:02:42.000000000 +0200
 811 @@ -39,7 +39,7 @@
 812      data = {'url': page.url(request, querystr, escape=0)}
 813      data.update(request.cfg.chart_options)
 814      result = ('<img src="%(url)s" width="%(width)d" height="%(height)d"'
 815 -              ' alt="useragents chart">') % data
 816 +              ' alt="useragents chart" />') % data
 817  
 818      return result
 819  
 820 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/_tests/broken/test_converter_text_html_text_moin_wiki.py moin-dev/MoinMoin/_tests/broken/test_converter_text_html_text_moin_wiki.py
 821 --- moin-dev.orig/MoinMoin/_tests/broken/test_converter_text_html_text_moin_wiki.py	2006-06-21 10:25:45.000000000 +0200
 822 +++ moin-dev/MoinMoin/_tests/broken/test_converter_text_html_text_moin_wiki.py	2006-06-16 16:02:42.000000000 +0200
 823 @@ -1050,7 +1050,7 @@
 824  
 825      def testSmiley01(self):
 826          test = ur":-)"
 827 -        output = ur"""<img src="/wiki/modern/img/smile.png" alt=":-)" height="15" width="15">"""
 828 +        output = ur"""<img src="/wiki/modern/img/smile.png" alt=":-)" height="15" width="15" />"""
 829          self.do(test, output)
 830  
 831  class StripTests(unittest.TestCase):
 832 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/theme/__init__.py moin-dev/MoinMoin/theme/__init__.py
 833 --- moin-dev.orig/MoinMoin/theme/__init__.py	2006-06-21 10:25:48.000000000 +0200
 834 +++ moin-dev/MoinMoin/theme/__init__.py	2006-06-16 16:11:51.000000000 +0200
 835 @@ -487,7 +487,7 @@
 836          try:
 837              tag = self.request.formatter.image(src=img, alt=alt, width=w, height=h)
 838          except AttributeError: # XXX FIXME if we have no formatter or no request 
 839 -            tag = '<img src="%s" alt="%s" width="%s" height="%s">' % (
 840 +            tag = '<img src="%s" alt="%s" width="%s" height="%s" />' % (
 841                  img, alt, w, h)
 842              import warnings
 843              warnings.warn("calling themes without correct request", DeprecationWarning)
 844 @@ -580,7 +580,7 @@
 845          @rtype: string
 846          @return: stylesheets links
 847          """
 848 -        link = '<link rel="stylesheet" type="text/css" charset="%s" media="%s" href="%s">'
 849 +        link = '<link rel="stylesheet" type="text/css" charset="%s" media="%s" href="%s" />'
 850  
 851          # Check mode
 852          if d.get('print_mode'):
 853 @@ -695,16 +695,16 @@
 854          html = u'''
 855  <form id="searchform" method="get" action="">
 856  <div>
 857 -<input type="hidden" name="action" value="fullsearch">
 858 -<input type="hidden" name="context" value="180">
 859 +<input type="hidden" name="action" value="fullsearch" />
 860 +<input type="hidden" name="context" value="180" />
 861  <label for="searchinput">%(search_label)s</label>
 862  <input id="searchinput" type="text" name="value" value="%(search_value)s" size="20"
 863      onfocus="searchFocus(this)" onblur="searchBlur(this)"
 864 -    onkeyup="searchChange(this)" onchange="searchChange(this)" alt="Search">
 865 +    onkeyup="searchChange(this)" onchange="searchChange(this)" alt="Search" />
 866  <input id="titlesearch" name="titlesearch" type="submit"
 867 -    value="%(search_title_label)s" alt="Search Titles">
 868 +    value="%(search_title_label)s" alt="Search Titles" />
 869  <input id="fullsearch" name="fullsearch" type="submit"
 870 -    value="%(search_full_label)s" alt="Search Full Text">
 871 +    value="%(search_full_label)s" alt="Search Full Text" />
 872  </div>
 873  </form>
 874  <script type="text/javascript">
 875 @@ -859,7 +859,7 @@
 876          link = u''
 877          if self.shouldUseRSS():
 878              link = (u'<link rel="alternate" title="%s Recent Changes" '
 879 -                    u'href="%s" type="application/rss+xml">') % (
 880 +                    u'href="%s" type="application/rss+xml" />') % (
 881                          self.cfg.sitename,
 882                          self.rsshref() )
 883          return link
 884 @@ -963,7 +963,7 @@
 885          # class="disabled" is a workaround for browsers that ignore
 886          # "disabled", e.g IE, Safari
 887          # for XHTML: data['disabled'] = ' disabled="disabled"'
 888 -        disabled = ' disabled class="disabled"'
 889 +        disabled = ' disabled="disabled" class="disabled"'
 890          
 891          # Format standard actions
 892          available = request.getAvailableActions(page)
 893 @@ -1018,14 +1018,14 @@
 894  <div>
 895      <label>%(label)s</label>
 896      <select name="action"
 897 -        onchange="if ((this.selectedIndex != 0) &&
 898 +        onchange="if ((this.selectedIndex != 0) &amp;&amp;
 899                        (this.options[this.selectedIndex].disabled == false)) {
 900                  this.form.submit();
 901              }
 902              this.selectedIndex = 0;">
 903          %(options)s
 904      </select>
 905 -    <input type="submit" value="%(do_button)s">
 906 +    <input type="submit" value="%(do_button)s" />
 907  </div>
 908  <script type="text/javascript">
 909  <!--// Init menu
 910 @@ -1160,7 +1160,7 @@
 911          _ = self.request.getText
 912          return """\
 913  <script type="text/javascript">
 914 -var gui_editor_link_href = "%(url)s?action=edit&editor=gui";
 915 +var gui_editor_link_href = "%(url)s?action=edit&amp;editor=gui";
 916  var gui_editor_link_text = "%(text)s";
 917  </script>        
 918  """ % {'url': page.url(self.request),
 919 @@ -1466,14 +1466,14 @@
 920  
 921          # include charset information - needed for moin_dump or any other case
 922          # when reading the html without a web server
 923 -        user_head.append('''<meta http-equiv="Content-Type" content="%s;charset=%s">\n''' % (page.output_mimetype, page.output_charset))
 924 +        user_head.append('''<meta http-equiv="Content-Type" content="%s;charset=%s" />\n''' % (page.output_mimetype, page.output_charset))
 925  
 926          meta_keywords = request.getPragma('keywords')
 927          meta_desc = request.getPragma('description')
 928          if meta_keywords:
 929 -            user_head.append('<meta name="keywords" content="%s">\n' % escape(meta_keywords, 1))
 930 +            user_head.append('<meta name="keywords" content="%s" />\n' % escape(meta_keywords, 1))
 931          if meta_desc:
 932 -            user_head.append('<meta name="description" content="%s">\n' % escape(meta_desc, 1))
 933 +            user_head.append('<meta name="description" content="%s" />\n' % escape(meta_desc, 1))
 934  
 935          # search engine precautions / optimization:
 936          # if it is an action or edit/search, send query headers (noindex,nofollow):
 937 @@ -1496,14 +1496,13 @@
 938              user_head.append(request.cfg.html_head_normal)
 939  
 940          if keywords.has_key('pi_refresh') and keywords['pi_refresh']:
 941 -            user_head.append('<meta http-equiv="refresh" content="%(delay)d;URL=%(url)s">' % keywords['pi_refresh'])
 942 +            user_head.append('<meta http-equiv="refresh" content="%(delay)d;URL=%(url)s" />' % keywords['pi_refresh'])
 943          
 944          # output buffering increases latency but increases throughput as well
 945          output = []
 946 -        # later: <html xmlns=\"http://www.w3.org/1999/xhtml\">
 947          output.append("""\
 948 -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
 949 -<html>
 950 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 951 +<html xmlns="http://www.w3.org/1999/xhtml">
 952  <head>
 953  %s
 954  %s
 955 @@ -1521,11 +1520,11 @@
 956          ))
 957  
 958          # Links
 959 -        output.append('<link rel="Start" href="%s/%s">\n' % (scriptname, wikiutil.quoteWikinameURL(page_front_page)))
 960 +        output.append('<link rel="Start" href="%s/%s" />\n' % (scriptname, wikiutil.quoteWikinameURL(page_front_page)))
 961          if pagename:
 962 -            output.append('<link rel="Alternate" title="%s" href="%s/%s?action=raw">\n' % (
 963 +            output.append('<link rel="Alternate" title="%s" href="%s/%s?action=raw" />\n' % (
 964                  _('Wiki Markup'), scriptname, pagename_quoted,))
 965 -            output.append('<link rel="Alternate" media="print" title="%s" href="%s/%s?action=print">\n' % (
 966 +            output.append('<link rel="Alternate" media="print" title="%s" href="%s/%s?action=print" />\n' % (
 967                  _('Print View'), scriptname, pagename_quoted,))
 968  
 969              # !!! currently disabled due to Mozilla link prefetching, see
 970 @@ -1538,15 +1537,15 @@
 971              #~         # this shopuld never happend in theory, but let's be sure
 972              #~         pass
 973              #~     else:
 974 -            #~         request.write('<link rel="First" href="%s/%s">\n' % (request.getScriptname(), quoteWikinameURL(all_pages[0]))
 975 +            #~         request.write('<link rel="First" href="%s/%s" />\n' % (request.getScriptname(), quoteWikinameURL(all_pages[0]))
 976              #~         if pos > 0:
 977 -            #~             request.write('<link rel="Previous" href="%s/%s">\n' % (request.getScriptname(), quoteWikinameURL(all_pages[pos-1])))
 978 +            #~             request.write('<link rel="Previous" href="%s/%s" />\n' % (request.getScriptname(), quoteWikinameURL(all_pages[pos-1])))
 979              #~         if pos+1 < len(all_pages):
 980 -            #~             request.write('<link rel="Next" href="%s/%s">\n' % (request.getScriptname(), quoteWikinameURL(all_pages[pos+1])))
 981 -            #~         request.write('<link rel="Last" href="%s/%s">\n' % (request.getScriptname(), quoteWikinameURL(all_pages[-1])))
 982 +            #~             request.write('<link rel="Next" href="%s/%s" />\n' % (request.getScriptname(), quoteWikinameURL(all_pages[pos+1])))
 983 +            #~         request.write('<link rel="Last" href="%s/%s" />\n' % (request.getScriptname(), quoteWikinameURL(all_pages[-1])))
 984  
 985              if page_parent_page:
 986 -                output.append('<link rel="Up" href="%s/%s">\n' % (scriptname, wikiutil.quoteWikinameURL(page_parent_page)))
 987 +                output.append('<link rel="Up" href="%s/%s" />\n' % (scriptname, wikiutil.quoteWikinameURL(page_parent_page)))
 988  
 989          # write buffer because we call AttachFile
 990          request.write(''.join(output))
 991 @@ -1557,10 +1556,10 @@
 992              AttachFile.send_link_rel(request, pagename)
 993  
 994          output.extend([
 995 -            '<link rel="Search" href="%s/%s">\n' % (scriptname, wikiutil.quoteWikinameURL(page_find_page)),
 996 -            '<link rel="Index" href="%s/%s">\n' % (scriptname, wikiutil.quoteWikinameURL(page_title_index)),
 997 -            '<link rel="Glossary" href="%s/%s">\n' % (scriptname, wikiutil.quoteWikinameURL(page_word_index)),
 998 -            '<link rel="Help" href="%s/%s">\n' % (scriptname, wikiutil.quoteWikinameURL(page_help_formatting)),
 999 +            '<link rel="Search" href="%s/%s" />\n' % (scriptname, wikiutil.quoteWikinameURL(page_find_page)),
1000 +            '<link rel="Index" href="%s/%s" />\n' % (scriptname, wikiutil.quoteWikinameURL(page_title_index)),
1001 +            '<link rel="Glossary" href="%s/%s" />\n' % (scriptname, wikiutil.quoteWikinameURL(page_word_index)),
1002 +            '<link rel="Help" href="%s/%s" />\n' % (scriptname, wikiutil.quoteWikinameURL(page_help_formatting)),
1003                        ])
1004          
1005          output.append("</head>\n")
1006 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/MoinMoin/theme/modern.py moin-dev/MoinMoin/theme/modern.py
1007 --- moin-dev.orig/MoinMoin/theme/modern.py	2006-06-21 10:25:48.000000000 +0200
1008 +++ moin-dev/MoinMoin/theme/modern.py	2006-06-16 16:02:42.000000000 +0200
1009 @@ -35,7 +35,7 @@
1010              self.trail(d),
1011              self.navibar(d),
1012              #u'<hr id="pageline">',
1013 -            u'<div id="pageline"><hr style="display:none;"></div>',
1014 +            u'<div id="pageline"><hr style="display:none;" /></div>',
1015              self.msg(d),
1016              self.editbar(d),
1017              u'</div>',
1018 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/wiki/config/wikiconfig.py moin-dev/wiki/config/wikiconfig.py
1019 --- moin-dev.orig/wiki/config/wikiconfig.py	2006-06-21 10:25:49.000000000 +0200
1020 +++ moin-dev/wiki/config/wikiconfig.py	2006-06-16 16:02:42.000000000 +0200
1021 @@ -38,7 +38,7 @@
1022      # Wiki logo. You can use an image, text or both. [Unicode]
1023      # For no logo or text, use '' - the default is to show the sitename.
1024      # See also url_prefix setting below!
1025 -    logo_string = u'<img src="/wiki/common/moinmoin.png" alt="MoinMoin Logo">'
1026 +    logo_string = u'<img src="/wiki/common/moinmoin.png" alt="MoinMoin Logo" />'
1027  
1028      # name of entry page / front page [Unicode], choose one of those:
1029  
1030 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/wiki/htdocs/applets/FCKeditor/_samples/py/sample01.py moin-dev/wiki/htdocs/applets/FCKeditor/_samples/py/sample01.py
1031 --- moin-dev.orig/wiki/htdocs/applets/FCKeditor/_samples/py/sample01.py	2006-06-21 10:25:49.000000000 +0200
1032 +++ moin-dev/wiki/htdocs/applets/FCKeditor/_samples/py/sample01.py	2006-06-16 16:02:42.000000000 +0200
1033 @@ -34,15 +34,15 @@
1034  <html>
1035  	<head>
1036  		<title>FCKeditor - Sample</title>
1037 -		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
1038 -		<meta name="robots" content="noindex, nofollow">
1039 +		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1040 +		<meta name="robots" content="noindex, nofollow" />
1041  		<link href="../sample.css" rel="stylesheet" type="text/css" />
1042  	</head>
1043  	<body>
1044  		<h1>FCKeditor - Python - Sample 1</h1>
1045  		This sample displays a normal HTML form with an FCKeditor with full features 
1046  		enabled.
1047 -		<hr>
1048 +		<hr />
1049  		<form action="sampleposteddata.py" method="post" target="_blank">
1050  """
1051  
1052 @@ -64,10 +64,10 @@
1053  """
1054  
1055  # For testing your environments
1056 -print "<hr>"
1057 +print "<hr />"
1058  for key in os.environ.keys():
1059  	print "%s: %s<br>" % (key, os.environ.get(key, ""))
1060 -print "<hr>"
1061 +print "<hr />"
1062  
1063  # Document footer
1064  print """
1065 diff -Naur -x .hg -x '*.pyc' -r moin-dev.orig/wiki/htdocs/applets/FCKeditor/_samples/py/sampleposteddata.py moin-dev/wiki/htdocs/applets/FCKeditor/_samples/py/sampleposteddata.py
1066 --- moin-dev.orig/wiki/htdocs/applets/FCKeditor/_samples/py/sampleposteddata.py	2006-06-21 10:25:49.000000000 +0200
1067 +++ moin-dev/wiki/htdocs/applets/FCKeditor/_samples/py/sampleposteddata.py	2006-06-16 16:02:42.000000000 +0200
1068 @@ -37,8 +37,8 @@
1069  <html>
1070  	<head>
1071  		<title>FCKeditor - Samples - Posted Data</title>
1072 -		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
1073 -		<meta name="robots" content="noindex, nofollow">
1074 +		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1075 +		<meta name="robots" content="noindex, nofollow" />
1076  		<link href="../sample.css" rel="stylesheet" type="text/css" />
1077  	</head>
1078  	<body>
1079 @@ -48,7 +48,7 @@
1080  print """
1081  		<h1>FCKeditor - Samples - Posted Data</h1>
1082  		This page lists all data posted by the form.
1083 -		<hr>
1084 +		<hr />
1085  		<table width="100%" border="1" cellspacing="0" bordercolor="#999999">
1086  			<tr style="FONT-WEIGHT: bold; COLOR: #dddddd; BACKGROUND-COLOR: #999999">
1087  				<td nowrap>Field Name&nbsp;&nbsp;</td>
1088 @@ -69,10 +69,10 @@
1089  print "</table>"
1090  
1091  # For testing your environments
1092 -print "<hr>"
1093 +print "<hr />"
1094  for key in os.environ.keys():
1095  	print "%s: %s<br>" % (key, os.environ.get(key, ""))
1096 -print "<hr>"
1097 +print "<hr />"
1098  
1099  # Document footer
1100  print """
valid_xhtml10_1.patch

Comments

TODO

Known Issues

Discussion

Thanks a lot for your work on this. Especially the more complex things on the todo might be critical as there is no such thing as 99% xhtml. -- ThomasWaldmann 2006-06-21 10:37:11

Please only output CDATA sections if you're outputting application/xhtml+xml ... which I suspect/hope you're not yet, because that requires 100% XHTML. CDATA will break in text/html, even if syntactically it is perfectly XHTML. Otherwise thanks for doing a lot of the tedious gruntwork. -- -- DeronMeranda 2006-06-21 15:10:44

Plan


CategoryMoinMoinPatch

MoinMoin: MoinMoinPatch/ValidXHTMLOutput (last edited 2007-10-29 19:08:53 by localhost)