For HTML 5, drop type="" attributes for CSS/JS
authorAryeh Gregor <simetrical@users.mediawiki.org>
Tue, 11 Aug 2009 00:09:24 +0000 (00:09 +0000)
committerAryeh Gregor <simetrical@users.mediawiki.org>
Tue, 11 Aug 2009 00:09:24 +0000 (00:09 +0000)
This time done in a nice, centralized fashion, reducing LOC for callers
even if HTML 5 is disabled.  The implementation is a new Html class,
similar to Xml but intended to be HTML-specific from the beginning
instead of half-heartedly attempting to provide generic XML services but
actually with lots of HTML-specific stuff tacked on.

As part of the new Html class, a global config option $wgWellFormedXml
is added.  It's set to true by default, but if set to false, the Html
class will drop some things that HTML 5 doesn't require, like
self-closing " />" syntax and attribute quotation marks (sometimes).

RELEASE-NOTES
includes/AutoLoader.php
includes/ChangesList.php
includes/DefaultSettings.php
includes/EditPage.php
includes/Html.php [new file with mode: 0644]
includes/Linker.php
includes/OutputPage.php
includes/Skin.php
includes/specials/SpecialSearch.php
maintenance/parserTests.inc

index 7e81183..7cc621f 100644 (file)
@@ -192,6 +192,9 @@ this. Was used when mwEmbed was going to be an extension.
    numbers outside the permitted ranges), etc.
 ** The summary attribute has been removed from tables of contents.  summary is
    obsolete in HTML 5 and wasn't useful here anyway.
+** Unnecessary type="" attribute removed for CSS and JS.
+** If $wgWellFormedXml is set to false, some bytes will be shaved off of HTML
+   output by omitting some things like quotation marks where HTML 5 allows.
 * Added crop for inline images.
 
 === Bug fixes in 1.16 ===
