Drop support for XHTML 1.0
authorDaniel Friesen <daniel@nadir-seen-fire.com>
Fri, 10 May 2013 04:04:33 +0000 (21:04 -0700)
committerDaniel Friesen <daniel@nadir-seen-fire.com>
Thu, 16 May 2013 06:09:25 +0000 (23:09 -0700)
* $wgHtml5 = false; is now ignored completely.
* $wgDocType and $wgDTD have been removed.
* $wgXhtmlDefaultNamespace is now ignored.
* XHTML5 will be output if $wgMimeType is set to an XML mime type (according to HTML5's rules).
* For backwards compatibility with extensions $wgHtml5 and $wgXhtmlDefaultNamespace are set
  in Setup.php but depending on them is deprecated.

Change-Id: Iad9634e2ee420b5a3bbffe550421fde4fa1819b0

21 files changed:
RELEASE-NOTES-1.22
includes/DefaultSettings.php
includes/GlobalFunctions.php
includes/Html.php
includes/OutputHandler.php
includes/OutputPage.php
includes/PHPVersionError.php
includes/Sanitizer.php
includes/Setup.php
includes/SkinTemplate.php
includes/User.php
includes/parser/Parser.php
includes/templates/NoLocalSettings.php
languages/messages/MessagesEn.php
maintenance/fuzz-tester.php
maintenance/renderDump.php
tests/phpunit/includes/HtmlTest.php
tests/phpunit/includes/SanitizerTest.php
tests/phpunit/includes/XmlSelectTest.php
tests/phpunit/includes/XmlTest.php
tests/phpunit/includes/parser/NewParserTest.php

index 6b66ce0..f9866f8 100644 (file)
@@ -18,6 +18,11 @@ production.
 * $wgCascadingRestrictionLevels was added.
 * ftps, ssh, sftp, xmpp, sip, sips, tel, sms, bitcoin, magnet, urn, and geo
   have been whitelisted inside of $wgUrlProtocols.
+* $wgDocType and $wgDTD have been removed and are no longer used for the DOCTYPE.
+* $wgHtml5 is no longer used by core. Setting it to false will no longer disable HTML5.
+  It is still set to true for extension compatibility but doing so in extensions is deprecated.
+* $wgXhtmlDefaultNamespace is no longer used by core. Setting it will no longer change the
+  xmlns used by MediaWiki. Reliance on this variable by extensions is deprecated.
 
 === New features in 1.22 ===
 * (bug 44525) mediawiki.jqueryMsg can now parse (whitelisted) HTML elements and attributes.
@@ -72,6 +77,8 @@ production.
   uses ES5 getter/setter to emit a warning when they are used.
 * $wgCascadingRestrictionLevels was added, allowing one to specify restriction levels
   which can be cascading (previously 'sysop' was hard-coded as the only one).
+* XHTML5 support has been improved. If you set $wgMimeType = 'application/xhtml+xml'
+  MediaWiki will try outputting markup acording to XHTML5 rules.
 
 === Bug fixes in 1.22 ===
 * Disable Special:PasswordReset when $wgEnableEmail is false. Previously one
@@ -155,6 +162,7 @@ changes to languages because of Bugzilla reports.
   user ID, or file name.  The old Special:Filepath page was reimplemented
   to redirect through Special:Redirect.
 * Monobook: Removed the old conditional stylesheets for Opera 6, 7 and 9.
+* Support for XHTML 1.0 has been removed. MediaWiki now only outputs (X)HTML5.
 
 == Compatibility ==
 
index 296b71d..2cb0a36 100644 (file)
@@ -2518,48 +2518,36 @@ $wgLocalTZoffset = null;
 $wgMimeType = 'text/html';
 
 /**
- * The content type used in script tags.  This is mostly going to be ignored if
- * $wgHtml5 is true, at least for actual HTML output, since HTML5 doesn't
- * require a MIME type for JavaScript or CSS (those are the default script and
- * style languages).
+ * The content type used in script tags.  This is mostly going to be ignored at
+ * least for actual HTML output, since HTML5 doesn't require a MIME type for
+ * JavaScript or CSS (those are the default script and style languages).
  */
 $wgJsMimeType = 'text/javascript';
 
 /**
- * The HTML document type.  Ignored if $wgHtml5 is true, since <!DOCTYPE html>
- * doesn't actually have a doctype part to put this variable's contents in.
- */
-$wgDocType = '-//W3C//DTD XHTML 1.0 Transitional//EN';
-
-/**
- * The URL of the document type declaration.  Ignored if $wgHtml5 is true,
- * since HTML5 has no DTD, and <!DOCTYPE html> doesn't actually have a DTD part
- * to put this variable's contents in.
- */
-$wgDTD = 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd';
-
-/**
- * The default xmlns attribute.  Ignored if $wgHtml5 is true (or it's supposed
- * to be), since we don't currently support XHTML5, and in HTML5 (i.e., served
- * as text/html) the attribute has no effect, so why bother?
+ * The default xmlns attribute. The option to define this has been removed.
+ * The value of this variable is no longer used by core and is set to a fixed
+ * value in Setup.php for compatibility with extensions that depend on the value
+ * of this variable being set. Such a dependency however is deprecated.
+ * @deprecated since 1.22
  */
-$wgXhtmlDefaultNamespace = 'http://www.w3.org/1999/xhtml';
+$wgXhtmlDefaultNamespace = null;
 
 /**
- * Should we output an HTML5 doctype?  If false, use XHTML 1.0 Transitional
- * instead, and disable HTML5 features.  This may eventually be removed and set
- * to always true.  If it's true, a number of other settings will be irrelevant
- * and have no effect.
+ * Previously used to determine if we should output an HTML5 doctype.
+ * This is no longer used as we always output HTML5 now. For compatibility with
+ * extensions that still check the value of this config it's value is now forced
+ * to true by Setup.php.
+ * @deprecated since 1.22
  */
 $wgHtml5 = true;
 
 /**
  * Defines the value of the version attribute in the &lt;html&gt; tag, if any.
- * This is ignored if $wgHtml5 is false.  If $wgAllowRdfaAttributes and
- * $wgHtml5 are both true, and this evaluates to boolean false (like if it's
- * left at the default null value), it will be auto-initialized to the correct
- * value for RDFa+HTML5.  As such, you should have no reason to ever actually
- * set this to anything.
+ * If $wgAllowRdfaAttributes is true, and this evaluates to boolean false
+ * (like if it's left at the default null value), it will be auto-initialized
+ * to the correct value for RDFa+HTML5.  As such, you should have no reason to
+ * ever actually set this to anything.
  */
 $wgHtml5Version = null;
 
@@ -2570,7 +2558,7 @@ $wgHtml5Version = null;
 $wgAllowRdfaAttributes = false;
 
 /**
- * Enabled HTML5 microdata attributes for use in wikitext, if $wgHtml5 is also true.
+ * Enabled HTML5 microdata attributes for use in wikitext.
  */
 $wgAllowMicrodataAttributes = false;
 
@@ -2604,8 +2592,7 @@ $wgWellFormedXml = true;
  * Normally we wouldn't have to define this in the root "<html>"
  * element, but IE needs it there in some circumstances.
  *
- * This is ignored if $wgHtml5 is true, for the same reason as
- * $wgXhtmlDefaultNamespace.
+ * This is ignored if $wgMimeType is set to a non-XML mimetype.
  */
 $wgXhtmlNamespaces = array();
 
index 5c45577..78fcb8b 100644 (file)
@@ -1674,7 +1674,7 @@ function wfMsgExt( $key, $options ) {
 
 /**
  * Since wfMsg() and co suck, they don't return false if the message key they
- * looked up didn't exist but a XHTML string, this function checks for the
+ * looked up didn't exist but instead the key wrapped in <>'s, this function checks for the
  * nonexistence of messages by checking the MessageCache::get() result directly.
  *
  * @deprecated since 1.18. Use Message::isDisabled().
index cb082a1..e7455b7 100644 (file)
@@ -36,8 +36,8 @@
  *
  * There are two important configuration options this class uses:
  *
- * $wgHtml5: If this is set to false, then all output should be valid XHTML 1.0
- *     Transitional.
+ * $wgMimeType: If this is set to an xml mimetype then output should be
+ *     valid XHTML5.
  * $wgWellFormedXml: If this is set to true, then all output should be
  *     well-formed XML (quotes on attributes, self-closing tags, etc.).
  *
@@ -101,19 +101,6 @@ class Html {
                'itemscope',
        );
 
-       private static $HTMLFiveOnlyAttribs = array(
-               'autocomplete',
-               'autofocus',
-               'max',
-               'min',
-               'multiple',
-               'pattern',
-               'placeholder',
-               'required',
-               'step',
-               'spellcheck',
-       );
-
        /**
         * Returns an HTML element in a string.  The major advantage here over
         * manually typing out the HTML is that it will escape all attribute
@@ -177,7 +164,7 @@ class Html {
         * @return string
         */
        public static function openElement( $element, $attribs = array() ) {
-               global $wgHtml5, $wgWellFormedXml;
+               global $wgWellFormedXml;
                $attribs = (array)$attribs;
                // This is not required in HTML5, but let's do it anyway, for
                // consistency and better compression.
@@ -204,36 +191,28 @@ class Html {
                                'image',
                                'reset',
                                'button',
-                       );
 
-                       // Allow more input types in HTML5 mode
-                       if ( $wgHtml5 ) {
-                               $validTypes = array_merge( $validTypes, array(
-                                       'datetime',
-                                       'datetime-local',
-                                       'date',
-                                       'month',
-                                       'time',
-                                       'week',
-                                       'number',
-                                       'range',
-                                       'email',
-                                       'url',
-                                       'search',
-                                       'tel',
-                                       'color',
-                               ) );
-                       }
+                               // HTML input types
+                               'datetime',
+                               'datetime-local',
+                               'date',
+                               'month',
+                               'time',
+                               'week',
+                               'number',
+                               'range',
+                               'email',
+                               'url',
+                               'search',
+                               'tel',
+                               'color',
+                       );
                        if ( isset( $attribs['type'] )
                        && !in_array( $attribs['type'], $validTypes ) ) {
                                unset( $attribs['type'] );
                        }
                }
 
-               if ( !$wgHtml5 && $element == 'textarea' && isset( $attribs['maxlength'] ) ) {
-                       unset( $attribs['maxlength'] );
-               }
-
                // According to standard the default type for <button> elements is "submit".
                // Depending on compatibility mode IE might use "button", instead.
                // We enforce the standard "submit".
@@ -294,12 +273,6 @@ class Html {
         * @return array An array of attributes functionally identical to $attribs
         */
        private static function dropDefaults( $element, $attribs ) {
-               // Don't bother doing anything if we aren't outputting HTML5; it's too
-               // much of a pain to maintain two sets of defaults.
-               global $wgHtml5;
-               if ( !$wgHtml5 ) {
-                       return $attribs;
-               }
 
                // Whenever altering this array, please provide a covering test case
                // in HtmlTest::provideElementsWithAttributesHavingDefaultValues
@@ -444,7 +417,7 @@ class Html {
         *   (starting with a space if at least one attribute is output)
         */
        public static function expandAttributes( $attribs ) {
-               global $wgHtml5, $wgWellFormedXml;
+               global $wgWellFormedXml;
 
                $ret = '';
                $attribs = (array)$attribs;
@@ -460,15 +433,10 @@ class Html {
                                $key = $value;
                        }
 
-                       // Not technically required in HTML5, but required in XHTML 1.0,
-                       // and we'd like consistency and better compression anyway.
+                       // Not technically required in HTML5 but we'd like consistency
+                       // and better compression anyway.
                        $key = strtolower( $key );
 
-                       // Here we're blacklisting some HTML5-only attributes...
-                       if ( !$wgHtml5 && in_array( $key, self::$HTMLFiveOnlyAttribs ) ) {
-                               continue;
-                       }
-
                        // Bug 23769: Blacklist all form validation attributes for now.  Current
                        // (June 2010) WebKit has no UI, so the form just refuses to submit
                        // without telling the user why, which is much worse than failing
@@ -552,15 +520,12 @@ class Html {
                        }
 
                        if ( in_array( $key, self::$boolAttribs ) ) {
-                               // In XHTML 1.0 Transitional, the value needs to be equal to the
-                               // key.  In HTML5, we can leave the value empty instead.  If we
-                               // don't need well-formed XML, we can omit the = entirely.
+                               // In HTML5, we can leave the value empty. If we don't need
+                               // well-formed XML, we can omit the = entirely.
                                if ( !$wgWellFormedXml ) {
                                        $ret .= " $key";
-                               } elseif ( $wgHtml5 ) {
-                                       $ret .= " $key=\"\"";
                                } else {
-                                       $ret .= " $key=\"$key\"";
+                                       $ret .= " $key=\"\"";
                                }
                        } else {
                                // Apparently we need to entity-encode \n, \r, \t, although the
@@ -602,14 +567,10 @@ class Html {
         * @return string Raw HTML
         */
        public static function inlineScript( $contents ) {
-               global $wgHtml5, $wgJsMimeType, $wgWellFormedXml;
+               global $wgWellFormedXml;
 
                $attrs = array();
 
-               if ( !$wgHtml5 ) {
-                       $attrs['type'] = $wgJsMimeType;
-               }
-
                if ( $wgWellFormedXml && preg_match( '/[<&]/', $contents ) ) {
                        $contents = "/*<![CDATA[*/$contents/*]]>*/";
                }
@@ -625,14 +586,8 @@ class Html {
         * @return string Raw HTML
         */
        public static function linkedScript( $url ) {
-               global $wgHtml5, $wgJsMimeType;
-
                $attrs = array( 'src' => $url );
 
-               if ( !$wgHtml5 ) {
-                       $attrs['type'] = $wgJsMimeType;
-               }
-
                return self::element( 'script', $attrs );
        }
 
@@ -677,8 +632,7 @@ class Html {
 
        /**
         * Convenience function to produce an "<input>" element.  This supports the
-        * new HTML5 input types and attributes, and will silently strip them if
-        * $wgHtml5 is false.
+        * new HTML5 input types and attributes.
         *
         * @param $name    string name attribute
         * @param $value   mixed  value attribute
@@ -712,9 +666,7 @@ class Html {
         * Convenience function to produce an "<input>" element.
         *
         * This supports leaving out the cols= and rows= which Xml requires and are
-        * required by HTML4/XHTML but not required by HTML5 and will silently set
-        * cols="" and rows="" if $wgHtml5 is false and cols and rows are omitted
-        * (HTML4 validates present but empty cols="" and rows="" as valid).
+        * required by HTML4/XHTML but not required by HTML5.
         *
         * @param $name    string name attribute
         * @param $value   string value attribute
@@ -723,20 +675,8 @@ class Html {
         * @return string Raw HTML
         */
        public static function textarea( $name, $value = '', $attribs = array() ) {
-               global $wgHtml5;
-
                $attribs['name'] = $name;
 
-               if ( !$wgHtml5 ) {
-                       if ( !isset( $attribs['cols'] ) ) {
-                               $attribs['cols'] = "";
-                       }
-
-                       if ( !isset( $attribs['rows'] ) ) {
-                               $attribs['rows'] = "";
-                       }
-               }
-
                if ( substr( $value, 0, 1 ) == "\n" ) {
                        // Workaround for bug 12130: browsers eat the initial newline
                        // assuming that it's just for show, but they do keep the later
@@ -859,28 +799,29 @@ class Html {
        public static function htmlHeader( $attribs = array() ) {
                $ret = '';
 
-               global $wgMimeType;
-
-               if ( self::isXmlMimeType( $wgMimeType ) ) {
-                       $ret .= "<?xml version=\"1.0\" encoding=\"UTF-8\" ?" . ">\n";
-               }
+               global $wgHtml5Version, $wgMimeType, $wgXhtmlNamespaces;
 
-               global $wgHtml5, $wgHtml5Version, $wgDocType, $wgDTD;
-               global $wgXhtmlNamespaces, $wgXhtmlDefaultNamespace;
+               $isXHTML = self::isXmlMimeType( $wgMimeType );
 
-               if ( $wgHtml5 ) {
-                       $ret .= "<!DOCTYPE html>\n";
+               if ( $isXHTML ) { // XHTML5
+                       // XML mimetyped markup should have an xml header.
+                       // However a DOCTYPE is not needed.
+                       $ret .= "<?xml version=\"1.0\" encoding=\"UTF-8\" ?" . ">\n";
 
-                       if ( $wgHtml5Version ) {
-                               $attribs['version'] = $wgHtml5Version;
-                       }
-               } else {
-                       $ret .= "<!DOCTYPE html PUBLIC \"$wgDocType\" \"$wgDTD\">\n";
-                       $attribs['xmlns'] = $wgXhtmlDefaultNamespace;
+                       // Add the standard xmlns
+                       $attribs['xmlns'] = 'http://www.w3.org/1999/xhtml';
 
+                       // And support custom namespaces
                        foreach ( $wgXhtmlNamespaces as $tag => $ns ) {
                                $attribs["xmlns:$tag"] = $ns;
                        }
+               } else { // HTML5
+                       // DOCTYPE
+                       $ret .= "<!DOCTYPE html>\n";
+               }
+
+               if ( $wgHtml5Version ) {
+                       $attribs['version'] = $wgHtml5Version;
                }
 
                $html = Html::openElement( 'html', $attribs );
@@ -901,14 +842,11 @@ class Html {
         * @return Boolean
         */
        public static function isXmlMimeType( $mimetype ) {
-               switch ( $mimetype ) {
-                       case 'text/xml':
-                       case 'application/xhtml+xml':
-                       case 'application/xml':
-                               return true;
-                       default:
-                               return false;
-               }
+               # http://www.whatwg.org/specs/web-apps/current-work/multipage/infrastructure.html#xml-mime-type
+               # * text/xml
+               # * application/xml
+               # * Any mimetype with a subtype ending in +xml (this implicitly includes application/xhtml+xml)
+               return (bool) preg_match( '!^(text|application)/xml$|^.+/.+\+xml$!', $mimetype );
        }
 
        /**
index e7928cc..5104a1a 100644 (file)
@@ -177,20 +177,8 @@ function wfHtmlValidationHandler( $s ) {
 
        header( 'Cache-Control: no-cache' );
 
-       $out = <<<EOT
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" lang="en" dir="ltr">
-<head>
-<title>HTML validation error</title>
-<style>
-.highlight { background-color: #ffc }
-li { white-space: pre }
-</style>
-</head>
-<body>
-<h1>HTML validation error</h1>
-<ul>
-EOT;
+       $out = Html::element( 'h1', null, 'HTML validation error' );
+       $out .= Html::openElement( 'ul' );
 
        $error = strtok( $errors, "\n" );
        $badLines = array();
@@ -198,26 +186,40 @@ EOT;
                if ( preg_match( '/^line (\d+)/', $error, $m ) ) {
                        $lineNum = intval( $m[1] );
                        $badLines[$lineNum] = true;
-                       $out .= "<li><a href=\"#line-{$lineNum}\">" . htmlspecialchars( $error ) . "</a></li>\n";
+                       $out .= Html::rawElement( 'li', null,
+                               Html::element( 'a', array( 'href' => "#line-{$lineNum}" ), $error ) ) . "\n";
                }
                $error = strtok( "\n" );
        }
 
-       $out .= '</ul>';
-       $out .= '<pre>' . htmlspecialchars( $errors ) . '</pre>';
-       $out .= "<ol>\n";
+       $out .= Html::closeElement( 'ul' );
+       $out .= Html::element( 'pre', null, $errors );
+       $out .= Html::openElement( 'ol' ) . "\n";
        $line = strtok( $s, "\n" );
        $i = 1;
        while ( $line !== false ) {
+               $attrs = array();
                if ( isset( $badLines[$i] ) ) {
-                       $out .= "<li class=\"highlight\" id=\"line-$i\">";
-               } else {
-                       $out .= '<li>';
+                       $attrs['class'] = 'highlight';
+                       $attrs['id'] = "line-$i";
                }
-               $out .= htmlspecialchars( $line ) . "</li>\n";
+               $out .= Html::element( 'li', $attrs, $line ) . "\n";
                $line = strtok( "\n" );
                $i++;
        }
-       $out .= '</ol></body></html>';
+       $out .= Html::closeElement( 'ol' );
+
+       $style = <<<CSS
+.highlight { background-color: #ffc }
+li { white-space: pre }
+CSS;
+
+       $out = Html::htmlHeader( array( 'lang' => 'en', 'dir' => 'ltr' ) ) .
+               Html::rawElement( 'head', null,
+                       Html::element( 'title', null, 'HTML validation error' ) .
+                       Html::inlineStyle( $style ) ) .
+               Html::rawElement( 'body', null, $out ) .
+               Html::closeElement( 'html' );
+
        return $out;
 }
index 2c9a081..d379e46 100644 (file)
@@ -3133,7 +3133,7 @@ $templates
         */
        public function getHeadLinksArray( $addContentType = false ) {
                global $wgUniversalEditButton, $wgFavicon, $wgAppleTouchIcon, $wgEnableAPI,
-                       $wgSitename, $wgVersion, $wgHtml5, $wgMimeType,
+                       $wgSitename, $wgVersion,
                        $wgFeed, $wgOverrideSiteFeed, $wgAdvertisedFeedTypes,
                        $wgDisableLangConversion, $wgCanonicalLanguageLinks,
                        $wgRightsPage, $wgRightsUrl;
@@ -3143,20 +3143,9 @@ $templates
                $canonicalUrl = $this->mCanonicalUrl;
 
                if ( $addContentType ) {
-                       if ( $wgHtml5 ) {
-                               # More succinct than <meta http-equiv=Content-Type>, has the
-                               # same effect
-                               $tags['meta-charset'] = Html::element( 'meta', array( 'charset' => 'UTF-8' ) );
-                       } else {
-                               $tags['meta-content-type'] = Html::element( 'meta', array(
-                                       'http-equiv' => 'Content-Type',
-                                       'content' => "$wgMimeType; charset=UTF-8"
-                               ) );
-                               $tags['meta-content-style-type'] = Html::element( 'meta', array( // bug 15835
-                                       'http-equiv' => 'Content-Style-Type',
-                                       'content' => 'text/css'
-                               ) );
-                       }
+                       # More succinct than <meta http-equiv=Content-Type>, has the
+                       # same effect
+                       $tags['meta-charset'] = Html::element( 'meta', array( 'charset' => 'UTF-8' ) );
                }
 
                $tags['meta-generator'] = Html::element( 'meta', array(
index c9321f0..02d3546 100644 (file)
@@ -61,12 +61,12 @@ function wfPHPVersionError( $type ) {
                header( 'Pragma: no-cache' );
 
                $finalOutput = <<<HTML
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns='http://www.w3.org/1999/xhtml' lang='en'>
+<!DOCTYPE html>
+<html lang="en" dir="ltr">
        <head>
+               <meta charset="UTF-8" />
                <title>MediaWiki {$mwVersion}</title>
-               <meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
-               <style type='text/css' media='screen'>
+               <style media='screen'>
                        body {
                                color: #000;
                                background-color: #fff;
index 099d0af..d3e3d1a 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * XHTML sanitizer for %MediaWiki.
+ * HTML sanitizer for %MediaWiki.
  *
  * Copyright Â© 2002-2005 Brion Vibber <brion@pobox.com> et al
  * http://www.mediawiki.org/
@@ -25,7 +25,7 @@
  */
 
 /**
- * XHTML sanitizer for MediaWiki
+ * HTML sanitizer for MediaWiki
  * @ingroup Parser
  */
 class Sanitizer {
@@ -364,7 +364,7 @@ class Sanitizer {
         * @return string
         */
        static function removeHTMLtags( $text, $processCallback = null, $args = array(), $extratags = array(), $removetags = array() ) {
-               global $wgUseTidy, $wgHtml5, $wgAllowMicrodataAttributes, $wgAllowImageTag;
+               global $wgUseTidy, $wgAllowMicrodataAttributes, $wgAllowImageTag;
 
                static $htmlpairsStatic, $htmlsingle, $htmlsingleonly, $htmlnest, $tabletags,
                        $htmllist, $listtags, $htmlsingleallowed, $htmlelementsStatic, $staticInitialised;
@@ -373,7 +373,7 @@ class Sanitizer {
 
                // Base our staticInitialised variable off of the global config state so that if the globals
                // are changed (like in the screwed up test system) we will re-initialise the settings.
-               $globalContext = implode( '-', compact( 'wgHtml5', 'wgAllowMicrodataAttributes', 'wgAllowImageTag' ) );
+               $globalContext = implode( '-', compact( 'wgAllowMicrodataAttributes', 'wgAllowImageTag' ) );
                if ( !$staticInitialised || $staticInitialised != $globalContext ) {
 
                        $htmlpairsStatic = array( # Tags that must be closed
@@ -382,18 +382,15 @@ class Sanitizer {
                                'strike', 'strong', 'tt', 'var', 'div', 'center',
                                'blockquote', 'ol', 'ul', 'dl', 'table', 'caption', 'pre',
                                'ruby', 'rt', 'rb', 'rp', 'p', 'span', 'abbr', 'dfn',
-                               'kbd', 'samp'
+                               'kbd', 'samp', 'data', 'time', 'mark'
                        );
-                       if ( $wgHtml5 ) {
-                               $htmlpairsStatic = array_merge( $htmlpairsStatic, array( 'data', 'time', 'mark' ) );
-                       }
                        $htmlsingle = array(
                                'br', 'hr', 'li', 'dt', 'dd'
                        );
                        $htmlsingleonly = array( # Elements that cannot have close tags
                                'br', 'hr'
                        );
-                       if ( $wgHtml5 && $wgAllowMicrodataAttributes ) {
+                       if ( $wgAllowMicrodataAttributes ) {
                                $htmlsingle[] = $htmlsingleonly[] = 'meta';
                                $htmlsingle[] = $htmlsingleonly[] = 'link';
                        }
@@ -710,7 +707,7 @@ class Sanitizer {
         * @todo Check for unique id attribute :P
         */
        static function validateAttributes( $attribs, $whitelist ) {
-               global $wgAllowRdfaAttributes, $wgAllowMicrodataAttributes, $wgHtml5;
+               global $wgAllowRdfaAttributes, $wgAllowMicrodataAttributes;
 
                $whitelist = array_flip( $whitelist );
                $hrefExp = '/^(' . wfUrlProtocols() . ')[^\s]+$/';
@@ -726,8 +723,8 @@ class Sanitizer {
                                continue;
                        }
 
-                       # Allow any attribute beginning with "data-", if in HTML5 mode
-                       if ( !( $wgHtml5 && preg_match( '/^data-/i', $attribute ) ) && !isset( $whitelist[$attribute] ) ) {
+                       # Allow any attribute beginning with "data-"
+                       if ( !preg_match( '/^data-/i', $attribute ) && !isset( $whitelist[$attribute] ) ) {
                                continue;
                        }
 
@@ -1030,10 +1027,10 @@ class Sanitizer {
         * @return String
         */
        static function escapeId( $id, $options = array() ) {
-               global $wgHtml5, $wgExperimentalHtmlIds;
+               global $wgExperimentalHtmlIds;
                $options = (array)$options;
 
-               if ( $wgHtml5 && $wgExperimentalHtmlIds && !in_array( 'legacy', $options ) ) {
+               if ( $wgExperimentalHtmlIds && !in_array( 'legacy', $options ) ) {
                        $id = Sanitizer::decodeCharReferences( $id );
                        $id = preg_replace( '/[ \t\n\r\f_\'"&#%]+/', '_', $id );
                        $id = trim( $id, '_' );
@@ -1423,10 +1420,10 @@ class Sanitizer {
         * @return Array
         */
        static function setupAttributeWhitelist() {
-               global $wgAllowRdfaAttributes, $wgHtml5, $wgAllowMicrodataAttributes;
+               global $wgAllowRdfaAttributes, $wgAllowMicrodataAttributes;
 
                static $whitelist, $staticInitialised;
-               $globalContext = implode( '-', compact( 'wgAllowRdfaAttributes', 'wgHtml5', 'wgAllowMicrodataAttributes' ) );
+               $globalContext = implode( '-', compact( 'wgAllowRdfaAttributes', 'wgAllowMicrodataAttributes' ) );
 
                if ( isset( $whitelist ) && $staticInitialised == $globalContext ) {
                        return $whitelist;
@@ -1452,7 +1449,7 @@ class Sanitizer {
                        ) );
                }
 
-               if ( $wgHtml5 && $wgAllowMicrodataAttributes ) {
+               if ( $wgAllowMicrodataAttributes ) {
                        # add HTML5 microdata tags as specified by http://www.whatwg.org/specs/web-apps/current-work/multipage/microdata.html#the-microdata-model
                        $common = array_merge( $common, array(
                                'itemid', 'itemprop', 'itemref', 'itemscope', 'itemtype'
@@ -1591,8 +1588,8 @@ class Sanitizer {
                        # 15.3
                        'hr'         => array_merge( $common, array( 'noshade', 'size', 'width' ) ),
 
-                       # XHTML Ruby annotation text module, simple ruby only.
-                       # http://www.w3c.org/TR/ruby/
+                       # HTML Ruby annotation text module, simple ruby only.
+                       # http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-ruby-element
                        'ruby'       => $common,
                        # rbc
                        # rtc
@@ -1608,25 +1605,20 @@ class Sanitizer {
                        # HTML 5 section 4.6
                        'bdi' => $common,
 
-               );
-
-               if ( $wgHtml5 ) {
                        # HTML5 elements, defined by:
                        # http://www.whatwg.org/specs/web-apps/current-work/multipage/
-                       $whitelist += array(
-                               'data' => array_merge( $common, array( 'value' ) ),
-                               'time' => array_merge( $common, array( 'datetime' ) ),
-                               'mark' => $common,
-
-                               // meta and link are only permitted by removeHTMLtags when Microdata
-                               // is enabled so we don't bother adding a conditional to hide these
-                               // Also meta and link are only valid in WikiText as Microdata elements
-                               // (ie: validateTag rejects tags missing the attributes needed for Microdata)
-                               // So we don't bother including $common attributes that have no purpose.
-                               'meta' => array( 'itemprop', 'content' ),
-                               'link' => array( 'itemprop', 'href' ),
-                       );
-               }
+                       'data' => array_merge( $common, array( 'value' ) ),
+                       'time' => array_merge( $common, array( 'datetime' ) ),
+                       'mark' => $common,
+
+                       // meta and link are only permitted by removeHTMLtags when Microdata
+                       // is enabled so we don't bother adding a conditional to hide these
+                       // Also meta and link are only valid in WikiText as Microdata elements
+                       // (ie: validateTag rejects tags missing the attributes needed for Microdata)
+                       // So we don't bother including $common attributes that have no purpose.
+                       'meta' => array( 'itemprop', 'content' ),
+                       'link' => array( 'itemprop', 'href' ),
+               );
 
                $staticInitialised = $globalContext;
 
index 565ca49..acbc3b6 100644 (file)
@@ -344,7 +344,14 @@ foreach ( $wgDisabledActions as $action ) {
        $wgActions[$action] = false;
 }
 
-if ( !$wgHtml5Version && $wgHtml5 && $wgAllowRdfaAttributes ) {
+# We always output html5 since 1.22, override any change made by local settings
+$wgHtml5 = true;
+
+# Setting wgXhtmlDefaultNamespace is not supported since 1.22.
+# However we define it here for extensions that depend on its value.
+$wgXhtmlDefaultNamespace = 'http://www.w3.org/1999/xhtml';
+
+if ( !$wgHtml5Version && $wgAllowRdfaAttributes ) {
        # see http://www.w3.org/TR/rdfa-in-html/#document-conformance
        if ( $wgMimeType == 'application/xhtml+xml' ) {
                $wgHtml5Version = 'XHTML+RDFa 1.0';
index e53d424..e3a6ccf 100644 (file)
@@ -174,7 +174,7 @@ class SkinTemplate extends Skin {
                global $wgContLang;
                global $wgScript, $wgStylePath;
                global $wgMimeType, $wgJsMimeType;
-               global $wgXhtmlDefaultNamespace, $wgXhtmlNamespaces, $wgHtml5Version;
+               global $wgXhtmlNamespaces, $wgHtml5Version;
                global $wgDisableCounters, $wgSitename, $wgLogo;
                global $wgMaxCredits, $wgShowCreditsIfMax;
                global $wgPageShowWatchingUsers;
@@ -236,7 +236,7 @@ class SkinTemplate extends Skin {
 
                        $tpl->set( 'jsvarurl', false );
 
-                       $tpl->setRef( 'xhtmldefaultnamespace', $wgXhtmlDefaultNamespace );
+                       $tpl->set( 'xhtmldefaultnamespace', 'http://www.w3.org/1999/xhtml' );
                        $tpl->set( 'xhtmlnamespaces', $wgXhtmlNamespaces );
                        $tpl->set( 'html5version', $wgHtml5Version );
                        $tpl->set( 'headlinks', $out->getHeadLinks() );
index d114b99..1d87d40 100644 (file)
@@ -4507,8 +4507,7 @@ class User {
         *
         * @return array Array of HTML attributes suitable for feeding to
         *   Html::element(), directly or indirectly.  (Don't feed to Xml::*()!
-        *   That will potentially output invalid XHTML 1.0 Transitional, and will
-        *   get confused by the boolean attribute syntax used.)
+        *   That will get confused by the boolean attribute syntax used.)
         */
        public static function passwordChangeInputAttribs() {
                global $wgMinimalPasswordLength;
index b2bcd61..840e174 100644 (file)
@@ -28,7 +28,7 @@
 /**
  * PHP Parser - Processes wiki markup (which uses a more user-friendly
  * syntax, such as "[[link]]" for making links), and provides a one-way
- * transformation of that wiki markup it into XHTML output / markup
+ * transformation of that wiki markup it into (X)HTML output / markup
  * (which in turn the browser understands, and can display).
  *
  * There are seven main entry points into the Parser class:
@@ -4131,7 +4131,7 @@ class Parser {
         * @private
         */
        function formatHeadings( $text, $origText, $isMain = true ) {
-               global $wgMaxTocLevel, $wgHtml5, $wgExperimentalHtmlIds;
+               global $wgMaxTocLevel, $wgExperimentalHtmlIds;
 
                # Inhibit editsection links if requested in the page
                if ( isset( $this->mDoubleUnderscores['noeditsection'] ) ) {
@@ -4309,7 +4309,7 @@ class Parser {
                        # Save headline for section edit hint before it's escaped
                        $headlineHint = $safeHeadline;
 
-                       if ( $wgHtml5 && $wgExperimentalHtmlIds ) {
+                       if ( $wgExperimentalHtmlIds ) {
                                # For reverse compatibility, provide an id that's
                                # HTML4-compatible, like we used to.
                                #
index 8175458..0006df4 100644 (file)
@@ -52,12 +52,12 @@ if ( !function_exists( 'session_name' ) ) {
        $installerStarted = ( $success && isset( $_SESSION['installData'] ) );
 }
 ?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns='http://www.w3.org/1999/xhtml' lang='en'>
+<!DOCTYPE html>
+<html lang="en" dir="ltr">
        <head>
+               <meta charset="UTF-8" />
                <title>MediaWiki <?php echo htmlspecialchars( $wgVersion ) ?></title>
-               <meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
-               <style type='text/css' media='screen'>
+               <style media='screen'>
                        html, body {
                                color: #000;
                                background-color: #fff;
index 4cc00da..df89a75 100644 (file)
@@ -629,8 +629,8 @@ The sidebar for MonoBook is generated from this message, lines that do not
 begin with * or ** are discarded, furthermore lines that do begin with ** and
 do not contain | are also discarded, but do not depend on this behavior for
 future releases. Also note that since each list value is wrapped in a unique
-XHTML id it should only appear once and include characters that are legal
-XHTML id names.
+(X)HTML id it should only appear once and include characters that are legal
+(X)HTML id names.
 */
 'sidebar' => '
 * navigation
index ca15d74..2c9e92b 100644 (file)
@@ -2543,7 +2543,7 @@ function runWikiTest( pageTest $test, &$testname, $can_overwrite = false ) {
                if ( !$valid ) print "\nW3C web validation failed - view details with: html2text " . DIRECTORY . "/" . $testname . ".validator_output.html";
        }
 
-       // Get tidy to check the page, unless we already know it produces non-XHTML output.
+       // Get tidy to check the page, unless we already know it produces non-(X)HTML output.
        if ( $test->tidyValidate() ) {
                $valid = tidyCheckFile( $testname . HTML_FILE ) && $valid;
        }
index 8b1fcdb..1b92f19 100644 (file)
@@ -105,11 +105,10 @@ class DumpRenderer extends Maintenance {
                $output = $content->getParserOutput( $title, null, $options );
 
                file_put_contents( $filename,
-                       "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" " .
-                       "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" .
-                       "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" .
+                       "<!DOCTYPE html>\n" .
+                       "<html lang=\"en\" dir=\"ltr\">\n" .
                        "<head>\n" .
-                       "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n" .
+                       "<meta charset=\"UTF-8\" />\n" .
                        "<title>" . htmlspecialchars( $display ) . "</title>\n" .
                        "</head>\n" .
                        "<body>\n" .
index 4e010d4..ecfe418 100644 (file)
@@ -37,7 +37,6 @@ class HtmlTest extends MediaWikiTestCase {
                        'wgLanguageCode' => $langCode,
                        'wgContLang' => $langObj,
                        'wgLang' => $langObj,
-                       'wgHtml5' => true,
                        'wgWellFormedXml' => false,
                ) );
        }
@@ -70,6 +69,31 @@ class HtmlTest extends MediaWikiTestCase {
                );
        }
 
+       public function dataXmlMimeType() {
+               return array(
+                       // ( $mimetype, $isXmlMimeType )
+                       # HTML is not an XML MimeType
+                       array( 'text/html', false ),
+                       # XML is an XML MimeType
+                       array( 'text/xml', true ),
+                       array( 'application/xml', true ),
+                       # XHTML is an XML MimeType
+                       array( 'application/xhtml+xml', true ),
+                       # Make sure other +xml MimeTypes are supported
+                       # SVG is another random MimeType even though we don't use it
+                       array( 'image/svg+xml', true ),
+                       # Complete random other MimeTypes are not XML
+                       array( 'text/plain', false ),
+               );
+       }
+
+       /**
+        * @dataProvider dataXmlMimeType
+        */
+       public function testXmlMimeType( $mimetype, $isXmlMimeType ) {
+               $this->assertEquals( $isXmlMimeType, Html::isXmlMimeType( $mimetype ) );
+       }
+
        public function testExpandAttributesSkipsNullAndFalse() {
 
                ### EMPTY ########
@@ -117,14 +141,6 @@ class HtmlTest extends MediaWikiTestCase {
                        Html::expandAttributes( array( 'selected' => true ) ),
                        'Boolean attributes have empty string value when value is true (wgWellFormedXml)'
                );
-
-               $this->setMwGlobals( 'wgHtml5', false );
-
-               $this->assertEquals(
-                       ' selected="selected"',
-                       Html::expandAttributes( array( 'selected' => true ) ),
-                       'Boolean attributes have their key as value when value is true (wgWellFormedXml, wgHTML5 = false)'
-               );
        }
 
        /**
index 159ea71..b745423 100644 (file)
@@ -71,8 +71,6 @@ class SanitizerTest extends MediaWikiTestCase {
         */
        function testRemovehtmltagsOnHtml5Tags( $tag, $escaped ) {
                $this->setMwGlobals( array(
-                       # Enable HTML5 mode
-                       'wgHtml5' => true,
                        'wgUseTidy' => false
                ) );
 
index d7227b4..08c031f 100644 (file)
@@ -7,7 +7,6 @@ class XmlSelectTest extends MediaWikiTestCase {
        protected function setUp() {
                parent::setUp();
                $this->setMwGlobals( array(
-                       'wgHtml5' => true,
                        'wgWellFormedXml' => true,
                ) );
                $this->select = new XmlSelect();
index f482328..2294804 100644 (file)
@@ -29,7 +29,6 @@ class XmlTest extends MediaWikiTestCase {
 
                $this->setMwGlobals( array(
                        'wgLang' => $langObj,
-                       'wgHtml5' => true,
                        'wgWellFormedXml' => true,
                ) );
        }
index e0158a2..db352de 100644 (file)
@@ -83,7 +83,6 @@ class NewParserTest extends MediaWikiTestCase {
                $tmpGlobals['wgRawHtml'] = false;
                $tmpGlobals['wgUseTidy'] = false;
                $tmpGlobals['wgAlwaysUseTidy'] = false;
-               $tmpGlobals['wgHtml5'] = true;
                $tmpGlobals['wgWellFormedXml'] = true;
                $tmpGlobals['wgAllowMicrodataAttributes'] = true;
                $tmpGlobals['wgExperimentalHtmlIds'] = false;