Merge lp:~wgrant/launchpad/wbr-is-void into lp:launchpad
- wbr-is-void
- Merge into devel
| Status: | Merged |
|---|---|
| Approved by: | William Grant on 2012-04-02 |
| Approved revision: | no longer in the source branch. |
| Merged at revision: | 15051 |
| Proposed branch: | lp:~wgrant/launchpad/wbr-is-void |
| Merge into: | lp:launchpad |
| Diff against target: |
448 lines (+99/-93) 10 files modified
lib/lp/app/__init__.py (+8/-2) lib/lp/app/browser/stringformatter.py (+2/-2) lib/lp/app/browser/tests/test_stringformatter.py (+23/-23) lib/lp/app/doc/displaying-paragraphs-of-text.txt (+45/-45) lib/lp/app/doc/tales-email-formatting.txt (+10/-10) lib/lp/app/doc/tales.txt (+5/-5) lib/lp/blueprints/workitemmigration.py (+1/-1) lib/lp/bugs/stories/bugs/xx-bug-comments-truncated.txt (+2/-2) lib/lp/registry/browser/tests/person-views.txt (+2/-2) lib/lp/registry/stories/announcements/xx-announcements.txt (+1/-1) |
| To merge this branch: | bzr merge lp:~wgrant/launchpad/wbr-is-void |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Ian Booth (community) | 2012-04-02 | Approve on 2012-04-02 | |
|
Review via email:
|
|||
Commit Message
Use a self-closing form of <wbr> to be a valid HTML/XML polyglot. It's a void element, so a separate closing tag is invalid.
Description of the Change
Launchpad currently spits out <wbr></wbr> sequences instead of the classical <wbr>. Amusingly, while having a separate closing tag makes it well-formed XML, because it's a void element it's neither valid HTML nor XHTML.
We should use <wbr /> instead. HTML5 and XML both like that, as do all the browsers we support.
The only thing I've found that doesn't is BeautifulSoup; it assumes the closing tag was forgotten, so extends the element to the next tag. Even if a browser I haven't tested does the same thing, the tag will just be ignored harmlessly.
This makes a lot more of our pages valid HTML5 while remaining well-formed XML.
Preview Diff
| 1 | === modified file 'lib/lp/app/__init__.py' |
| 2 | --- lib/lp/app/__init__.py 2011-12-19 23:38:16 +0000 |
| 3 | +++ lib/lp/app/__init__.py 2012-04-02 11:42:25 +0000 |
| 4 | @@ -15,10 +15,16 @@ |
| 5 | # values, but they kindly left this global variable for you to monkey patch if |
| 6 | # you want the old behavior, just like we do. |
| 7 | from zope.app.form.browser import itemswidgets |
| 8 | - |
| 9 | - |
| 10 | itemswidgets.EXPLICIT_EMPTY_SELECTION = False |
| 11 | |
| 12 | +# Monkeypatch our embedded BeautifulSoup and the one in mechanize to |
| 13 | +# teach them that wbr (new in HTML5, but widely supported forever) is |
| 14 | +# self-closing. |
| 15 | +import BeautifulSoup |
| 16 | +import mechanize._beautifulsoup |
| 17 | +BeautifulSoup.BeautifulSoup.SELF_CLOSING_TAGS['wbr'] = None |
| 18 | +mechanize._beautifulsoup.BeautifulSoup.SELF_CLOSING_TAGS['wbr'] = None |
| 19 | + |
| 20 | # Load versioninfo.py so that we get errors on start-up rather than waiting |
| 21 | # for first page load. |
| 22 | import lp.app.versioninfo |
| 23 | |
| 24 | === modified file 'lib/lp/app/browser/stringformatter.py' |
| 25 | --- lib/lp/app/browser/stringformatter.py 2011-12-29 05:29:36 +0000 |
| 26 | +++ lib/lp/app/browser/stringformatter.py 2012-04-02 11:42:25 +0000 |
| 27 | @@ -153,7 +153,7 @@ |
| 28 | while pos < len(word): |
| 29 | chunk, pos = next_word_chunk(word, pos, 7, 15) |
| 30 | broken.append(chunk) |
| 31 | - return '<wbr></wbr>'.join(broken) |
| 32 | + return '<wbr />'.join(broken) |
| 33 | |
| 34 | |
| 35 | break_text_pat = re.compile(r''' |
| 36 | @@ -718,7 +718,7 @@ |
| 37 | return line[:-4] |
| 38 | |
| 39 | for line in self.text_to_html().split('\n'): |
| 40 | - if 'Desired=<wbr></wbr>Unknown/' in line and not in_fold: |
| 41 | + if 'Desired=<wbr />Unknown/' in line and not in_fold: |
| 42 | # When we see a evidence of dpkg output, we switch the |
| 43 | # quote matching rules. We do not assume lines that start |
| 44 | # with a pipe are quoted passages. dpkg output is often |
| 45 | |
| 46 | === modified file 'lib/lp/app/browser/tests/test_stringformatter.py' |
| 47 | --- lib/lp/app/browser/tests/test_stringformatter.py 2012-01-01 02:58:52 +0000 |
| 48 | +++ lib/lp/app/browser/tests/test_stringformatter.py 2012-04-02 11:42:25 +0000 |
| 49 | @@ -73,18 +73,18 @@ |
| 50 | >>> from lp.app.browser.stringformatter import add_word_breaks |
| 51 | |
| 52 | >>> print add_word_breaks('abcdefghijklmnop') |
| 53 | - abcdefghijklmno<wbr></wbr>p |
| 54 | + abcdefghijklmno<wbr />p |
| 55 | |
| 56 | >>> print add_word_breaks('abcdef/ghijklmnop') |
| 57 | - abcdef/<wbr></wbr>ghijklmnop |
| 58 | + abcdef/<wbr />ghijklmnop |
| 59 | |
| 60 | >>> print add_word_breaks('ab/cdefghijklmnop') |
| 61 | - ab/cdefghijklmn<wbr></wbr>op |
| 62 | + ab/cdefghijklmn<wbr />op |
| 63 | |
| 64 | The string can contain HTML entities, which do not get split: |
| 65 | |
| 66 | >>> print add_word_breaks('abcdef&anentity;hijklmnop') |
| 67 | - abcdef&anentity;<wbr></wbr>hijklmnop |
| 68 | + abcdef&anentity;<wbr />hijklmnop |
| 69 | """ |
| 70 | |
| 71 | |
| 72 | @@ -100,13 +100,13 @@ |
| 73 | 1234567890123456 |
| 74 | |
| 75 | >>> print break_long_words('12345678901234567890') |
| 76 | - 123456789012345<wbr></wbr>67890 |
| 77 | + 123456789012345<wbr />67890 |
| 78 | |
| 79 | >>> print break_long_words('<tag a12345678901234567890="foo"></tag>') |
| 80 | <tag a12345678901234567890="foo"></tag> |
| 81 | |
| 82 | >>> print break_long_words('12345678901234567890 1234567890.1234567890') |
| 83 | - 123456789012345<wbr></wbr>67890 1234567890.<wbr></wbr>1234567890 |
| 84 | + 123456789012345<wbr />67890 1234567890.<wbr />1234567890 |
| 85 | |
| 86 | >>> print break_long_words('1234567890&abcdefghi;123') |
| 87 | 1234567890&abcdefghi;123 |
| 88 | @@ -172,13 +172,13 @@ |
| 89 | |
| 90 | expected_strings = [ |
| 91 | ('<p><a rel="nofollow" href="http://example.com">' |
| 92 | - 'http://<wbr></wbr>example.<wbr></wbr>com</a></p>'), |
| 93 | + 'http://<wbr />example.<wbr />com</a></p>'), |
| 94 | ('<p><a rel="nofollow" href="http://example.com/">' |
| 95 | - 'http://<wbr></wbr>example.<wbr></wbr>com/</a></p>'), |
| 96 | + 'http://<wbr />example.<wbr />com/</a></p>'), |
| 97 | ('<p><a rel="nofollow" href="http://example.com/path">' |
| 98 | - 'http://<wbr></wbr>example.<wbr></wbr>com/path</a></p>'), |
| 99 | + 'http://<wbr />example.<wbr />com/path</a></p>'), |
| 100 | ('<p><a rel="nofollow" href="http://example.com/path/">' |
| 101 | - 'http://<wbr></wbr>example.<wbr></wbr>com/path/</a></p>'), |
| 102 | + 'http://<wbr />example.<wbr />com/path/</a></p>'), |
| 103 | ] |
| 104 | |
| 105 | self.assertEqual( |
| 106 | @@ -196,23 +196,23 @@ |
| 107 | |
| 108 | expected_html = [ |
| 109 | ('<p>(<a rel="nofollow" href="http://example.com">' |
| 110 | - 'http://<wbr></wbr>example.<wbr></wbr>com</a>)</p>'), |
| 111 | + 'http://<wbr />example.<wbr />com</a>)</p>'), |
| 112 | ('<p><a rel="nofollow" ' |
| 113 | 'href="http://example.com/path_(with_parens)">' |
| 114 | - 'http://<wbr></wbr>example.<wbr></wbr>com/path_' |
| 115 | - '<wbr></wbr>(with_parens)</a></p>'), |
| 116 | + 'http://<wbr />example.<wbr />com/path_' |
| 117 | + '<wbr />(with_parens)</a></p>'), |
| 118 | ('<p>(<a rel="nofollow" ' |
| 119 | 'href="http://example.com/path_(with_parens)">' |
| 120 | - 'http://<wbr></wbr>example.<wbr></wbr>com/path_' |
| 121 | - '<wbr></wbr>(with_parens)</a>)</p>'), |
| 122 | + 'http://<wbr />example.<wbr />com/path_' |
| 123 | + '<wbr />(with_parens)</a>)</p>'), |
| 124 | ('<p>(<a rel="nofollow" ' |
| 125 | 'href="http://example.com/path_(with_parens)and_stuff">' |
| 126 | - 'http://<wbr></wbr>example.<wbr></wbr>com' |
| 127 | - '/path_<wbr></wbr>(with_parens)<wbr></wbr>and_stuff</a>)</p>'), |
| 128 | + 'http://<wbr />example.<wbr />com' |
| 129 | + '/path_<wbr />(with_parens)<wbr />and_stuff</a>)</p>'), |
| 130 | ('<p><a rel="nofollow" ' |
| 131 | 'href="http://example.com/path_(with_parens">' |
| 132 | - 'http://<wbr></wbr>example.<wbr></wbr>com' |
| 133 | - '/path_<wbr></wbr>(with_parens</a></p>'), |
| 134 | + 'http://<wbr />example.<wbr />com' |
| 135 | + '/path_<wbr />(with_parens</a></p>'), |
| 136 | ] |
| 137 | |
| 138 | self.assertEqual( |
| 139 | @@ -236,7 +236,7 @@ |
| 140 | expected_html = ( |
| 141 | '<p>This becomes a link: ' |
| 142 | '<a rel="nofollow" ' |
| 143 | - 'href="apt:some-package">apt:some-<wbr></wbr>package</a></p>') |
| 144 | + 'href="apt:some-package">apt:some-<wbr />package</a></p>') |
| 145 | self.assertEqual(expected_html, html) |
| 146 | |
| 147 | # Do it again for apt:// |
| 148 | @@ -245,7 +245,7 @@ |
| 149 | expected_html = ( |
| 150 | '<p>This becomes a link: ' |
| 151 | '<a rel="nofollow" ' |
| 152 | - 'href="apt://some-package">apt://some-<wbr></wbr>package</a></p>') |
| 153 | + 'href="apt://some-package">apt://some-<wbr />package</a></p>') |
| 154 | self.assertEqual(expected_html, html) |
| 155 | |
| 156 | def test_file_is_not_linked(self): |
| 157 | @@ -253,7 +253,7 @@ |
| 158 | html = FormattersAPI(test_string).text_to_html() |
| 159 | expected_html = ( |
| 160 | "<p>This doesn't become a link: " |
| 161 | - "file://<wbr></wbr>some/file.<wbr></wbr>txt</p>") |
| 162 | + "file://<wbr />some/file.<wbr />txt</p>") |
| 163 | self.assertEqual(expected_html, html) |
| 164 | |
| 165 | def test_data_is_linked(self): |
| 166 | @@ -263,7 +263,7 @@ |
| 167 | "<p>This becomes a link: " |
| 168 | '<a rel="nofollow" ' |
| 169 | 'href="data:text/plain,test">' |
| 170 | - 'data:text/<wbr></wbr>plain,test</a></p>') |
| 171 | + 'data:text/<wbr />plain,test</a></p>') |
| 172 | self.assertEqual(expected_html, html) |
| 173 | |
| 174 | def test_no_link_with_linkify_text_false(self): |
| 175 | |
| 176 | === modified file 'lib/lp/app/doc/displaying-paragraphs-of-text.txt' |
| 177 | --- lib/lp/app/doc/displaying-paragraphs-of-text.txt 2011-12-29 05:29:36 +0000 |
| 178 | +++ lib/lp/app/doc/displaying-paragraphs-of-text.txt 2012-04-02 11:42:25 +0000 |
| 179 | @@ -85,7 +85,7 @@ |
| 180 | <p>This is a code sample written in Python.<br /> |
| 181 | def messageCount(self):<br /> |
| 182 | """See IRosettaStats."""<br /> |
| 183 | - return self.potemplate<wbr></wbr>.messageCount(<wbr></wbr>)</p> |
| 184 | + return self.potemplate<wbr />.messageCount(<wbr />)</p> |
| 185 | <p> def currentCount(self, language=None):<br /> |
| 186 | """See IRosettaStats."""<br /> |
| 187 | return self.currentCount</p> |
| 188 | @@ -103,12 +103,12 @@ |
| 189 | ... 'I have a Jabber account (jabber:foo@jabber.example.com)\n' |
| 190 | ... 'Foo Bar <mailto:foo.bar@example.net>') |
| 191 | >>> print test_tales('foo/fmt:text-to-html', foo=text) |
| 192 | - <p><a rel="nofollow" href="https://launchpad.net/">https:/<wbr></wbr>/launchpad.<wbr></wbr>net/</a> is the new Launchpad site<br /> |
| 193 | - <a rel="nofollow" href="http://example.com/something?foo=bar&hum=baz">http://<wbr></wbr>example.<wbr></wbr>com/something?<wbr></wbr>foo=bar&<wbr></wbr>hum=baz</a><br /> |
| 194 | - You can check the PPC md5sums at <a rel="nofollow" href="ftp://ftp.ubuntu.com/ubuntu/dists/breezy/main/installer-powerpc/current/images/MD5SUMS">ftp://ftp.<wbr></wbr>ubuntu.<wbr></wbr>com/ubuntu/<wbr></wbr>dists/breezy/<wbr></wbr>main/installer-<wbr></wbr>powerpc/<wbr></wbr>current/<wbr></wbr>images/<wbr></wbr>MD5SUMS</a><br /> |
| 195 | - <a rel="nofollow" href="irc://irc.freenode.net/#launchpad">irc://irc.<wbr></wbr>freenode.<wbr></wbr>net/#launchpad</a></p> |
| 196 | - <p>I have a Jabber account (<a rel="nofollow" href="jabber:foo@jabber.example.com">jabber:<wbr></wbr>foo@jabber.<wbr></wbr>example.<wbr></wbr>com</a>)<br /> |
| 197 | - Foo Bar <<a rel="nofollow" href="mailto:foo.bar@example.net">mailto:<wbr></wbr>foo.bar@<wbr></wbr>example.<wbr></wbr>net</a>></p> |
| 198 | + <p><a rel="nofollow" href="https://launchpad.net/">https:/<wbr />/launchpad.<wbr />net/</a> is the new Launchpad site<br /> |
| 199 | + <a rel="nofollow" href="http://example.com/something?foo=bar&hum=baz">http://<wbr />example.<wbr />com/something?<wbr />foo=bar&<wbr />hum=baz</a><br /> |
| 200 | + You can check the PPC md5sums at <a rel="nofollow" href="ftp://ftp.ubuntu.com/ubuntu/dists/breezy/main/installer-powerpc/current/images/MD5SUMS">ftp://ftp.<wbr />ubuntu.<wbr />com/ubuntu/<wbr />dists/breezy/<wbr />main/installer-<wbr />powerpc/<wbr />current/<wbr />images/<wbr />MD5SUMS</a><br /> |
| 201 | + <a rel="nofollow" href="irc://irc.freenode.net/#launchpad">irc://irc.<wbr />freenode.<wbr />net/#launchpad</a></p> |
| 202 | + <p>I have a Jabber account (<a rel="nofollow" href="jabber:foo@jabber.example.com">jabber:<wbr />foo@jabber.<wbr />example.<wbr />com</a>)<br /> |
| 203 | + Foo Bar <<a rel="nofollow" href="mailto:foo.bar@example.net">mailto:<wbr />foo.bar@<wbr />example.<wbr />net</a>></p> |
| 204 | |
| 205 | |
| 206 | URL linkification |
| 207 | @@ -158,43 +158,43 @@ |
| 208 | ... ) |
| 209 | |
| 210 | >>> print test_tales('foo/fmt:text-to-html', foo=text) |
| 211 | - <p><a rel="nofollow" href="http://localhost:8086/bar/baz/foo.html">http://<wbr></wbr>localhost:<wbr></wbr>8086/bar/<wbr></wbr>baz/foo.<wbr></wbr>html</a><br /> |
| 212 | - <a rel="nofollow" href="ftp://localhost:8086/bar/baz/foo.bar.html">ftp://localhost<wbr></wbr>:8086/bar/<wbr></wbr>baz/foo.<wbr></wbr>bar.html</a><br /> |
| 213 | - <a rel="nofollow" href="sftp://localhost:8086/bar/baz/foo.bar.html">sftp://<wbr></wbr>localhost:<wbr></wbr>8086/bar/<wbr></wbr>baz/foo.<wbr></wbr>bar.html</a>.<br /> |
| 214 | - <a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr></wbr>localhost:<wbr></wbr>8086/bar/<wbr></wbr>baz/foo.<wbr></wbr>bar.html</a>;<br /> |
| 215 | - <a rel="nofollow" href="news://localhost:8086/bar/baz/foo.bar.html">news://<wbr></wbr>localhost:<wbr></wbr>8086/bar/<wbr></wbr>baz/foo.<wbr></wbr>bar.html</a>:<br /> |
| 216 | - <a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr></wbr>localhost:<wbr></wbr>8086/bar/<wbr></wbr>baz/foo.<wbr></wbr>bar.html</a>?<br /> |
| 217 | - <a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr></wbr>localhost:<wbr></wbr>8086/bar/<wbr></wbr>baz/foo.<wbr></wbr>bar.html</a>,<br /> |
| 218 | - <<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr></wbr>localhost:<wbr></wbr>8086/bar/<wbr></wbr>baz/foo.<wbr></wbr>bar.html</a>><br /> |
| 219 | - <<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr></wbr>localhost:<wbr></wbr>8086/bar/<wbr></wbr>baz/foo.<wbr></wbr>bar.html</a>>,<br /> |
| 220 | - <<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr></wbr>localhost:<wbr></wbr>8086/bar/<wbr></wbr>baz/foo.<wbr></wbr>bar.html</a>>.<br /> |
| 221 | - <<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr></wbr>localhost:<wbr></wbr>8086/bar/<wbr></wbr>baz/foo.<wbr></wbr>bar.html</a>>;<br /> |
| 222 | - <<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr></wbr>localhost:<wbr></wbr>8086/bar/<wbr></wbr>baz/foo.<wbr></wbr>bar.html</a>>:<br /> |
| 223 | - <<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr></wbr>localhost:<wbr></wbr>8086/bar/<wbr></wbr>baz/foo.<wbr></wbr>bar.html</a>>?<br /> |
| 224 | - (<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr></wbr>localhost:<wbr></wbr>8086/bar/<wbr></wbr>baz/foo.<wbr></wbr>bar.html</a>)<br /> |
| 225 | - (<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr></wbr>localhost:<wbr></wbr>8086/bar/<wbr></wbr>baz/foo.<wbr></wbr>bar.html</a>),<br /> |
| 226 | - (<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr></wbr>localhost:<wbr></wbr>8086/bar/<wbr></wbr>baz/foo.<wbr></wbr>bar.html</a>).<br /> |
| 227 | - (<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr></wbr>localhost:<wbr></wbr>8086/bar/<wbr></wbr>baz/foo.<wbr></wbr>bar.html</a>);<br /> |
| 228 | - (<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr></wbr>localhost:<wbr></wbr>8086/bar/<wbr></wbr>baz/foo.<wbr></wbr>bar.html</a>):<br /> |
| 229 | - <a rel="nofollow" href="http://localhost/bar/baz/foo.bar.html?a=b&b=a">http://<wbr></wbr>localhost/<wbr></wbr>bar/baz/<wbr></wbr>foo.bar.<wbr></wbr>html?a=<wbr></wbr>b&b=a</a><br /> |
| 230 | - <a rel="nofollow" href="http://localhost/bar/baz/foo.bar.html?a=b&b=a">http://<wbr></wbr>localhost/<wbr></wbr>bar/baz/<wbr></wbr>foo.bar.<wbr></wbr>html?a=<wbr></wbr>b&b=a</a>.<br /> |
| 231 | - <a rel="nofollow" href="http://localhost/bar/baz/foo.bar.html?a=b&b=a">http://<wbr></wbr>localhost/<wbr></wbr>bar/baz/<wbr></wbr>foo.bar.<wbr></wbr>html?a=<wbr></wbr>b&b=a</a>,<br /> |
| 232 | - <a rel="nofollow" href="http://localhost/bar/baz/foo.bar.html?a=b&b=a">http://<wbr></wbr>localhost/<wbr></wbr>bar/baz/<wbr></wbr>foo.bar.<wbr></wbr>html?a=<wbr></wbr>b&b=a</a>;<br /> |
| 233 | - <a rel="nofollow" href="http://localhost/bar/baz/foo.bar.html?a=b&b=a">http://<wbr></wbr>localhost/<wbr></wbr>bar/baz/<wbr></wbr>foo.bar.<wbr></wbr>html?a=<wbr></wbr>b&b=a</a>:<br /> |
| 234 | - <a rel="nofollow" href="http://localhost/bar/baz/foo.bar.html?a=b&b=a:b;c@d_e%f~g#h,j!k-l+m$n*o'p">http://<wbr></wbr>localhost/<wbr></wbr>bar/baz/<wbr></wbr>foo.bar.<wbr></wbr>html?a=<wbr></wbr>b&b=a:b;<wbr></wbr>c@d_e%f~<wbr></wbr>g#h,j!k-<wbr></wbr>l+m$n*o'<wbr></wbr>p</a><br /> |
| 235 | - <a rel="nofollow" href="http://www.searchtools.com/test/urls/(parens).html">http://<wbr></wbr>www.searchtools<wbr></wbr>.com/test/<wbr></wbr>urls/(parens)<wbr></wbr>.html</a><br /> |
| 236 | - <a rel="nofollow" href="http://www.searchtools.com/test/urls/-dash.html">http://<wbr></wbr>www.searchtools<wbr></wbr>.com/test/<wbr></wbr>urls/-dash.<wbr></wbr>html</a><br /> |
| 237 | - <a rel="nofollow" href="http://www.searchtools.com/test/urls/_underscore.html">http://<wbr></wbr>www.searchtools<wbr></wbr>.com/test/<wbr></wbr>urls/_underscor<wbr></wbr>e.html</a><br /> |
| 238 | - <a rel="nofollow" href="http://www.searchtools.com/test/urls/period.x.html">http://<wbr></wbr>www.searchtools<wbr></wbr>.com/test/<wbr></wbr>urls/period.<wbr></wbr>x.html</a><br /> |
| 239 | - <a rel="nofollow" href="http://www.searchtools.com/test/urls/!exclamation.html">http://<wbr></wbr>www.searchtools<wbr></wbr>.com/test/<wbr></wbr>urls/!exclamati<wbr></wbr>on.html</a><br /> |
| 240 | - <a rel="nofollow" href="http://www.searchtools.com/test/urls/~tilde.html">http://<wbr></wbr>www.searchtools<wbr></wbr>.com/test/<wbr></wbr>urls/~tilde.<wbr></wbr>html</a><br /> |
| 241 | - <a rel="nofollow" href="http://www.searchtools.com/test/urls/*asterisk.html">http://<wbr></wbr>www.searchtools<wbr></wbr>.com/test/<wbr></wbr>urls/*asterisk.<wbr></wbr>html</a><br /> |
| 242 | - <a rel="nofollow" href="irc://irc.freenode.net/launchpad">irc://irc.<wbr></wbr>freenode.<wbr></wbr>net/launchpad</a><br /> |
| 243 | - <a rel="nofollow" href="irc://irc.freenode.net/%23launchpad,isserver">irc://irc.<wbr></wbr>freenode.<wbr></wbr>net/%23launchpa<wbr></wbr>d,isserver</a><br /> |
| 244 | - <a rel="nofollow" href="mailto:noreply@launchpad.net">mailto:<wbr></wbr>noreply@<wbr></wbr>launchpad.<wbr></wbr>net</a><br /> |
| 245 | - <a rel="nofollow" href="jabber:noreply@launchpad.net">jabber:<wbr></wbr>noreply@<wbr></wbr>launchpad.<wbr></wbr>net</a><br /> |
| 246 | - <a rel="nofollow" href="http://localhost/foo?xxx&">http://<wbr></wbr>localhost/<wbr></wbr>foo?xxx&</a><br /> |
| 247 | - <a rel="nofollow" href="http://localhost?testing=[square-brackets-in-query]">http://<wbr></wbr>localhost?<wbr></wbr>testing=<wbr></wbr>[square-<wbr></wbr>brackets-<wbr></wbr>in-query]</a></p> |
| 248 | + <p><a rel="nofollow" href="http://localhost:8086/bar/baz/foo.html">http://<wbr />localhost:<wbr />8086/bar/<wbr />baz/foo.<wbr />html</a><br /> |
| 249 | + <a rel="nofollow" href="ftp://localhost:8086/bar/baz/foo.bar.html">ftp://localhost<wbr />:8086/bar/<wbr />baz/foo.<wbr />bar.html</a><br /> |
| 250 | + <a rel="nofollow" href="sftp://localhost:8086/bar/baz/foo.bar.html">sftp://<wbr />localhost:<wbr />8086/bar/<wbr />baz/foo.<wbr />bar.html</a>.<br /> |
| 251 | + <a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr />localhost:<wbr />8086/bar/<wbr />baz/foo.<wbr />bar.html</a>;<br /> |
| 252 | + <a rel="nofollow" href="news://localhost:8086/bar/baz/foo.bar.html">news://<wbr />localhost:<wbr />8086/bar/<wbr />baz/foo.<wbr />bar.html</a>:<br /> |
| 253 | + <a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr />localhost:<wbr />8086/bar/<wbr />baz/foo.<wbr />bar.html</a>?<br /> |
| 254 | + <a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr />localhost:<wbr />8086/bar/<wbr />baz/foo.<wbr />bar.html</a>,<br /> |
| 255 | + <<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr />localhost:<wbr />8086/bar/<wbr />baz/foo.<wbr />bar.html</a>><br /> |
| 256 | + <<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr />localhost:<wbr />8086/bar/<wbr />baz/foo.<wbr />bar.html</a>>,<br /> |
| 257 | + <<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr />localhost:<wbr />8086/bar/<wbr />baz/foo.<wbr />bar.html</a>>.<br /> |
| 258 | + <<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr />localhost:<wbr />8086/bar/<wbr />baz/foo.<wbr />bar.html</a>>;<br /> |
| 259 | + <<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr />localhost:<wbr />8086/bar/<wbr />baz/foo.<wbr />bar.html</a>>:<br /> |
| 260 | + <<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr />localhost:<wbr />8086/bar/<wbr />baz/foo.<wbr />bar.html</a>>?<br /> |
| 261 | + (<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr />localhost:<wbr />8086/bar/<wbr />baz/foo.<wbr />bar.html</a>)<br /> |
| 262 | + (<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr />localhost:<wbr />8086/bar/<wbr />baz/foo.<wbr />bar.html</a>),<br /> |
| 263 | + (<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr />localhost:<wbr />8086/bar/<wbr />baz/foo.<wbr />bar.html</a>).<br /> |
| 264 | + (<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr />localhost:<wbr />8086/bar/<wbr />baz/foo.<wbr />bar.html</a>);<br /> |
| 265 | + (<a rel="nofollow" href="http://localhost:8086/bar/baz/foo.bar.html">http://<wbr />localhost:<wbr />8086/bar/<wbr />baz/foo.<wbr />bar.html</a>):<br /> |
| 266 | + <a rel="nofollow" href="http://localhost/bar/baz/foo.bar.html?a=b&b=a">http://<wbr />localhost/<wbr />bar/baz/<wbr />foo.bar.<wbr />html?a=<wbr />b&b=a</a><br /> |
| 267 | + <a rel="nofollow" href="http://localhost/bar/baz/foo.bar.html?a=b&b=a">http://<wbr />localhost/<wbr />bar/baz/<wbr />foo.bar.<wbr />html?a=<wbr />b&b=a</a>.<br /> |
| 268 | + <a rel="nofollow" href="http://localhost/bar/baz/foo.bar.html?a=b&b=a">http://<wbr />localhost/<wbr />bar/baz/<wbr />foo.bar.<wbr />html?a=<wbr />b&b=a</a>,<br /> |
| 269 | + <a rel="nofollow" href="http://localhost/bar/baz/foo.bar.html?a=b&b=a">http://<wbr />localhost/<wbr />bar/baz/<wbr />foo.bar.<wbr />html?a=<wbr />b&b=a</a>;<br /> |
| 270 | + <a rel="nofollow" href="http://localhost/bar/baz/foo.bar.html?a=b&b=a">http://<wbr />localhost/<wbr />bar/baz/<wbr />foo.bar.<wbr />html?a=<wbr />b&b=a</a>:<br /> |
| 271 | + <a rel="nofollow" href="http://localhost/bar/baz/foo.bar.html?a=b&b=a:b;c@d_e%f~g#h,j!k-l+m$n*o'p">http://<wbr />localhost/<wbr />bar/baz/<wbr />foo.bar.<wbr />html?a=<wbr />b&b=a:b;<wbr />c@d_e%f~<wbr />g#h,j!k-<wbr />l+m$n*o'<wbr />p</a><br /> |
| 272 | + <a rel="nofollow" href="http://www.searchtools.com/test/urls/(parens).html">http://<wbr />www.searchtools<wbr />.com/test/<wbr />urls/(parens)<wbr />.html</a><br /> |
| 273 | + <a rel="nofollow" href="http://www.searchtools.com/test/urls/-dash.html">http://<wbr />www.searchtools<wbr />.com/test/<wbr />urls/-dash.<wbr />html</a><br /> |
| 274 | + <a rel="nofollow" href="http://www.searchtools.com/test/urls/_underscore.html">http://<wbr />www.searchtools<wbr />.com/test/<wbr />urls/_underscor<wbr />e.html</a><br /> |
| 275 | + <a rel="nofollow" href="http://www.searchtools.com/test/urls/period.x.html">http://<wbr />www.searchtools<wbr />.com/test/<wbr />urls/period.<wbr />x.html</a><br /> |
| 276 | + <a rel="nofollow" href="http://www.searchtools.com/test/urls/!exclamation.html">http://<wbr />www.searchtools<wbr />.com/test/<wbr />urls/!exclamati<wbr />on.html</a><br /> |
| 277 | + <a rel="nofollow" href="http://www.searchtools.com/test/urls/~tilde.html">http://<wbr />www.searchtools<wbr />.com/test/<wbr />urls/~tilde.<wbr />html</a><br /> |
| 278 | + <a rel="nofollow" href="http://www.searchtools.com/test/urls/*asterisk.html">http://<wbr />www.searchtools<wbr />.com/test/<wbr />urls/*asterisk.<wbr />html</a><br /> |
| 279 | + <a rel="nofollow" href="irc://irc.freenode.net/launchpad">irc://irc.<wbr />freenode.<wbr />net/launchpad</a><br /> |
| 280 | + <a rel="nofollow" href="irc://irc.freenode.net/%23launchpad,isserver">irc://irc.<wbr />freenode.<wbr />net/%23launchpa<wbr />d,isserver</a><br /> |
| 281 | + <a rel="nofollow" href="mailto:noreply@launchpad.net">mailto:<wbr />noreply@<wbr />launchpad.<wbr />net</a><br /> |
| 282 | + <a rel="nofollow" href="jabber:noreply@launchpad.net">jabber:<wbr />noreply@<wbr />launchpad.<wbr />net</a><br /> |
| 283 | + <a rel="nofollow" href="http://localhost/foo?xxx&">http://<wbr />localhost/<wbr />foo?xxx&</a><br /> |
| 284 | + <a rel="nofollow" href="http://localhost?testing=[square-brackets-in-query]">http://<wbr />localhost?<wbr />testing=<wbr />[square-<wbr />brackets-<wbr />in-query]</a></p> |
| 285 | |
| 286 | |
| 287 | The fmt:text-to-html formatter leaves a number of non-URIs unlinked: |
| 288 | @@ -203,7 +203,7 @@ |
| 289 | ... 'nothttp://launchpad.net/\n' |
| 290 | ... 'http::No-cache=True\n') |
| 291 | >>> print test_tales('foo/fmt:text-to-html', foo=text) |
| 292 | - <p>nothttp:<wbr></wbr>//launchpad.<wbr></wbr>net/<br /> |
| 293 | + <p>nothttp:<wbr />//launchpad.<wbr />net/<br /> |
| 294 | http::No-cache=True</p> |
| 295 | |
| 296 | |
| 297 | |
| 298 | === modified file 'lib/lp/app/doc/tales-email-formatting.txt' |
| 299 | --- lib/lp/app/doc/tales-email-formatting.txt 2011-06-23 13:10:40 +0000 |
| 300 | +++ lib/lp/app/doc/tales-email-formatting.txt 2012-04-02 11:42:25 +0000 |
| 301 | @@ -122,8 +122,8 @@ |
| 302 | ... '\n') |
| 303 | >>> print test_tales('foo/fmt:email-to-html', |
| 304 | ... foo='\n'.join([python, not_python])) |
| 305 | - <p>>>> tz = pytz.timezone(<wbr></wbr>"Asia/Calcutta"... |
| 306 | - >>> mydate = datetime.<wbr></wbr>datetime(<wbr></wbr>2007, 2, ... |
| 307 | + <p>>>> tz = pytz.timezone(<wbr />"Asia/Calcutta"... |
| 308 | + >>> mydate = datetime.<wbr />datetime(<wbr />2007, 2, ... |
| 309 | 2007-02-18 15:35:00+05:30</p> |
| 310 | <p><span class="foldable-quoted">> This line really is a quoted ... |
| 311 | >>> This does not invoke an exception rule. |
| 312 | @@ -154,11 +154,11 @@ |
| 313 | ... '\n') |
| 314 | >>> print test_tales('foo/fmt:email-to-html', foo=dpkg) |
| 315 | <p>dpkg -l libdvdread3<br /> |
| 316 | - Desired=<wbr></wbr>Unknown/<wbr></wbr>Install/<wbr></wbr>... |
| 317 | - | Status=<wbr></wbr>Not/Installed/<wbr></wbr>Config-<wbr></wbr>... |
| 318 | - |/ Err?=(none)<wbr></wbr>/Hold/Reinst-<wbr></wbr>required/... |
| 319 | + Desired=<wbr />Unknown/<wbr />Install/<wbr />... |
| 320 | + | Status=<wbr />Not/Installed/<wbr />Config-<wbr />... |
| 321 | + |/ Err?=(none)<wbr />/Hold/Reinst-<wbr />required/... |
| 322 | ||/ Name Version Description<br /> |
| 323 | - +++-===<wbr></wbr>=======<wbr></wbr>====-==<wbr></wbr>=======... |
| 324 | + +++-===<wbr />=======<wbr />====-==<wbr />=======... |
| 325 | ii libdvdread3 0.9.7-2ubuntu1 library for reading DVDs</p> |
| 326 | |
| 327 | >>> bad_dpkg = ('When dpkg output is in text, possibly tampered with,\n' |
| 328 | @@ -175,11 +175,11 @@ |
| 329 | ... foo='\n'.join([bad_dpkg])) |
| 330 | <p>When dpkg output is in text, possibly tampered with,<br /> |
| 331 | we must take care to identify '|' quoted passages.<br /> |
| 332 | - $ Desired=<wbr></wbr>Unknown/<wbr></wbr>Install/<wbr></wbr>Remove/... |
| 333 | + $ Desired=<wbr />Unknown/<wbr />Install/<wbr />Remove/... |
| 334 | |<br /> |
| 335 | - Status=<wbr></wbr>Not/Installed/<wbr></wbr>Config-... |
| 336 | - |/ Err?=(none)<wbr></wbr>/Hold/Reinst-<wbr></wbr>required/... |
| 337 | + Status=<wbr />Not/Installed/<wbr />Config-... |
| 338 | + |/ Err?=(none)<wbr />/Hold/Reinst-<wbr />required/... |
| 339 | ||/ Name Version Description<br /> |
| 340 | - +++-===<wbr></wbr>=======<wbr></wbr>====-==<wbr></wbr>=======... |
| 341 | + +++-===<wbr />=======<wbr />====-==<wbr />=======... |
| 342 | ii libdvdread3 0.9.7-2ubuntu1 library for reading DVDs</p> |
| 343 | |
| 344 | |
| 345 | === modified file 'lib/lp/app/doc/tales.txt' |
| 346 | --- lib/lp/app/doc/tales.txt 2011-12-24 17:49:30 +0000 |
| 347 | +++ lib/lp/app/doc/tales.txt 2012-04-02 11:42:25 +0000 |
| 348 | @@ -287,7 +287,7 @@ |
| 349 | |
| 350 | >>> test_tales('foo/fmt:break-long-words', |
| 351 | ... foo='<http://launchpad.net/products/launchpad>') |
| 352 | - '<http:/<wbr></wbr>/launchpad.<wbr></wbr>...<wbr></wbr>launchpad>' |
| 353 | + '<http:/<wbr />/launchpad.<wbr />...<wbr />launchpad>' |
| 354 | |
| 355 | To get a int with its thousands separated by a comma, use fmt:intcomma. |
| 356 | |
| 357 | @@ -924,8 +924,8 @@ |
| 358 | Version: GnuPG v1.4.1 (GNU/Linux)<br /> |
| 359 | Comment: Using GnuPG with Thunderbird<br /> |
| 360 | <br /> |
| 361 | - iD8DBQFED60Y0F+<wbr></wbr>nu1YWqI0RAqrNAJ<wbr></wbr>... |
| 362 | - T2PIWy0CUJsX8RX<wbr></wbr>St/M51WE=<br /> |
| 363 | + iD8DBQFED60Y0F+<wbr />nu1YWqI0RAqrNAJ<wbr />... |
| 364 | + T2PIWy0CUJsX8RX<wbr />St/M51WE=<br /> |
| 365 | =J2S5<br /> |
| 366 | -----END PGP SIGNATURE----- |
| 367 | </span></p> |
| 368 | @@ -942,7 +942,7 @@ |
| 369 | Raise your hand if you can read this.</p> |
| 370 | <p><span class="foldable"...>--<br /> |
| 371 | __C U R T I S C. H O V E Y_______<br /> |
| 372 | - sinzui.<wbr></wbr>is@example.<wbr></wbr>org<br /> |
| 373 | + sinzui.<wbr />is@example.<wbr />org<br /> |
| 374 | Guilty of stealing everything I am. |
| 375 | </span></p> |
| 376 | |
| 377 | @@ -1012,7 +1012,7 @@ |
| 378 | </span></p> |
| 379 | <p><span class="foldable"...>--<br /> |
| 380 | __C U R T I S C. H O V E Y_______<br /> |
| 381 | - sinzui.<wbr></wbr>is@example.<wbr></wbr>org<br /> |
| 382 | + sinzui.<wbr />is@example.<wbr />org<br /> |
| 383 | Guilty of stealing everything I am. |
| 384 | </span></p> |
| 385 | |
| 386 | |
| 387 | === modified file 'lib/lp/blueprints/workitemmigration.py' |
| 388 | --- lib/lp/blueprints/workitemmigration.py 2012-03-22 23:21:24 +0000 |
| 389 | +++ lib/lp/blueprints/workitemmigration.py 2012-04-02 11:42:25 +0000 |
| 390 | @@ -75,7 +75,7 @@ |
| 391 | |
| 392 | def milestone_extract(text, valid_milestones): |
| 393 | words = text.replace('(', ' ').replace(')', ' ').replace( |
| 394 | - '[', ' ').replace(']', ' ').replace('<wbr></wbr>', '').split() |
| 395 | + '[', ' ').replace(']', ' ').replace('<wbr />', '').split() |
| 396 | for milestone in valid_milestones: |
| 397 | for word in words: |
| 398 | if word == milestone.name: |
| 399 | |
| 400 | === modified file 'lib/lp/bugs/stories/bugs/xx-bug-comments-truncated.txt' |
| 401 | --- lib/lp/bugs/stories/bugs/xx-bug-comments-truncated.txt 2012-02-21 22:30:41 +0000 |
| 402 | +++ lib/lp/bugs/stories/bugs/xx-bug-comments-truncated.txt 2012-04-02 11:42:25 +0000 |
| 403 | @@ -191,8 +191,8 @@ |
| 404 | Version: GnuPG v1.4.1 (GNU/Linux)<br /> |
| 405 | Comment: Using GnuPG with Thunderbird<br /> |
| 406 | <br /> |
| 407 | - iD8DBQFED60Y0F+<wbr></wbr>nu1YWqI0RAqrNAJ<wbr></wbr>... |
| 408 | - T2PIWy0CUJsX8RX<wbr></wbr>St/M51WE=<br /> |
| 409 | + iD8DBQFED60Y0F+<wbr />nu1YWqI0RAqrNAJ<wbr />... |
| 410 | + T2PIWy0CUJsX8RX<wbr />St/M51WE=<br /> |
| 411 | =J2S5<br /> |
| 412 | -----END PGP SIGNATURE----- |
| 413 | </span></p> |
| 414 | |
| 415 | === modified file 'lib/lp/registry/browser/tests/person-views.txt' |
| 416 | --- lib/lp/registry/browser/tests/person-views.txt 2012-02-10 19:52:27 +0000 |
| 417 | +++ lib/lp/registry/browser/tests/person-views.txt 2012-04-02 11:42:25 +0000 |
| 418 | @@ -28,7 +28,7 @@ |
| 419 | >>> print view.homepage_content |
| 420 | <p>line one <script></p> |
| 421 | <BLANKLINE> |
| 422 | - <p><a rel="nofollow" href="http://aa.aa/">http://<wbr></wbr>aa.aa/</a></p> |
| 423 | + <p><a rel="nofollow" href="http://aa.aa/">http://<wbr />aa.aa/</a></p> |
| 424 | |
| 425 | Teams are always valid and do not have probation rules; the homepage |
| 426 | content is formatted HTML. |
| 427 | @@ -44,7 +44,7 @@ |
| 428 | >>> print view.homepage_content |
| 429 | <p>line one <script></p> |
| 430 | <BLANKLINE> |
| 431 | - <p><a rel="nofollow" href="http://aa.aa/">http://<wbr></wbr>aa.aa/</a></p> |
| 432 | + <p><a rel="nofollow" href="http://aa.aa/">http://<wbr />aa.aa/</a></p> |
| 433 | |
| 434 | New users are on probation; the homepage content is escaped HTML. |
| 435 | |
| 436 | |
| 437 | === modified file 'lib/lp/registry/stories/announcements/xx-announcements.txt' |
| 438 | --- lib/lp/registry/stories/announcements/xx-announcements.txt 2011-12-20 10:52:02 +0000 |
| 439 | +++ lib/lp/registry/stories/announcements/xx-announcements.txt 2012-04-02 11:42:25 +0000 |
| 440 | @@ -764,7 +764,7 @@ |
| 441 | Newline="<br /> |
| 442 | "<br /> |
| 443 | url="<a rel="nofollow" |
| 444 | - href="http://www.ubuntu.com">http://<wbr></wbr>www.ubuntu.<wbr></wbr>com</a>"... |
| 445 | + href="http://www.ubuntu.com">http://<wbr />www.ubuntu.<wbr />com</a>"... |
| 446 | |
| 447 | |
| 448 | Deletion |

Seems ok, so long as an XXX is added for the BeautifulSoup workaround.