index c03eeb3..d81a1cb 100644 (file)
@@ -95,6 +95,7 @@ $wgAutoloadLocalClasses = array(
        'HistoryBlobCurStub' => 'includes/HistoryBlob.php',
        'HistoryBlob' => 'includes/HistoryBlob.php',
        'HistoryBlobStub' => 'includes/HistoryBlob.php',
+       'Html' => 'includes/Html.php',
        'HTMLCacheUpdate' => 'includes/HTMLCacheUpdate.php',
        'HTMLCacheUpdateJob' => 'includes/HTMLCacheUpdate.php',
        'HTMLFileCache' => 'includes/HTMLFileCache.php',
index 57314ee..844f687 100644 (file)
@@ -600,15 +600,13 @@ class EnhancedChangesList extends ChangesList {
        *  @ return string
        */
        public function beginRecentChangesList() {
-               global $wgStylePath, $wgJsMimeType, $wgStyleVersion;
+               global $wgStylePath, $wgStyleVersion;
                $this->rc_cache = array();
                $this->rcMoveIndex = 0;
                $this->rcCacheIndex = 0;
                $this->lastdate = '';
                $this->rclistOpen = false;
-               $script = Xml::tags( 'script', array(
-                       'type' => $wgJsMimeType,
-                       'src' => $wgStylePath . "/common/enhancedchanges.js?$wgStyleVersion" ), '' );
+               $script = Html::linkedScript( $wgStylePath . "/common/enhancedchanges.js?$wgStyleVersion" );
                return $script;
        }
        /**
index 08ac119..f799f60 100644 (file)
@@ -907,6 +907,23 @@ $wgXhtmlDefaultNamespace = 'http://www.w3.org/1999/xhtml';
  */
 $wgHtml5 = true;
 
+/**
+ * Should we try to make our HTML output well-formed XML?  If set to false,
+ * output will be a few bytes shorter, and the HTML will arguably be more
+ * readable.  If set to true, life will be much easier for the authors of
+ * screen-scraping bots, and the HTML will arguably be more readable.
+ *
+ * Setting this to false may omit quotation marks on some attributes, omit
+ * slashes from some self-closing tags, omit some ending tags, etc., where
+ * permitted by HTML 5.  Setting it to true will not guarantee that all pages
+ * will be well-formed, although non-well-formed pages should be rare and it's
+ * a bug if you find one.  Conversely, setting it to false doesn't mean that
+ * all XML-y constructs will be omitted, just that they might be.
+ *
+ * Because of compatibility with screen-scraping bots, and because it's
+ * controversial, this is currently left to true by default.
+ */
+$wgWellFormedXml = true;
 
 /**
  * Permit other namespaces in addition to the w3.org default.
index 4aa603b..2c6fba0 100644 (file)
@@ -2056,7 +2056,7 @@ END
         * @return string
         */
        static function getEditToolbar() {
-               global $wgStylePath, $wgContLang, $wgLang, $wgJsMimeType;
+               global $wgStylePath, $wgContLang, $wgLang;
 
                /**
                 * toolarray an array of arrays which each include the filename of
@@ -2171,9 +2171,9 @@ END
                        )
                );
                $toolbar = "<div id='toolbar'>\n";
-               $toolbar.="<script type='$wgJsMimeType'>\n/*<![CDATA[*/\n";
 
-               foreach($toolarray as $tool) {
+               $script = '';
+               foreach ( $toolarray as $tool ) {
                        $params = array(
                                $image = $wgStylePath.'/common/images/'.$tool['image'],
                                // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
@@ -2189,11 +2189,11 @@ END
 
                        $paramList = implode( ',',
                                array_map( array( 'Xml', 'encodeJsVar' ), $params ) );
-                       $toolbar.="addButton($paramList);\n";
+                       $script .= "addButton($paramList);\n";
                }
+               $toolbar .= Html::inlineScript( "\n$script\n" );
 
-               $toolbar.="/*]]>*/\n</script>";
-               $toolbar.="\n</div>";
+               $toolbar .= "\n</div>";
 
                wfRunHooks( 'EditPageBeforeEditToolbar', array( &$toolbar ) );
 
diff --git a/includes/Html.php b/includes/Html.php
new file mode 100644 (file)
index 0000000..7a75aef
--- /dev/null
@@ -0,0 +1,217 @@
+<?php
+# Copyright (C) 2009 Aryeh Gregor
+# http://www.mediawiki.org/
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * This class is a collection of static functions that serve two purposes:
+ *
+ * 1) Implement any algorithms specified by HTML 5, or other HTML
+ * specifications, in a convenient and self-contained way.
+ *
+ * 2) Allow HTML elements to be conveniently and safely generated, like the
+ * current Xml class but a) less confused (Xml supports HTML-specific things,
+ * but only sometimes!) and b) not necessarily confined to XML-compatible
+ * output.
+ *
+ * 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.
+ * $wgWellFormedXml: If this is set to true, then all output should be
+ *     well-formed XML (quotes on attributes, self-closing tags, etc.).
+ *
+ * This class is meant to be confined to utility functions that are called from
+ * trusted code paths.  It does not do enforcement of policy like not allowing
+ * <a> elements.
+ */
+class Html {
+       # List of void elements from HTML 5, section 9.1.2 as of 2009-08-10
+       private static $voidElements = array(
+               'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input',
+               'keygen', 'link', 'meta', 'param', 'source'
+       );
+
+       /**
+        * Returns an HTML element in a string.  The major advantage here over
+        * manually typing out the HTML is that it will escape all attribute
+        * values.  If you're hardcoding all the attributes, or there are none, you
+        * should probably type out the string yourself.
+        *
+        * This is quite similar to Xml::element(), but it implements some useful
+        * HTML-specific logic.  For instance, there is no $allowShortTag
+        * parameter: the closing tag is magically omitted if $element has an empty
+        * content model.  If $wgWellFormedXml is false, then a few bytes will be
+        * shaved off the HTML output as well.  In the future, other HTML-specific
+        * features might be added, like allowing arrays for the values of
+        * attributes like class= and media=.
+        *
+        * One notable difference to Xml::element() is that $contents is *not*
+        * escaped.  This means that Html::element() can be usefully nested, rather
+        * than using the rather clumsy Xml::openElement() and Xml::closeElement().  
+        *
+        * @param $element  string The element's name, e.g., 'a'
+        * @param $attribs  array  Associative array of attributes, e.g., array(
+        *   'href' => 'http://www.mediawiki.org/' ).  Values will be HTML-escaped.
+        * @param $contents string The raw HTML contents of the element: *not*
+        *   escaped!
+        * @return string Raw HTML
+        */
+       public static function element( $element, $attribs = array(), $contents = '' ) {
+               global $wgWellFormedXml;
+               $element = strtolower( $element );
+               $start = "<$element" . self::expandAttributes( $attribs );
+               if ( in_array( $element, self::$voidElements ) ) {
+                       if ( $wgWellFormedXml ) {
+                               return "$start />";
+                       }
+                       return "$start>";
+               } else {
+                       return "$start>$contents</$element>";
+               }
+       }
+
+       /**
+        * Given an associative array of element attributes, generate a string
+        * to stick after the element name in HTML output.  Like array( 'href' =>
+        * 'http://www.mediawiki.org/' ) becomes something like
+        * ' href="http://www.mediawiki.org"'.  Again, this is like
+        * Xml::expandAttributes(), but it implements some HTML-specific logic.
+        * For instance, it will omit quotation marks if $wgWellFormedXml is false.
+        *
+        * @param $attribs array Associative array of attributes, e.g., array(
+        *   'href' => 'http://www.mediawiki.org/' ).  Values will be HTML-escaped.
+        * @return string HTML fragment that goes between element name and '>'
+        *   (starting with a space if at least one attribute is output)
+        */
+       public static function expandAttributes( $attribs ) {
+               global $wgWellFormedXml;
+
+               $ret = '';
+               foreach ( $attribs as $key => $value ) {
+                       # See the "Attributes" section in the HTML syntax part of HTML 5,
+                       # 9.1.2.3 as of 2009-08-10.  Most attributes can have quotation
+                       # marks omitted, but not all.  (Although a literal " is not
+                       # permitted, we don't check for that, since it will be escaped
+                       # anyway.)
+                       if ( $wgWellFormedXml || $value == ''
+                       || preg_match( "/[ '=<>]/", $value ) ) {
+                               $quote = '"';
+                       } else {
+                               $quote = '';
+                       }
+
+                       # Apparently we need to entity-encode \n, \r, \t, although the spec
+                       # doesn't mention that.  Since we're doing strtr() anyway, and we
+                       # don't need <> escaped here, we may as well not call
+                       # htmlspecialchars().  FIXME: verify that we actually need to 
+                       # escape \n\r\t here, and explain why, exactly.
+                       $ret .= " $key=$quote" . strtr( $value, array(
+                               '&' => '&amp;',
+                               '"' => '&quot;',
+                               "\n" => '&#10;',
+                               "\r" => '&#13;',
+                               "\t" => '&#9;'
+                       ) ) . $quote;
+               }
+               return $ret;
+       }
+
+       /**
+        * Output a <script> tag with the given contents.  TODO: do some useful
+        * escaping as well, like if $contents contains literal '</script>' or (for
+        * XML) literal "]]>".
+        *
+        * @param $contents string JavaScript
+        * @return string Raw HTML
+        */
+       public static function inlineScript( $contents ) {
+               global $wgHtml5, $wgJsMimeType;
+
+               $attrs = array();
+               if ( !$wgHtml5 ) {
+                       $attrs['type'] = $wgJsMimeType;
+                       $contents = "/*<![CDATA[*/$contents/*]]>*/";
+               }
+               return self::element( 'script', $attrs, $contents );
+       }
+
+       /**
+        * Output a <script> tag linking to the given URL, e.g.,
+        * <script src=foo.js></script>.
+        *
+        * @param $url string
+        * @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 );
+       }
+
+       /**
+        * Output a <style> tag with the given contents for the given media type
+        * (if any).  TODO: do some useful escaping as well, like if $contents
+        * contains literal '</style>' (admittedly unlikely).
+        *
+        * @param $contents string CSS
+        * @param $media mixed A media type string, like 'screen', or null for all
+        *   media
+        * @return string Raw HTML
+        */
+       public static function inlineStyle( $contents, $media = null ) {
+               global $wgHtml5;
+
+               $attrs = array();
+               if ( !$wgHtml5 ) {
+                       # Technically we should probably add CDATA stuff here like with 
+                       # scripts, but in practice, stylesheets tend not to have 
+                       # problematic characters anyway.
+                       $attrs['type'] = 'text/css';
+               }
+               if ( $media !== null ) {
+                       $attrs['media'] = $media;
+               }
+               return self::element( 'style', $attrs, $contents );
+       }
+
+       /**
+        * Output a <link rel=stylesheet> linking to the given URL for the given
+        * media type (if any).
+        *
+        * @param $url string
+        * @param $media mixed A media type string, like 'screen', or null for all
+        *   media
+        * @return string Raw HTML
+        */
+       public static function linkedStyle( $url, $media = null ) {
+               global $wgHtml5;
+
+               $attrs = array( 'rel' => 'stylesheet', 'href' => $url );
+               if ( !$wgHtml5 ) {
+                       $attrs['type'] = 'text/css';
+               }
+               if ( $media !== null ) {
+                       $attrs['media'] = $media;
+               }
+               return self::element( 'link', $attrs );
+       }
+}
index bd306ce..8497a83 100644 (file)
@@ -1257,7 +1257,6 @@ class Linker {
 
        /** @todo document */
        function tocList($toc) {
-               global $wgJsMimeType;
                $title = wfMsgHtml('toc') ;
                return
                   '<table id="toc" class="toc"><tr><td>'
@@ -1266,13 +1265,13 @@ class Linker {
                 # no trailing newline, script should not be wrapped in a
                 # paragraph
                 . "</ul>\n</td></tr></table>"
-                . '<script type="' . $wgJsMimeType . '">'
-                . ' if (window.showTocToggle) {'
-                . ' var tocShowText = "' . Xml::escapeJsString( wfMsg('showtoc') ) . '";'
-                . ' var tocHideText = "' . Xml::escapeJsString( wfMsg('hidetoc') ) . '";'
-                . ' showTocToggle();'
-                . ' } '
-                . "</script>\n";
+                . Html::inlineScript(
+                       'if (window.showTocToggle) {'
+                       . ' var tocShowText = "' . Xml::escapeJsString( wfMsg('showtoc') ) . '";'
+                       . ' var tocHideText = "' . Xml::escapeJsString( wfMsg('hidetoc') ) . '";'
+                       . ' showTocToggle();'
+                       . ' } ' )
+               . "\n";
        }
        
        /**
index 7c51381..d60835e 100644 (file)
@@ -109,8 +109,7 @@ class OutputPage {
         *             addStyle() and draws from the /skins folder.
         */
        public function addExtensionStyle( $url ) {
-               $linkarr = array( 'rel' => 'stylesheet', 'href' => $url, 'type' => 'text/css' );
-               array_push( $this->mExtStyles, $linkarr );
+               array_push( $this->mExtStyles, $url );
        }
 
        /**
@@ -118,7 +117,7 @@ class OutputPage {
         * @param string $file filename in skins/common or complete on-server path (/foo/bar.js)
         */
        function addScriptFile( $file ) {
-               global $wgStylePath, $wgStyleVersion, $wgJsMimeType, $wgScript, $wgUser;
+               global $wgStylePath, $wgStyleVersion, $wgScript, $wgUser;
                global $wgJSAutoloadClasses, $wgJSAutoloadLocalClasses, $wgEnableScriptLoader, $wgScriptPath;
 
                if( substr( $file, 0, 1 ) == '/' ) {
@@ -163,15 +162,7 @@ class OutputPage {
                }
 
                // if the script loader did not find a way to add the script than add using addScript
-               $this->addScript(
-                       Xml::element( 'script',
-                               array(
-                                       'type' => $wgJsMimeType,
-                                       'src' => wfAppendQuery( $path, $this->getURIDparam() ),
-                               ),
-                               '', false
-                       )
-               );
+               $this->addScript( Html::linkedScript( wfAppendQuery( $path, $this->getURIDparam() ) ) );
        }
 
        /**
@@ -180,7 +171,7 @@ class OutputPage {
         *  different page load types (edit, upload, view, etc)
         */
        function addCoreScripts2Top(){
-               global $wgEnableScriptLoader, $wgStyleVersion, $wgJSAutoloadLocalClasses, $wgJsMimeType, $wgScriptPath, $wgEnableJS2system;
+               global $wgEnableScriptLoader, $wgStyleVersion, $wgJSAutoloadLocalClasses, $wgScriptPath, $wgEnableJS2system;
                //@@todo we should deprecate wikibits in favor of mv_embed and native jQuery functions
 
                if( $wgEnableJS2system ){
@@ -195,12 +186,7 @@ class OutputPage {
                        $so = '';
                        foreach( $core_classes as $s ){
                                if( isset( $wgJSAutoloadLocalClasses[$s] ) ){
-                                       $so.= Xml::element( 'script', array(
-                                                       'type' => $wgJsMimeType,
-                                                       'src' => "{$wgScriptPath}/{$wgJSAutoloadLocalClasses[$s]}?" . $this->getURIDparam()
-                                               ),
-                                               '', false
-                                       );
+                                       $so .= Html::linkedScript( "{$wgScriptPath}/{$wgJSAutoloadLocalClasses[$s]}?" . $this->getURIDparam() );
                                }
                        }
                        $this->mScripts =  $so . $this->mScripts;
@@ -213,7 +199,7 @@ class OutputPage {
         */
        function addScriptClass( $js_class ){
                global $wgDebugJavaScript, $wgJSAutoloadLocalClasses, $wgJSAutoloadClasses,
-                               $wgJsMimeType, $wgEnableScriptLoader, $wgStyleVersion, $wgScriptPath;
+                               $wgEnableScriptLoader, $wgStyleVersion, $wgScriptPath;
 
                if( isset( $wgJSAutoloadClasses[$js_class] ) || isset( $wgJSAutoloadLocalClasses[$js_class] ) ){
                        if( $wgEnableScriptLoader ){
@@ -228,16 +214,8 @@ class OutputPage {
                                }else if( isset( $wgJSAutoloadLocalClasses[$js_class] ) ){
                                        $path.= $wgJSAutoloadLocalClasses[$js_class];
                                }
-                               $urlApend = ( $wgDebugJavaScript) ? time() : $wgStyleVersion;
-                               $this->addScript(
-                                       Xml::element( 'script',
-                                               array(
-                                                       'type' => $wgJsMimeType,
-                                                       'src' => "$path?" . $urlApend,
-                                               ),
-                                               '', false
-                                       )
-                               );
+                               $urlAppend = ( $wgDebugJavaScript ) ? time() : $wgStyleVersion;
+                               $this->addScript( Html::linkedScript( "$path?$urlAppend" ) );
                        }
                        return true;
                }
@@ -250,7 +228,7 @@ class OutputPage {
         * @param $forcClassAry Boolean: false by default
         */
        function getScriptLoaderJs( $forceClassAry = false ){
-               global $wgJsMimeType, $wgStyleVersion, $wgRequest, $wgDebugJavaScript;
+               global $wgStyleVersion, $wgRequest, $wgDebugJavaScript;
 
                if( !$forceClassAry ){
                        $class_list = implode( ',', $this->mScriptLoaderClassList );
@@ -268,14 +246,7 @@ class OutputPage {
 
                //generate the unique request param (combine with the most recent revision id of any wiki page with the $wgStyleVersion var)
 
-
-               return Xml::element( 'script',
-                               array(
-                                       'type' => $wgJsMimeType,
-                                       'src' => wfScript( 'mwScriptLoader' ) . "?class={$class_list}{$debug_param}&".$this->getURIDparam(),
-                               ),
-                               '', false
-               );
+               return Html::linkedScript( wfScript( 'mwScriptLoader' ) . "?class={$class_list}{$debug_param}&" . $this->getURIDparam() );
        }
 
        function getURIDparam(){
@@ -304,8 +275,7 @@ class OutputPage {
         * @param string $script JavaScript text, no <script> tags
         */
        function addInlineScript( $script ) {
-               global $wgJsMimeType;
-               $this->mScripts .= "\t\t<script type=\"$wgJsMimeType\">/*<![CDATA[*/\n\t\t$script\n\t\t/*]]>*/</script>\n";
+               $this->mScripts .= "\t\t" . Html::inlineScript( "\n\t\t$script\n\t\t" ) . "\n";
        }
 
        function getScript() {
@@ -1056,7 +1026,7 @@ class OutputPage {
        public function output() {
                global $wgUser, $wgOutputEncoding, $wgRequest;
                global $wgContLanguageCode, $wgDebugRedirects, $wgMimeType;
-               global $wgJsMimeType, $wgUseAjax, $wgAjaxWatch;
+               global $wgUseAjax, $wgAjaxWatch;
                global $wgEnableMWSuggest, $wgUniversalEditButton;
                global $wgArticle;
 
@@ -1741,7 +1711,7 @@ class OutputPage {
                        $this->getHeadItems(),
                ));
                if( $sk->usercss ){
-                       $ret .= "<style type='text/css'>{$sk->usercss}</style>";
+                       $ret .= Html::inlineStyle( $sk->usercss );
                }
 
                if( $wgEnableScriptLoader )
@@ -1922,7 +1892,7 @@ class OutputPage {
         * @param $style_css Mixed: inline CSS
         */
        public function addInlineStyle( $style_css ){
-               $this->mScripts .= "<style type=\"text/css\">$style_css</style>";
+               $this->mScripts .= Html::inlineStyle( $style_css );
        }
 
        /**
@@ -1956,7 +1926,7 @@ class OutputPage {
                                return '';
                        }
                } else {
-                       $media = '';
+                       $media = null;
                }
 
                if( substr( $style, 0, 1 ) == '/' ||
@@ -1968,15 +1938,7 @@ class OutputPage {
                        $url = $wgStylePath . '/' . $style . '?' . $wgStyleVersion;
                }
 
-               $attribs = array(
-                       'rel' => 'stylesheet',
-                       'href' => $url,
-                       'type' => 'text/css' );
-               if( $media ) {
-                       $attribs['media'] = $media;
-               }
-
-               $link = Xml::element( 'link', $attribs );
+               $link = Html::linkedStyle( $url, $media );
 
                if( isset( $options['condition'] ) ) {
                        $condition = htmlspecialchars( $options['condition'] );
index 0df32f0..38b6138 100644 (file)
@@ -333,15 +333,13 @@ class Skin extends Linker {
        }
 
        static function makeVariablesScript( $data ) {
-               global $wgJsMimeType;
-
-               $r = array( "<script type=\"$wgJsMimeType\">/*<![CDATA[*/" );
+               $r = array();
                foreach ( $data as $name => $value ) {
                        $encValue = Xml::encodeJsVar( $value );
                        $r[] = "var $name = $encValue;";
                }
-               $r[] = "/*]]>*/</script>\n";
-               return implode( "\n\t\t", $r );
+               return Html::inlineScript( "\n\t\t" . implode( "\n\t\t", $r ) .
+                       "\n\t\t" );
        }
 
        /**
@@ -632,8 +630,8 @@ END;
                );
 
                // Add any extension CSS
-               foreach( $out->getExtStyle() as $tag ) {
-                       $out->addStyle( $tag['href'] );
+               foreach ( $out->getExtStyle() as $url ) {
+                       $out->addStyle( $url );
                }
 
                // If we use the site's dynamic CSS, throw that in, too
@@ -978,8 +976,7 @@ END;
         * @return String HTML-wrapped JS code to be put before </body>
         */
        function bottomScripts() {
-               global $wgJsMimeType;
-               $bottomScriptText = "\n\t\t<script type=\"$wgJsMimeType\">if (window.runOnloadHook) runOnloadHook();</script>\n";
+               $bottomScriptText = "\n\t\t" . Html::inlineScript( 'if (window.runOnloadHook) runOnloadHook();' ) . "\n";
                wfRunHooks( 'SkinAfterBottomScripts', array( $this, &$bottomScriptText ) );
                return $bottomScriptText;
        }
index b4ac3ab..da7f0d3 100644 (file)
@@ -801,12 +801,10 @@ class SpecialSearch {
        }
 
        protected function searchFocus() {
-               global $wgJsMimeType;
-               return "<script type=\"$wgJsMimeType\">" .
+               return Html::inlineScript(
                        "hookEvent(\"load\", function() {" .
                                "document.getElementById('searchText').focus();" .
-                       "});" .
-                       "</script>";
+                       "});" );
        }
 
        protected function formHeader( $term, $resultsShown, $totalNum ) {
index 16307ba..c3d8680 100644 (file)
@@ -647,6 +647,8 @@ class ParserTest {
                        'wgEnforceHtmlIds' => true,
                        'wgExternalLinkTarget' => false,
                        'wgAlwaysUseTidy' => false,
+                       'wgHtml5' => true,
+                       'wgWellFormedXml' => true,
                        );
 
                if ($config) {