Merge "Links created by Linker::makeExternalLink didn't include rel=nofollow"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Mon, 21 Jan 2013 22:33:07 +0000 (22:33 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Mon, 21 Jan 2013 22:33:07 +0000 (22:33 +0000)
1  2 
includes/Linker.php
tests/parser/parserTests.txt

diff --combined includes/Linker.php
@@@ -947,10 -947,10 +947,10 @@@ class Linker 
                        return '<a href="' . htmlspecialchars( $href ) . '" class="new" title="' .
                                htmlspecialchars( $title->getPrefixedText(), ENT_QUOTES ) . '">' .
                                $encLabel . '</a>';
 -              } else {
 -                      wfProfileOut( __METHOD__ );
 -                      return self::linkKnown( $title, $encLabel, array(), wfCgiToArray( $query ) );
                }
 +
 +              wfProfileOut( __METHOD__ );
 +              return self::linkKnown( $title, $encLabel, array(), wfCgiToArray( $query ) );
        }
  
        /**
         * @param $escape Boolean: do we escape the link text?
         * @param $linktype String: type of external link. Gets added to the classes
         * @param $attribs Array of extra attributes to <a>
+        * @param $title Title|null Title object used for title specific link attributes
         * @return string
         */
-       public static function makeExternalLink( $url, $text, $escape = true, $linktype = '', $attribs = array() ) {
+       public static function makeExternalLink( $url, $text, $escape = true, $linktype = '', $attribs = array(), $title = null ) {
+               global $wgTitle;
                $class = "external";
                if ( $linktype ) {
                        $class .= " $linktype";
                if ( $escape ) {
                        $text = htmlspecialchars( $text );
                }
+               if ( !$title ) {
+                       $title = $wgTitle;
+               }
+               $attribs['rel'] = Parser::getExternalLinkRel( $url, $title );
                $link = '';
                $success = wfRunHooks( 'LinkerMakeExternalLink',
                        array( &$url, &$text, &$link, &$attribs, $linktype ) );
        /**
         * This function is called by all recent changes variants, by the page history,
         * and by the user contributions list. It is responsible for formatting edit
 -       * comments. It escapes any HTML in the comment, but adds some CSS to format
 +       * summaries. It escapes any HTML in the summary, but adds some CSS to format
         * auto-generated comments (from section editing) and formats [[wikilinks]].
         *
         * @author Erik Moeller <moeller@scireview.de>
        static $autocommentLocal;
  
        /**
 +       * Converts autogenerated comments in edit summaries into section links.
         * The pattern for autogen comments is / * foo * /, which makes for
         * some nasty regex.
         * We look for all comments, match any text before and after the comment,
        }
  
        /**
 +       * Helper function for Linker::formatAutocomments
         * @param $match
         * @return string
         */
         * changes, so this allows sysops to combat a busy vandal without bothering
         * other users.
         *
 +       * If the option verify is set this function will return the link only in case the
 +       * revision can be reverted. Please note that due to performance limitations
 +       * it might be assumed that a user isn't the only contributor of a page while
 +       * (s)he is, which will lead to useless rollback links. Furthermore this wont
 +       * work if $wgShowRollbackEditCount is disabled, so this can only function
 +       * as an additional check.
 +       *
 +       * If the option noBrackets is set the rollback link wont be enclosed in []
 +       *
         * @param $rev Revision object
         * @param $context IContextSource context to use or null for the main context.
 +       * @param $options array
         * @return string
         */
 -      public static function generateRollback( $rev, IContextSource $context = null ) {
 +      public static function generateRollback( $rev, IContextSource $context = null, $options = array( 'verify' ) ) {
                if ( $context === null ) {
                        $context = RequestContext::getMain();
                }
 +              $editCount = false;
 +              if ( in_array( 'verify', $options ) ) {
 +                      $editCount = self::getRollbackEditCount( $rev, true );
 +                      if ( $editCount === false ) {
 +                              return '';
 +                      }
 +              }
 +
 +              $inner = self::buildRollbackLink( $rev, $context, $editCount );
 +
 +              if ( !in_array( 'noBrackets', $options ) ) {
 +                      $inner = $context->msg( 'brackets' )->rawParams( $inner )->plain();
 +              }
 +
 +              return '<span class="mw-rollback-link">' . $inner . '</span>';
 +      }
 +
 +      /**
 +       * This function will return the number of revisions which a rollback
 +       * would revert and, if $verify is set it will verify that a revision
 +       * can be reverted (that the user isn't the only contributor and the
 +       * revision we might rollback to isn't deleted). These checks can only
 +       * function as an additional check as this function only checks against
 +       * the last $wgShowRollbackEditCount edits.
 +       *
 +       * Returns null if $wgShowRollbackEditCount is disabled or false if $verify
 +       * is set and the user is the only contributor of the page.
 +       *
 +       * @param $rev Revision object
 +       * @param $verify Bool Try to verfiy that this revision can really be rolled back
 +       * @return integer|bool|null
 +       */
 +      public static function getRollbackEditCount( $rev, $verify ) {
 +              global $wgShowRollbackEditCount;
 +              if ( !is_int( $wgShowRollbackEditCount ) || !$wgShowRollbackEditCount > 0 ) {
 +                      // Nothing has happened, indicate this by returning 'null'
 +                      return null;
 +              }
 +
 +              $dbr = wfGetDB( DB_SLAVE );
 +
 +              // Up to the value of $wgShowRollbackEditCount revisions are counted
 +              $res = $dbr->select(
 +                      'revision',
 +                      array( 'rev_user_text', 'rev_deleted' ),
 +                      // $rev->getPage() returns null sometimes
 +                      array( 'rev_page' => $rev->getTitle()->getArticleID() ),
 +                      __METHOD__,
 +                      array(
 +                              'USE INDEX' => array( 'revision' => 'page_timestamp' ),
 +                              'ORDER BY' => 'rev_timestamp DESC',
 +                              'LIMIT' => $wgShowRollbackEditCount + 1
 +                      )
 +              );
 +
 +              $editCount = 0;
 +              $moreRevs = false;
 +              foreach ( $res as $row ) {
 +                      if ( $rev->getRawUserText() != $row->rev_user_text ) {
 +                              if ( $verify && ( $row->rev_deleted & Revision::DELETED_TEXT || $row->rev_deleted & Revision::DELETED_USER ) ) {
 +                                      // If the user or the text of the revision we might rollback to is deleted in some way we can't rollback
 +                                      // Similar to the sanity checks in WikiPage::commitRollback
 +                                      return false;
 +                              }
 +                              $moreRevs = true;
 +                              break;
 +                      }
 +                      $editCount++;
 +              }
  
 -              return '<span class="mw-rollback-link">'
 -                      . $context->msg( 'brackets' )->rawParams(
 -                              self::buildRollbackLink( $rev, $context ) )->plain()
 -                      . '</span>';
 +              if ( $verify && $editCount <= $wgShowRollbackEditCount && !$moreRevs ) {
 +                      // We didn't find at least $wgShowRollbackEditCount revisions made by the current user
 +                      // and there weren't any other revisions. That means that the current user is the only
 +                      // editor, so we can't rollback
 +                      return false;
 +              }
 +              return $editCount;
        }
  
        /**
         *
         * @param $rev Revision object
         * @param $context IContextSource context to use or null for the main context.
 +       * @param $editCount integer Number of edits that would be reverted
         * @return String: HTML fragment
         */
 -      public static function buildRollbackLink( $rev, IContextSource $context = null ) {
 +      public static function buildRollbackLink( $rev, IContextSource $context = null, $editCount = false ) {
                global $wgShowRollbackEditCount, $wgMiserMode;
  
                // To config which pages are effected by miser mode
                }
  
                if( !$disableRollbackEditCount && is_int( $wgShowRollbackEditCount ) && $wgShowRollbackEditCount > 0 ) {
 -                      $dbr = wfGetDB( DB_SLAVE );
 -
 -                      // Up to the value of $wgShowRollbackEditCount revisions are counted
 -                      $res = $dbr->select( 'revision',
 -                              array( 'rev_id', 'rev_user_text' ),
 -                              // $rev->getPage() returns null sometimes
 -                              array( 'rev_page' => $rev->getTitle()->getArticleID() ),
 -                              __METHOD__,
 -                              array(  'USE INDEX' => 'page_timestamp',
 -                                      'ORDER BY' => 'rev_timestamp DESC',
 -                                      'LIMIT' => $wgShowRollbackEditCount + 1 )
 -                      );
 -
 -                      $editCount = 0;
 -                      while( $row = $dbr->fetchObject( $res ) ) {
 -                              if( $rev->getUserText() != $row->rev_user_text ) {
 -                                      break;
 -                              }
 -                              $editCount++;
 +                      if ( !is_numeric( $editCount ) ) {
 +                              $editCount = self::getRollbackEditCount( $rev, false );
                        }
  
                        if( $editCount > $wgShowRollbackEditCount ) {
        /**
         * Returns HTML for the "templates used on this page" list.
         *
 +       * Make an HTML list of templates, and then add a "More..." link at
 +       * the bottom. If $more is null, do not add a "More..." link. If $more
 +       * is a Title, make a link to that title and use it. If $more is a string,
 +       * directly paste it in as the link.
 +       *
         * @param $templates Array of templates from Article::getUsedTemplate
         * or similar
 -       * @param $preview Boolean: whether this is for a preview
 -       * @param $section Boolean: whether this is for a section edit
 +       * @param bool $preview Whether this is for a preview
 +       * @param bool $section Whether this is for a section edit
 +       * @param Title|string|null $more A link for "More..." of the templates
         * @return String: HTML output
         */
 -      public static function formatTemplates( $templates, $preview = false, $section = false ) {
 +      public static function formatTemplates( $templates, $preview = false, $section = false, $more = null ) {
                wfProfileIn( __METHOD__ );
  
                $outText = '';
                                        . wfMessage( 'word-separator' )->escaped()
                                        . $protected . '</li>';
                        }
 +
 +                      if ( $more instanceof Title ) {
 +                              $outText .= '<li>' . self::link( $more, wfMessage( 'moredotdotdot' ) ) . '</li>';
 +                      } elseif ( $more ) {
 +                              $outText .= "<li>$more</li>";
 +                      }
 +
                        $outText .= '</ul>';
                }
 -              wfProfileOut( __METHOD__  );
 +              wfProfileOut( __METHOD__ );
                return $outText;
        }
  
                        }
                        $outText .= '</ul>';
                }
 -              wfProfileOut( __METHOD__  );
 +              wfProfileOut( __METHOD__ );
                return $outText;
        }
  
@@@ -785,24 -785,6 +785,24 @@@ x <div>foo</div> 
  
  !! end
  
 +!! test
 +Empty lines between block tags to test open p-tags are closed between the block tags
 +!! input
 +<div></div>
 +
 +
 +<div></div>a
 +
 +b
 +!! result
 +<div></div>
 +<p><br />
 +</p>
 +<div></div>a
 +<p>b
 +</p>
 +!! end
 +
  ###
  ### Preformatted text
  ###
  
  !!end
  
 +!!test
 +2c. Indent-Pre and tables (bug 42252)
 +!!input
 +{|
 + |+ foo
 + !  | bar
 +|}
 +!!result
 +<table>
 +<caption> foo
 +</caption>
 +<tr>
 +<th> bar
 +</th></tr></table>
 +
 +!!end
 +
  !!test
  3a. Indent-Pre and block tags (single-line html)
  !!input
  
  !!end
  
 +!! test
 +5. White-space in indent-pre
 +NOTE: the white-space char on 2nd line is significant
 +!! input
 + a<br/>
 + 
 + b
 +!! result
 +<pre>a<br />
 +
 +b
 +</pre>
 +!! end
 +
  ###
  ### HTML-pre (some to spec PHP parser behavior and some Parsoid-RT-centric)
  ###
@@@ -2773,45 -2724,6 +2773,45 @@@ A table with nothing but a captio
  
  !! end
  
 +!! test
 +A table with caption with default-spaced attributes and a table row
 +!! input
 +{|
 +|+ style="color: red;" | caption1
 +|-
 +| foo
 +|}
 +!! result
 +<table>
 +<caption style="color: red;"> caption1
 +</caption>
 +<tr>
 +<td> foo
 +</td></tr></table>
 +
 +!! end
 +
 +!! test
 +A table with captions with non-default spaced attributes and a table row
 +!! input
 +{|
 +|+style="color: red;"|caption2
 +|+ style="color: red;"| caption3
 +|-
 +| foo
 +|}
 +!! result
 +<table>
 +<caption style="color: red;">caption2
 +</caption>
 +<caption style="color: red;"> caption3
 +</caption>
 +<tr>
 +<td> foo
 +</td></tr></table>
 +
 +!! end
 +
  !! test
  Table td-cell syntax variations
  !! input
@@@ -3213,29 -3125,6 +3213,29 @@@ disable
  
  !! end
  
 +!! test
 +Wikitext table with a lot of comments
 +!! input
 +{|
 +<!-- c0 -->
 +| foo
 +<!-- c1 -->
 +|- <!-- c2 -->
 +<!-- c3 -->
 +|<!-- c4 -->
 +<!-- c5 -->
 +|}
 +!! result
 +<table>
 +<tr>
 +<td> foo
 +</td></tr>
 +<tr>
 +<td>
 +</td></tr></table>
 +
 +!! end
 +
  ###
  ### Internal links
  ###
@@@ -3320,28 -3209,6 +3320,28 @@@ Link with suffi
  </p>
  !! end
  
 +!! article
 +prefixed article
 +!! text
 +Some text
 +!! endarticle
 +
 +!! test
 +Bug 43661: Piped links with identical prefixes
 +!! input
 +[[prefixed article|prefixed articles with spaces]]
 +
 +[[prefixed article|prefixed articlesaoeu]]
 +
 +[[Main Page|Main Page test]]
 +!! result
 +<p><a href="/wiki/Prefixed_article" title="Prefixed article">prefixed articles with spaces</a>
 +</p><p><a href="/wiki/Prefixed_article" title="Prefixed article">prefixed articlesaoeu</a>
 +</p><p><a href="/wiki/Main_Page" title="Main Page">Main Page test</a>
 +</p>
 +!! end
 +
 +
  !! test
  Link with HTML entity in suffix / tail
  !! input
@@@ -3712,24 -3579,6 +3712,24 @@@ language=ka
  </p>
  !! end
  
 +!! test
 +Parsoid-centric test: Whitespace in ext- and wiki-links should be preserved
 +!! input
 +[[Foo|  bar]]
 +
 +[[Foo|  ''bar'']]
 +
 +[http://wp.org   foo]
 +
 +[http://wp.org   ''foo'']
 +!! result
 +<p><a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">  bar</a>
 +</p><p><a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">  <i>bar</i></a>
 +</p><p><a rel="nofollow" class="external text" href="http://wp.org">foo</a>
 +</p><p><a rel="nofollow" class="external text" href="http://wp.org"><i>foo</i></a>
 +</p>
 +!! end
 +
  ###
  ### Interwiki links (see maintenance/interwiki.sql)
  ###
@@@ -4192,54 -4041,6 +4192,54 @@@ Nested lists 8 (multiple nesting transi
  
  !! end
  
 +!! test
 +Unbalanced closing block tags break a list
 +(Disabled since php parser generates broken html -- relies on Tidy to fix up)
 +!! options
 +disabled
 +!! input
 +<div>
 +*a</div><div>
 +*b</div>
 +!! result
 +<div>
 +<ul><li>a
 +</li></ul></div><div>
 +<ul><li>b
 +</li></ul></div>
 +!! end
 +
 +!! test
 +Unbalanced closing non-block tags don't break a list
 +(Disabled since php parser generates broken html -- relies on Tidy to fix up)
 +!! options
 +disabled
 +!! input
 +<span>
 +*a</span><span>
 +*b</span>
 +!! result
 +<p><span></span>
 +</p>
 +<ul><li>a<span></span>
 +</li><li>b
 +</li></ul>
 +!! end
 +
 +!! test
 +Unclosed formatting tags that straddle lists are closed and reopened
 +(Disabled since php parser generates broken html -- relies on Tidy to fix up)
 +!! options
 +disabled
 +!! input
 +# <s> a
 +# b </s>
 +!! result
 +<ol><li> <s> a </s>
 +</li><li> <s> b </s>
 +</li></ol>
 +!! end
 +
  !! test
  List items are not parsed correctly following a <pre> block (bug 785)
  !! input
@@@ -4729,7 -4530,7 +4729,7 @@@ Magic links: RFC (bug 479
  !! input
  RFC 822
  !! result
- <p><a class="external mw-magiclink-rfc" href="//tools.ietf.org/html/rfc822">RFC 822</a>
+ <p><a class="external mw-magiclink-rfc" rel="nofollow" href="//tools.ietf.org/html/rfc822">RFC 822</a>
  </p>
  !! end
  
@@@ -4747,7 -4548,7 +4747,7 @@@ Magic links: PMID incorrectly converts 
  !! input
  PMID 1234
  !! result
- <p><a class="external mw-magiclink-pmid" href="//www.ncbi.nlm.nih.gov/pubmed/1234?dopt=Abstract">PMID 1234</a>
+ <p><a class="external mw-magiclink-pmid" rel="nofollow" href="//www.ncbi.nlm.nih.gov/pubmed/1234?dopt=Abstract">PMID 1234</a>
  </p>
  !! end
  
@@@ -5054,14 -4855,8 +5054,14 @@@ Main Pag
  Template as link source
  !! input
  [[{{linktest2}}]]
 +
 +[[{{linktest2}}|Main Page]]
 +
 +[[{{linktest2}}]]Page
  !! result
  <p><a href="/wiki/Main_Page" title="Main Page">Main Page</a>
 +</p><p><a href="/wiki/Main_Page" title="Main Page">Main Page</a>
 +</p><p><a href="/wiki/Main_Page" title="Main Page">Main Page</a>Page
  </p>
  !! end
  
@@@ -5575,23 -5370,8 +5575,23 @@@ Templates: Links: 2. Generation of lin
  Templates: Links: 3. Generation of part of a link href
  !!input
  [[Fo{{echo|o}}|bar]]
 +
 +[[Foo{{echo|bar}}]]
 +
 +[[Foo{{echo|bar}}baz]]
 +
 +[[Foo{{echo|bar}}|bar]]
 +
 +[[:Foo{{echo|bar}}]]
 +
 +[[:Foo{{echo|bar}}|bar]]
  !!result
  <p><a href="/index.php?title=Foo&amp;action=edit&amp;redlink=1" class="new" title="Foo (page does not exist)">bar</a>
 +</p><p><a href="/index.php?title=Foobar&amp;action=edit&amp;redlink=1" class="new" title="Foobar (page does not exist)">Foobar</a>
 +</p><p><a href="/index.php?title=Foobarbaz&amp;action=edit&amp;redlink=1" class="new" title="Foobarbaz (page does not exist)">Foobarbaz</a>
 +</p><p><a href="/index.php?title=Foobar&amp;action=edit&amp;redlink=1" class="new" title="Foobar (page does not exist)">bar</a>
 +</p><p><a href="/index.php?title=Foobar&amp;action=edit&amp;redlink=1" class="new" title="Foobar (page does not exist)">Foobar</a>
 +</p><p><a href="/index.php?title=Foobar&amp;action=edit&amp;redlink=1" class="new" title="Foobar (page does not exist)">bar</a>
  </p>
  !!end
  
@@@ -5914,7 -5694,7 +5914,7 @@@ disable
  |bar
  |}
  !!result
 -<table data-parsoid="{&quot;src&quot;:&quot;{|\n|{{echo|foo&lt;/table&gt;}}\n|bar\n|}&quot;}" about="#mwt1" typeof="mw:Object/Template ">
 +<table  about="#mwt1" typeof="mw:Object/Template ">
  <tbody><tr><td>foo</td></tr></tbody></table><span about="#mwt1">
  bar</span><span about="#mwt1">
  </span>
@@@ -5946,14 -5726,14 +5946,14 @@@ disable
    </tr>
  </table>
  !!result
 -<table data-parsoid="{&quot;src&quot;:&quot;&lt;table&gt;\n  &lt;tr&gt;\n    &lt;td&gt;\n    &lt;table&gt;\n      &lt;tr&gt;\n        &lt;td&gt;1. {{echo|foo &lt;/table&gt;}}&lt;/td&gt;\n        &lt;td&gt; bar &lt;/td&gt;\n        &lt;td&gt;2. {{echo|baz &lt;/table&gt;}}&lt;/td&gt;\n      &lt;/tr&gt;\n      &lt;tr&gt;\n        &lt;td&gt;abc&lt;/td&gt;\n      &lt;/tr&gt;\n    &lt;/table&gt;\n    &lt;/td&gt;\n  &lt;/tr&gt;\n  &lt;tr&gt;\n    &lt;td&gt;xyz&lt;/td&gt;\n  &lt;/tr&gt;\n&lt;/table&gt;&quot;}" about="#mwt1" typeof="mw:Object/Template">
 -  <tbody><tr data-parsoid="{&quot;stx&quot;:&quot;html&quot;}">
 -    <td data-parsoid="{&quot;stx&quot;:&quot;html&quot;}">
 -    <table data-parsoid="{&quot;stx&quot;:&quot;html&quot;}">
 -      <tbody><tr data-parsoid="{&quot;stx&quot;:&quot;html&quot;}">
 -        <td data-parsoid="{&quot;stx&quot;:&quot;html&quot;}">1. foo </td></tr></tbody></table></td>
 -        <td data-parsoid="{&quot;stx&quot;:&quot;html&quot;}"> bar </td>
 -        <td data-parsoid="{&quot;stx&quot;:&quot;html&quot;}">2. baz </td></tr></tbody></table><span about="#mwt1">
 +<table  about="#mwt1" typeof="mw:Object/Template">
 +  <tbody><tr >
 +    <td >
 +    <table >
 +      <tbody><tr >
 +        <td >1. foo </td></tr></tbody></table></td>
 +        <td > bar </td>
 +        <td >2. baz </td></tr></tbody></table><span about="#mwt1">
        </span><span about="#mwt1">
        
          abc</span><span about="#mwt1">
  </span>
  !!end
  
 +!! test
 +Templates: Ugly templates: 3. newline-only template parameter
 +!! input
 +foo {{echo|
 +}}
 +!! result
 +<p>foo 
 +</p>
 +!! end
 +
 +# This looks like a bug: a single newline triggers p/br for some reason.
 +!! test
 +Templates: Ugly templates: 4. newline-only template parameter inconsistency
 +!! input
 +{{echo|
 +}}
 +!! result
 +<p><br />
 +</p>
 +!! end
 +
 +
  !!test
  Parser Functions: 1. Simple example
  !!input
@@@ -6907,7 -6665,7 +6907,7 @@@ BUG 1887: A RFC with a thumbnai
  !! input
  [[Image:foobar.jpg|thumb|This is RFC 12354]]
  !! result
- <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is <a class="external mw-magiclink-rfc" href="//tools.ietf.org/html/rfc12354">RFC 12354</a></div></div></div>
+ <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="" /></a></div>This is <a class="external mw-magiclink-rfc" rel="nofollow" href="//tools.ietf.org/html/rfc12354">RFC 12354</a></div></div></div>
  
  !! end
  
@@@ -7747,10 -7505,6 +7747,10 @@@ Namespaced link must have a title (bad 
  !!end
  
  
 +###
 +### HTML tags and HTML attributes
 +###
 +
  !! test
  div with no attributes
  !! input
@@@ -7809,18 -7563,6 +7809,18 @@@ disable
  
  !! end
  
 +# The PHP parser escapes the opening brace to &#123; for some reason, so
 +# disabled this test for it.
 +!! test
 +div with braces in attribute value
 +!! options
 +disabled
 +!! input
 +<div title="{}">Foo</div>
 +!! result
 +<div title="{}">Foo</div>
 +!! end
 +
  # This it very inconsistent in the PHP parser: it returns 
  # class="class" if there is a space between the name and the equal sign (see
  # 'div with empty attribute value, space before equals'), but strips the
@@@ -7907,15 -7649,6 +7907,15 @@@ I always thought &eacute; was a cute le
  </p>
  !! end
  
 +!! test
 +text with entity-escaped character entity-like string: eacute
 +!! input
 +I always thought &amp;eacute; was a cute letter.
 +!! result
 +<p>I always thought &amp;eacute; was a cute letter.
 +</p>
 +!! end
 +
  !! test
  text with undefined character entity: xacute
  !! input
@@@ -10517,7 -10250,7 +10517,7 @@@ Double RF
  !! input
  RFC RFC 1234
  !! result
- <p>RFC <a class="external mw-magiclink-rfc" href="//tools.ietf.org/html/rfc1234">RFC 1234</a>
+ <p>RFC <a class="external mw-magiclink-rfc" rel="nofollow" href="//tools.ietf.org/html/rfc1234">RFC 1234</a>
  </p>
  !! end
  
@@@ -10535,7 -10268,7 +10535,7 @@@ RFC code coverag
  !! input
  RFC   983&#x20;987
  !! result
- <p><a class="external mw-magiclink-rfc" href="//tools.ietf.org/html/rfc983">RFC 983</a>&#x20;987
+ <p><a class="external mw-magiclink-rfc" rel="nofollow" href="//tools.ietf.org/html/rfc983">RFC 983</a>&#x20;987
  </p>
  !! end
  
@@@ -11067,29 -10800,6 +11067,29 @@@ language=sr ca
  !! end
  
  
 +!! article
 +Category:分类
 +!! text
 +blah
 +!! endarticle
 +
 +!! article
 +Category:分類
 +!! text
 +blah
 +!! endarticle
 +
 +!! test
 +Don't convert blue categorylinks to another variant (bug 33210)
 +!! options
 +language=zh cat
 +!! input
 +[[A]][[Category:分类]]
 +!! result
 +<a href="/wiki/Category:%E5%88%86%E7%B1%BB" title="Category:分类">分类</a>
 +!! end
 +
 +
  !! test
  Stripping -{}- tags (language variants)
  !! options
@@@ -11162,20 -10872,6 +11162,20 @@@ language=zh variant=zh-t
  !! end
  
  
 +!! test
 +Conversion around HTML tags
 +!! options
 +language=sr variant=sr-ec
 +!! input
 +-{H|span=>sr-ec:script;title=>sr-ec:src;}-
 +<span title="La-{sr-el:L;sr-ec:C;}-tin">ski</span>
 +!! result
 +<p>
 +<span title="ЛаCтин">ски</span>
 +</p>
 +!! end
 +
 +
  !! test
  Explicit session-wise language variant mapping (A flag and - flag)
  !! options
  </p>
  !! end
  
 +!! test
 +Recursive conversion of alt and title attrs shouldn't clear converter state
 +!! options
 +language=zh variant=zh-cn showtitle
 +!! input
 +-{H|zh-cn:Exclamation;zh-tw:exclamation;}-
 +Should be stripped-{T|zh-cn:China;zh-tw:Taiwan}-<span title="exclamation">!</span>
 +!! result
 +China
 +<p>
 +Should be stripped<span title="Exclamation">!</span>
 +</p>
 +!! end
 +
  !! test
  Bug 24072: more test on conversion rule for title
  !! options
@@@ -13260,23 -12942,6 +13260,23 @@@ disable
  </tbody></table>
  !! end
  
 +!! test
 +Tables: 4d. No escaping needed
 +!! input
 +{|
 +||+1
 +||-2
 +|}
 +!! result
 +<table>
 +<tr>
 +<td>+1
 +</td>
 +<td>-2
 +</td></tr></table>
 +
 +!! end
 +
  #### --------------- Links ---------------
  #### 1. Quote marks in link text
  #### 2. Wikilinks: Escapes needed
@@@ -13291,7 -12956,7 +13291,7 @@@ disable
  !! input
  [[Foo|<nowiki>Foo''boo''</nowiki>]]
  !! result
 -<a rel="mw:WikiLink" href="Foo" data-parsoid="{&quot;tsr&quot;:[0,7],&quot;contentPos&quot;:[5,5],&quot;src&quot;:&quot;[[Foo]]&quot;,&quot;bsp&quot;:[0,7],&quot;stx&quot;:&quot;simple&quot;}">Foo''boo''</a>
 +<a rel="mw:WikiLink" href="Foo">Foo''boo''</a>
  !! end
  
  !! test
@@@ -13533,23 -13198,6 +13533,23 @@@ disable
  </p>
  !! end
  
 +!! test
 +HTML tag with necessary entities in attributes
 +!! input
 +<span title="&amp;amp;">foo</span>
 +!! result
 +<p><span title="&amp;amp;">foo</span>
 +</p>
 +!! end
 +
 +!! test
 +HTML tag with 'unnecessary' entity encoding in attributes
 +!! input
 +<span title="&amp;">foo</span>
 +!! result
 +<p><span title="&amp;">foo</span>
 +</p>
 +!! end
  
  TODO:
  more images