| Index: trunk/phase3/maintenance/parserTests.inc |
| — | — | @@ -647,6 +647,8 @@ |
| 648 | 648 | 'wgEnforceHtmlIds' => true, |
| 649 | 649 | 'wgExternalLinkTarget' => false, |
| 650 | 650 | 'wgAlwaysUseTidy' => false, |
| | 651 | + 'wgHtml5' => true, |
| | 652 | + 'wgWellFormedXml' => true, |
| 651 | 653 | ); |
| 652 | 654 | |
| 653 | 655 | if ($config) { |
| Index: trunk/phase3/includes/Linker.php |
| — | — | @@ -1257,7 +1257,6 @@ |
| 1258 | 1258 | |
| 1259 | 1259 | /** @todo document */ |
| 1260 | 1260 | function tocList($toc) { |
| 1261 | | - global $wgJsMimeType; |
| 1262 | 1261 | $title = wfMsgHtml('toc') ; |
| 1263 | 1262 | return |
| 1264 | 1263 | '<table id="toc" class="toc"><tr><td>' |
| — | — | @@ -1266,13 +1265,13 @@ |
| 1267 | 1266 | # no trailing newline, script should not be wrapped in a |
| 1268 | 1267 | # paragraph |
| 1269 | 1268 | . "</ul>\n</td></tr></table>" |
| 1270 | | - . '<script type="' . $wgJsMimeType . '">' |
| 1271 | | - . ' if (window.showTocToggle) {' |
| 1272 | | - . ' var tocShowText = "' . Xml::escapeJsString( wfMsg('showtoc') ) . '";' |
| 1273 | | - . ' var tocHideText = "' . Xml::escapeJsString( wfMsg('hidetoc') ) . '";' |
| 1274 | | - . ' showTocToggle();' |
| 1275 | | - . ' } ' |
| 1276 | | - . "</script>\n"; |
| | 1269 | + . Html::inlineScript( |
| | 1270 | + 'if (window.showTocToggle) {' |
| | 1271 | + . ' var tocShowText = "' . Xml::escapeJsString( wfMsg('showtoc') ) . '";' |
| | 1272 | + . ' var tocHideText = "' . Xml::escapeJsString( wfMsg('hidetoc') ) . '";' |
| | 1273 | + . ' showTocToggle();' |
| | 1274 | + . ' } ' ) |
| | 1275 | + . "\n"; |
| 1277 | 1276 | } |
| 1278 | 1277 | |
| 1279 | 1278 | /** |
| Index: trunk/phase3/includes/EditPage.php |
| — | — | @@ -2056,7 +2056,7 @@ |
| 2057 | 2057 | * @return string |
| 2058 | 2058 | */ |
| 2059 | 2059 | static function getEditToolbar() { |
| 2060 | | - global $wgStylePath, $wgContLang, $wgLang, $wgJsMimeType; |
| | 2060 | + global $wgStylePath, $wgContLang, $wgLang; |
| 2061 | 2061 | |
| 2062 | 2062 | /** |
| 2063 | 2063 | * toolarray an array of arrays which each include the filename of |
| — | — | @@ -2171,9 +2171,9 @@ |
| 2172 | 2172 | ) |
| 2173 | 2173 | ); |
| 2174 | 2174 | $toolbar = "<div id='toolbar'>\n"; |
| 2175 | | - $toolbar.="<script type='$wgJsMimeType'>\n/*<![CDATA[*/\n"; |
| 2176 | 2175 | |
| 2177 | | - foreach($toolarray as $tool) { |
| | 2176 | + $script = ''; |
| | 2177 | + foreach ( $toolarray as $tool ) { |
| 2178 | 2178 | $params = array( |
| 2179 | 2179 | $image = $wgStylePath.'/common/images/'.$tool['image'], |
| 2180 | 2180 | // Note that we use the tip both for the ALT tag and the TITLE tag of the image. |
| — | — | @@ -2189,11 +2189,11 @@ |
| 2190 | 2190 | |
| 2191 | 2191 | $paramList = implode( ',', |
| 2192 | 2192 | array_map( array( 'Xml', 'encodeJsVar' ), $params ) ); |
| 2193 | | - $toolbar.="addButton($paramList);\n"; |
| | 2193 | + $script .= "addButton($paramList);\n"; |
| 2194 | 2194 | } |
| | 2195 | + $toolbar .= Html::inlineScript( "\n$script\n" ); |
| 2195 | 2196 | |
| 2196 | | - $toolbar.="/*]]>*/\n</script>"; |
| 2197 | | - $toolbar.="\n</div>"; |
| | 2197 | + $toolbar .= "\n</div>"; |
| 2198 | 2198 | |
| 2199 | 2199 | wfRunHooks( 'EditPageBeforeEditToolbar', array( &$toolbar ) ); |
| 2200 | 2200 | |
| Index: trunk/phase3/includes/OutputPage.php |
| — | — | @@ -109,8 +109,7 @@ |
| 110 | 110 | * addStyle() and draws from the /skins folder. |
| 111 | 111 | */ |
| 112 | 112 | public function addExtensionStyle( $url ) { |
| 113 | | - $linkarr = array( 'rel' => 'stylesheet', 'href' => $url, 'type' => 'text/css' ); |
| 114 | | - array_push( $this->mExtStyles, $linkarr ); |
| | 113 | + array_push( $this->mExtStyles, $url ); |
| 115 | 114 | } |
| 116 | 115 | |
| 117 | 116 | /** |
| — | — | @@ -118,7 +117,7 @@ |
| 119 | 118 | * @param string $file filename in skins/common or complete on-server path (/foo/bar.js) |
| 120 | 119 | */ |
| 121 | 120 | function addScriptFile( $file ) { |
| 122 | | - global $wgStylePath, $wgStyleVersion, $wgJsMimeType, $wgScript, $wgUser; |
| | 121 | + global $wgStylePath, $wgStyleVersion, $wgScript, $wgUser; |
| 123 | 122 | global $wgJSAutoloadClasses, $wgJSAutoloadLocalClasses, $wgEnableScriptLoader, $wgScriptPath; |
| 124 | 123 | |
| 125 | 124 | if( substr( $file, 0, 1 ) == '/' ) { |
| — | — | @@ -163,15 +162,7 @@ |
| 164 | 163 | } |
| 165 | 164 | |
| 166 | 165 | // if the script loader did not find a way to add the script than add using addScript |
| 167 | | - $this->addScript( |
| 168 | | - Xml::element( 'script', |
| 169 | | - array( |
| 170 | | - 'type' => $wgJsMimeType, |
| 171 | | - 'src' => wfAppendQuery( $path, $this->getURIDparam() ), |
| 172 | | - ), |
| 173 | | - '', false |
| 174 | | - ) |
| 175 | | - ); |
| | 166 | + $this->addScript( Html::linkedScript( wfAppendQuery( $path, $this->getURIDparam() ) ) ); |
| 176 | 167 | } |
| 177 | 168 | |
| 178 | 169 | /** |
| — | — | @@ -180,7 +171,7 @@ |
| 181 | 172 | * different page load types (edit, upload, view, etc) |
| 182 | 173 | */ |
| 183 | 174 | function addCoreScripts2Top(){ |
| 184 | | - global $wgEnableScriptLoader, $wgStyleVersion, $wgJSAutoloadLocalClasses, $wgJsMimeType, $wgScriptPath, $wgEnableJS2system; |
| | 175 | + global $wgEnableScriptLoader, $wgStyleVersion, $wgJSAutoloadLocalClasses, $wgScriptPath, $wgEnableJS2system; |
| 185 | 176 | //@@todo we should deprecate wikibits in favor of mv_embed and native jQuery functions |
| 186 | 177 | |
| 187 | 178 | if( $wgEnableJS2system ){ |
| — | — | @@ -195,12 +186,7 @@ |
| 196 | 187 | $so = ''; |
| 197 | 188 | foreach( $core_classes as $s ){ |
| 198 | 189 | if( isset( $wgJSAutoloadLocalClasses[$s] ) ){ |
| 199 | | - $so.= Xml::element( 'script', array( |
| 200 | | - 'type' => $wgJsMimeType, |
| 201 | | - 'src' => "{$wgScriptPath}/{$wgJSAutoloadLocalClasses[$s]}?" . $this->getURIDparam() |
| 202 | | - ), |
| 203 | | - '', false |
| 204 | | - ); |
| | 190 | + $so .= Html::linkedScript( "{$wgScriptPath}/{$wgJSAutoloadLocalClasses[$s]}?" . $this->getURIDparam() ); |
| 205 | 191 | } |
| 206 | 192 | } |
| 207 | 193 | $this->mScripts = $so . $this->mScripts; |
| — | — | @@ -213,7 +199,7 @@ |
| 214 | 200 | */ |
| 215 | 201 | function addScriptClass( $js_class ){ |
| 216 | 202 | global $wgDebugJavaScript, $wgJSAutoloadLocalClasses, $wgJSAutoloadClasses, |
| 217 | | - $wgJsMimeType, $wgEnableScriptLoader, $wgStyleVersion, $wgScriptPath; |
| | 203 | + $wgEnableScriptLoader, $wgStyleVersion, $wgScriptPath; |
| 218 | 204 | |
| 219 | 205 | if( isset( $wgJSAutoloadClasses[$js_class] ) || isset( $wgJSAutoloadLocalClasses[$js_class] ) ){ |
| 220 | 206 | if( $wgEnableScriptLoader ){ |
| — | — | @@ -228,16 +214,8 @@ |
| 229 | 215 | }else if( isset( $wgJSAutoloadLocalClasses[$js_class] ) ){ |
| 230 | 216 | $path.= $wgJSAutoloadLocalClasses[$js_class]; |
| 231 | 217 | } |
| 232 | | - $urlApend = ( $wgDebugJavaScript) ? time() : $wgStyleVersion; |
| 233 | | - $this->addScript( |
| 234 | | - Xml::element( 'script', |
| 235 | | - array( |
| 236 | | - 'type' => $wgJsMimeType, |
| 237 | | - 'src' => "$path?" . $urlApend, |
| 238 | | - ), |
| 239 | | - '', false |
| 240 | | - ) |
| 241 | | - ); |
| | 218 | + $urlAppend = ( $wgDebugJavaScript ) ? time() : $wgStyleVersion; |
| | 219 | + $this->addScript( Html::linkedScript( "$path?$urlAppend" ) ); |
| 242 | 220 | } |
| 243 | 221 | return true; |
| 244 | 222 | } |
| — | — | @@ -250,7 +228,7 @@ |
| 251 | 229 | * @param $forcClassAry Boolean: false by default |
| 252 | 230 | */ |
| 253 | 231 | function getScriptLoaderJs( $forceClassAry = false ){ |
| 254 | | - global $wgJsMimeType, $wgStyleVersion, $wgRequest, $wgDebugJavaScript; |
| | 232 | + global $wgStyleVersion, $wgRequest, $wgDebugJavaScript; |
| 255 | 233 | |
| 256 | 234 | if( !$forceClassAry ){ |
| 257 | 235 | $class_list = implode( ',', $this->mScriptLoaderClassList ); |
| — | — | @@ -268,14 +246,7 @@ |
| 269 | 247 | |
| 270 | 248 | //generate the unique request param (combine with the most recent revision id of any wiki page with the $wgStyleVersion var) |
| 271 | 249 | |
| 272 | | - |
| 273 | | - return Xml::element( 'script', |
| 274 | | - array( |
| 275 | | - 'type' => $wgJsMimeType, |
| 276 | | - 'src' => wfScript( 'mwScriptLoader' ) . "?class={$class_list}{$debug_param}&".$this->getURIDparam(), |
| 277 | | - ), |
| 278 | | - '', false |
| 279 | | - ); |
| | 250 | + return Html::linkedScript( wfScript( 'mwScriptLoader' ) . "?class={$class_list}{$debug_param}&" . $this->getURIDparam() ); |
| 280 | 251 | } |
| 281 | 252 | |
| 282 | 253 | function getURIDparam(){ |
| — | — | @@ -304,8 +275,7 @@ |
| 305 | 276 | * @param string $script JavaScript text, no <script> tags |
| 306 | 277 | */ |
| 307 | 278 | function addInlineScript( $script ) { |
| 308 | | - global $wgJsMimeType; |
| 309 | | - $this->mScripts .= "\t\t<script type=\"$wgJsMimeType\">/*<![CDATA[*/\n\t\t$script\n\t\t/*]]>*/</script>\n"; |
| | 279 | + $this->mScripts .= "\t\t" . Html::inlineScript( "\n\t\t$script\n\t\t" ) . "\n"; |
| 310 | 280 | } |
| 311 | 281 | |
| 312 | 282 | function getScript() { |
| — | — | @@ -1056,7 +1026,7 @@ |
| 1057 | 1027 | public function output() { |
| 1058 | 1028 | global $wgUser, $wgOutputEncoding, $wgRequest; |
| 1059 | 1029 | global $wgContLanguageCode, $wgDebugRedirects, $wgMimeType; |
| 1060 | | - global $wgJsMimeType, $wgUseAjax, $wgAjaxWatch; |
| | 1030 | + global $wgUseAjax, $wgAjaxWatch; |
| 1061 | 1031 | global $wgEnableMWSuggest, $wgUniversalEditButton; |
| 1062 | 1032 | global $wgArticle; |
| 1063 | 1033 | |
| — | — | @@ -1741,7 +1711,7 @@ |
| 1742 | 1712 | $this->getHeadItems(), |
| 1743 | 1713 | )); |
| 1744 | 1714 | if( $sk->usercss ){ |
| 1745 | | - $ret .= "<style type='text/css'>{$sk->usercss}</style>"; |
| | 1715 | + $ret .= Html::inlineStyle( $sk->usercss ); |
| 1746 | 1716 | } |
| 1747 | 1717 | |
| 1748 | 1718 | if( $wgEnableScriptLoader ) |
| — | — | @@ -1922,7 +1892,7 @@ |
| 1923 | 1893 | * @param $style_css Mixed: inline CSS |
| 1924 | 1894 | */ |
| 1925 | 1895 | public function addInlineStyle( $style_css ){ |
| 1926 | | - $this->mScripts .= "<style type=\"text/css\">$style_css</style>"; |
| | 1896 | + $this->mScripts .= Html::inlineStyle( $style_css ); |
| 1927 | 1897 | } |
| 1928 | 1898 | |
| 1929 | 1899 | /** |
| — | — | @@ -1956,7 +1926,7 @@ |
| 1957 | 1927 | return ''; |
| 1958 | 1928 | } |
| 1959 | 1929 | } else { |
| 1960 | | - $media = ''; |
| | 1930 | + $media = null; |
| 1961 | 1931 | } |
| 1962 | 1932 | |
| 1963 | 1933 | if( substr( $style, 0, 1 ) == '/' || |
| — | — | @@ -1968,16 +1938,8 @@ |
| 1969 | 1939 | $url = $wgStylePath . '/' . $style . '?' . $wgStyleVersion; |
| 1970 | 1940 | } |
| 1971 | 1941 | |
| 1972 | | - $attribs = array( |
| 1973 | | - 'rel' => 'stylesheet', |
| 1974 | | - 'href' => $url, |
| 1975 | | - 'type' => 'text/css' ); |
| 1976 | | - if( $media ) { |
| 1977 | | - $attribs['media'] = $media; |
| 1978 | | - } |
| | 1942 | + $link = Html::linkedStyle( $url, $media ); |
| 1979 | 1943 | |
| 1980 | | - $link = Xml::element( 'link', $attribs ); |
| 1981 | | - |
| 1982 | 1944 | if( isset( $options['condition'] ) ) { |
| 1983 | 1945 | $condition = htmlspecialchars( $options['condition'] ); |
| 1984 | 1946 | $link = "<!--[if $condition]>$link<![endif]-->"; |
| Index: trunk/phase3/includes/Html.php |
| — | — | @@ -0,0 +1,217 @@ |
| | 2 | +<?php |
| | 3 | +# Copyright (C) 2009 Aryeh Gregor |
| | 4 | +# http://www.mediawiki.org/ |
| | 5 | +# |
| | 6 | +# This program is free software; you can redistribute it and/or modify |
| | 7 | +# it under the terms of the GNU General Public License as published by |
| | 8 | +# the Free Software Foundation; either version 2 of the License, or |
| | 9 | +# (at your option) any later version. |
| | 10 | +# |
| | 11 | +# This program is distributed in the hope that it will be useful, |
| | 12 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| | 13 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| | 14 | +# GNU General Public License for more details. |
| | 15 | +# |
| | 16 | +# You should have received a copy of the GNU General Public License along |
| | 17 | +# with this program; if not, write to the Free Software Foundation, Inc., |
| | 18 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| | 19 | +# http://www.gnu.org/copyleft/gpl.html |
| | 20 | + |
| | 21 | +/** |
| | 22 | + * This class is a collection of static functions that serve two purposes: |
| | 23 | + * |
| | 24 | + * 1) Implement any algorithms specified by HTML 5, or other HTML |
| | 25 | + * specifications, in a convenient and self-contained way. |
| | 26 | + * |
| | 27 | + * 2) Allow HTML elements to be conveniently and safely generated, like the |
| | 28 | + * current Xml class but a) less confused (Xml supports HTML-specific things, |
| | 29 | + * but only sometimes!) and b) not necessarily confined to XML-compatible |
| | 30 | + * output. |
| | 31 | + * |
| | 32 | + * There are two important configuration options this class uses: |
| | 33 | + * |
| | 34 | + * $wgHtml5: If this is set to false, then all output should be valid XHTML 1.0 |
| | 35 | + * Transitional. |
| | 36 | + * $wgWellFormedXml: If this is set to true, then all output should be |
| | 37 | + * well-formed XML (quotes on attributes, self-closing tags, etc.). |
| | 38 | + * |
| | 39 | + * This class is meant to be confined to utility functions that are called from |
| | 40 | + * trusted code paths. It does not do enforcement of policy like not allowing |
| | 41 | + * <a> elements. |
| | 42 | + */ |
| | 43 | +class Html { |
| | 44 | + # List of void elements from HTML 5, section 9.1.2 as of 2009-08-10 |
| | 45 | + private static $voidElements = array( |
| | 46 | + 'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', |
| | 47 | + 'keygen', 'link', 'meta', 'param', 'source' |
| | 48 | + ); |
| | 49 | + |
| | 50 | + /** |
| | 51 | + * Returns an HTML element in a string. The major advantage here over |
| | 52 | + * manually typing out the HTML is that it will escape all attribute |
| | 53 | + * values. If you're hardcoding all the attributes, or there are none, you |
| | 54 | + * should probably type out the string yourself. |
| | 55 | + * |
| | 56 | + * This is quite similar to Xml::element(), but it implements some useful |
| | 57 | + * HTML-specific logic. For instance, there is no $allowShortTag |
| | 58 | + * parameter: the closing tag is magically omitted if $element has an empty |
| | 59 | + * content model. If $wgWellFormedXml is false, then a few bytes will be |
| | 60 | + * shaved off the HTML output as well. In the future, other HTML-specific |
| | 61 | + * features might be added, like allowing arrays for the values of |
| | 62 | + * attributes like class= and media=. |
| | 63 | + * |
| | 64 | + * One notable difference to Xml::element() is that $contents is *not* |
| | 65 | + * escaped. This means that Html::element() can be usefully nested, rather |
| | 66 | + * than using the rather clumsy Xml::openElement() and Xml::closeElement(). |
| | 67 | + * |
| | 68 | + * @param $element string The element's name, e.g., 'a' |
| | 69 | + * @param $attribs array Associative array of attributes, e.g., array( |
| | 70 | + * 'href' => 'http://www.mediawiki.org/' ). Values will be HTML-escaped. |
| | 71 | + * @param $contents string The raw HTML contents of the element: *not* |
| | 72 | + * escaped! |
| | 73 | + * @return string Raw HTML |
| | 74 | + */ |
| | 75 | + public static function element( $element, $attribs = array(), $contents = '' ) { |
| | 76 | + global $wgWellFormedXml; |
| | 77 | + $element = strtolower( $element ); |
| | 78 | + $start = "<$element" . self::expandAttributes( $attribs ); |
| | 79 | + if ( in_array( $element, self::$voidElements ) ) { |
| | 80 | + if ( $wgWellFormedXml ) { |
| | 81 | + return "$start />"; |
| | 82 | + } |
| | 83 | + return "$start>"; |
| | 84 | + } else { |
| | 85 | + return "$start>$contents</$element>"; |
| | 86 | + } |
| | 87 | + } |
| | 88 | + |
| | 89 | + /** |
| | 90 | + * Given an associative array of element attributes, generate a string |
| | 91 | + * to stick after the element name in HTML output. Like array( 'href' => |
| | 92 | + * 'http://www.mediawiki.org/' ) becomes something like |
| | 93 | + * ' href="http://www.mediawiki.org"'. Again, this is like |
| | 94 | + * Xml::expandAttributes(), but it implements some HTML-specific logic. |
| | 95 | + * For instance, it will omit quotation marks if $wgWellFormedXml is false. |
| | 96 | + * |
| | 97 | + * @param $attribs array Associative array of attributes, e.g., array( |
| | 98 | + * 'href' => 'http://www.mediawiki.org/' ). Values will be HTML-escaped. |
| | 99 | + * @return string HTML fragment that goes between element name and '>' |
| | 100 | + * (starting with a space if at least one attribute is output) |
| | 101 | + */ |
| | 102 | + public static function expandAttributes( $attribs ) { |
| | 103 | + global $wgWellFormedXml; |
| | 104 | + |
| | 105 | + $ret = ''; |
| | 106 | + foreach ( $attribs as $key => $value ) { |
| | 107 | + # See the "Attributes" section in the HTML syntax part of HTML 5, |
| | 108 | + # 9.1.2.3 as of 2009-08-10. Most attributes can have quotation |
| | 109 | + # marks omitted, but not all. (Although a literal " is not |
| | 110 | + # permitted, we don't check for that, since it will be escaped |
| | 111 | + # anyway.) |
| | 112 | + if ( $wgWellFormedXml || $value == '' |
| | 113 | + || preg_match( "/[ '=<>]/", $value ) ) { |
| | 114 | + $quote = '"'; |
| | 115 | + } else { |
| | 116 | + $quote = ''; |
| | 117 | + } |
| | 118 | + |
| | 119 | + # Apparently we need to entity-encode \n, \r, \t, although the spec |
| | 120 | + # doesn't mention that. Since we're doing strtr() anyway, and we |
| | 121 | + # don't need <> escaped here, we may as well not call |
| | 122 | + # htmlspecialchars(). FIXME: verify that we actually need to |
| | 123 | + # escape \n\r\t here, and explain why, exactly. |
| | 124 | + $ret .= " $key=$quote" . strtr( $value, array( |
| | 125 | + '&' => '&', |
| | 126 | + '"' => '"', |
| | 127 | + "\n" => ' ', |
| | 128 | + "\r" => ' ', |
| | 129 | + "\t" => '	' |
| | 130 | + ) ) . $quote; |
| | 131 | + } |
| | 132 | + return $ret; |
| | 133 | + } |
| | 134 | + |
| | 135 | + /** |
| | 136 | + * Output a <script> tag with the given contents. TODO: do some useful |
| | 137 | + * escaping as well, like if $contents contains literal '</script>' or (for |
| | 138 | + * XML) literal "]]>". |
| | 139 | + * |
| | 140 | + * @param $contents string JavaScript |
| | 141 | + * @return string Raw HTML |
| | 142 | + */ |
| | 143 | + public static function inlineScript( $contents ) { |
| | 144 | + global $wgHtml5, $wgJsMimeType; |
| | 145 | + |
| | 146 | + $attrs = array(); |
| | 147 | + if ( !$wgHtml5 ) { |
| | 148 | + $attrs['type'] = $wgJsMimeType; |
| | 149 | + $contents = "/*<![CDATA[*/$contents/*]]>*/"; |
| | 150 | + } |
| | 151 | + return self::element( 'script', $attrs, $contents ); |
| | 152 | + } |
| | 153 | + |
| | 154 | + /** |
| | 155 | + * Output a <script> tag linking to the given URL, e.g., |
| | 156 | + * <script src=foo.js></script>. |
| | 157 | + * |
| | 158 | + * @param $url string |
| | 159 | + * @return string Raw HTML |
| | 160 | + */ |
| | 161 | + public static function linkedScript( $url ) { |
| | 162 | + global $wgHtml5, $wgJsMimeType; |
| | 163 | + |
| | 164 | + $attrs = array( 'src' => $url ); |
| | 165 | + if ( !$wgHtml5 ) { |
| | 166 | + $attrs['type'] = $wgJsMimeType; |
| | 167 | + } |
| | 168 | + return self::element( 'script', $attrs ); |
| | 169 | + } |
| | 170 | + |
| | 171 | + /** |
| | 172 | + * Output a <style> tag with the given contents for the given media type |
| | 173 | + * (if any). TODO: do some useful escaping as well, like if $contents |
| | 174 | + * contains literal '</style>' (admittedly unlikely). |
| | 175 | + * |
| | 176 | + * @param $contents string CSS |
| | 177 | + * @param $media mixed A media type string, like 'screen', or null for all |
| | 178 | + * media |
| | 179 | + * @return string Raw HTML |
| | 180 | + */ |
| | 181 | + public static function inlineStyle( $contents, $media = null ) { |
| | 182 | + global $wgHtml5; |
| | 183 | + |
| | 184 | + $attrs = array(); |
| | 185 | + if ( !$wgHtml5 ) { |
| | 186 | + # Technically we should probably add CDATA stuff here like with |
| | 187 | + # scripts, but in practice, stylesheets tend not to have |
| | 188 | + # problematic characters anyway. |
| | 189 | + $attrs['type'] = 'text/css'; |
| | 190 | + } |
| | 191 | + if ( $media !== null ) { |
| | 192 | + $attrs['media'] = $media; |
| | 193 | + } |
| | 194 | + return self::element( 'style', $attrs, $contents ); |
| | 195 | + } |
| | 196 | + |
| | 197 | + /** |
| | 198 | + * Output a <link rel=stylesheet> linking to the given URL for the given |
| | 199 | + * media type (if any). |
| | 200 | + * |
| | 201 | + * @param $url string |
| | 202 | + * @param $media mixed A media type string, like 'screen', or null for all |
| | 203 | + * media |
| | 204 | + * @return string Raw HTML |
| | 205 | + */ |
| | 206 | + public static function linkedStyle( $url, $media = null ) { |
| | 207 | + global $wgHtml5; |
| | 208 | + |
| | 209 | + $attrs = array( 'rel' => 'stylesheet', 'href' => $url ); |
| | 210 | + if ( !$wgHtml5 ) { |
| | 211 | + $attrs['type'] = 'text/css'; |
| | 212 | + } |
| | 213 | + if ( $media !== null ) { |
| | 214 | + $attrs['media'] = $media; |
| | 215 | + } |
| | 216 | + return self::element( 'link', $attrs ); |
| | 217 | + } |
| | 218 | +} |
| Property changes on: trunk/phase3/includes/Html.php |
| ___________________________________________________________________ |
| Name: svn:eol-style |
| 1 | 219 | + native |
| Index: trunk/phase3/includes/AutoLoader.php |
| — | — | @@ -95,6 +95,7 @@ |
| 96 | 96 | 'HistoryBlobCurStub' => 'includes/HistoryBlob.php', |
| 97 | 97 | 'HistoryBlob' => 'includes/HistoryBlob.php', |
| 98 | 98 | 'HistoryBlobStub' => 'includes/HistoryBlob.php', |
| | 99 | + 'Html' => 'includes/Html.php', |
| 99 | 100 | 'HTMLCacheUpdate' => 'includes/HTMLCacheUpdate.php', |
| 100 | 101 | 'HTMLCacheUpdateJob' => 'includes/HTMLCacheUpdate.php', |
| 101 | 102 | 'HTMLFileCache' => 'includes/HTMLFileCache.php', |
| Index: trunk/phase3/includes/ChangesList.php |
| — | — | @@ -600,15 +600,13 @@ |
| 601 | 601 | * @ return string |
| 602 | 602 | */ |
| 603 | 603 | public function beginRecentChangesList() { |
| 604 | | - global $wgStylePath, $wgJsMimeType, $wgStyleVersion; |
| | 604 | + global $wgStylePath, $wgStyleVersion; |
| 605 | 605 | $this->rc_cache = array(); |
| 606 | 606 | $this->rcMoveIndex = 0; |
| 607 | 607 | $this->rcCacheIndex = 0; |
| 608 | 608 | $this->lastdate = ''; |
| 609 | 609 | $this->rclistOpen = false; |
| 610 | | - $script = Xml::tags( 'script', array( |
| 611 | | - 'type' => $wgJsMimeType, |
| 612 | | - 'src' => $wgStylePath . "/common/enhancedchanges.js?$wgStyleVersion" ), '' ); |
| | 610 | + $script = Html::linkedScript( $wgStylePath . "/common/enhancedchanges.js?$wgStyleVersion" ); |
| 613 | 611 | return $script; |
| 614 | 612 | } |
| 615 | 613 | /** |
| Index: trunk/phase3/includes/DefaultSettings.php |
| — | — | @@ -907,6 +907,23 @@ |
| 908 | 908 | */ |
| 909 | 909 | $wgHtml5 = true; |
| 910 | 910 | |
| | 911 | +/** |
| | 912 | + * Should we try to make our HTML output well-formed XML? If set to false, |
| | 913 | + * output will be a few bytes shorter, and the HTML will arguably be more |
| | 914 | + * readable. If set to true, life will be much easier for the authors of |
| | 915 | + * screen-scraping bots, and the HTML will arguably be more readable. |
| | 916 | + * |
| | 917 | + * Setting this to false may omit quotation marks on some attributes, omit |
| | 918 | + * slashes from some self-closing tags, omit some ending tags, etc., where |
| | 919 | + * permitted by HTML 5. Setting it to true will not guarantee that all pages |
| | 920 | + * will be well-formed, although non-well-formed pages should be rare and it's |
| | 921 | + * a bug if you find one. Conversely, setting it to false doesn't mean that |
| | 922 | + * all XML-y constructs will be omitted, just that they might be. |
| | 923 | + * |
| | 924 | + * Because of compatibility with screen-scraping bots, and because it's |
| | 925 | + * controversial, this is currently left to true by default. |
| | 926 | + */ |
| | 927 | +$wgWellFormedXml = true; |
| 911 | 928 | |
| 912 | 929 | /** |
| 913 | 930 | * Permit other namespaces in addition to the w3.org default. |
| Index: trunk/phase3/includes/specials/SpecialSearch.php |
| — | — | @@ -801,12 +801,10 @@ |
| 802 | 802 | } |
| 803 | 803 | |
| 804 | 804 | protected function searchFocus() { |
| 805 | | - global $wgJsMimeType; |
| 806 | | - return "<script type=\"$wgJsMimeType\">" . |
| | 805 | + return Html::inlineScript( |
| 807 | 806 | "hookEvent(\"load\", function() {" . |
| 808 | 807 | "document.getElementById('searchText').focus();" . |
| 809 | | - "});" . |
| 810 | | - "</script>"; |
| | 808 | + "});" ); |
| 811 | 809 | } |
| 812 | 810 | |
| 813 | 811 | protected function formHeader( $term, $resultsShown, $totalNum ) { |
| Index: trunk/phase3/includes/Skin.php |
| — | — | @@ -333,15 +333,13 @@ |
| 334 | 334 | } |
| 335 | 335 | |
| 336 | 336 | static function makeVariablesScript( $data ) { |
| 337 | | - global $wgJsMimeType; |
| 338 | | - |
| 339 | | - $r = array( "<script type=\"$wgJsMimeType\">/*<![CDATA[*/" ); |
| | 337 | + $r = array(); |
| 340 | 338 | foreach ( $data as $name => $value ) { |
| 341 | 339 | $encValue = Xml::encodeJsVar( $value ); |
| 342 | 340 | $r[] = "var $name = $encValue;"; |
| 343 | 341 | } |
| 344 | | - $r[] = "/*]]>*/</script>\n"; |
| 345 | | - return implode( "\n\t\t", $r ); |
| | 342 | + return Html::inlineScript( "\n\t\t" . implode( "\n\t\t", $r ) . |
| | 343 | + "\n\t\t" ); |
| 346 | 344 | } |
| 347 | 345 | |
| 348 | 346 | /** |
| — | — | @@ -632,8 +630,8 @@ |
| 633 | 631 | ); |
| 634 | 632 | |
| 635 | 633 | // Add any extension CSS |
| 636 | | - foreach( $out->getExtStyle() as $tag ) { |
| 637 | | - $out->addStyle( $tag['href'] ); |
| | 634 | + foreach ( $out->getExtStyle() as $url ) { |
| | 635 | + $out->addStyle( $url ); |
| 638 | 636 | } |
| 639 | 637 | |
| 640 | 638 | // If we use the site's dynamic CSS, throw that in, too |
| — | — | @@ -978,8 +976,7 @@ |
| 979 | 977 | * @return String HTML-wrapped JS code to be put before </body> |
| 980 | 978 | */ |
| 981 | 979 | function bottomScripts() { |
| 982 | | - global $wgJsMimeType; |
| 983 | | - $bottomScriptText = "\n\t\t<script type=\"$wgJsMimeType\">if (window.runOnloadHook) runOnloadHook();</script>\n"; |
| | 980 | + $bottomScriptText = "\n\t\t" . Html::inlineScript( 'if (window.runOnloadHook) runOnloadHook();' ) . "\n"; |
| 984 | 981 | wfRunHooks( 'SkinAfterBottomScripts', array( $this, &$bottomScriptText ) ); |
| 985 | 982 | return $bottomScriptText; |
| 986 | 983 | } |
| Index: trunk/phase3/RELEASE-NOTES |
| — | — | @@ -192,6 +192,9 @@ |
| 193 | 193 | numbers outside the permitted ranges), etc. |
| 194 | 194 | ** The summary attribute has been removed from tables of contents. summary is |
| 195 | 195 | obsolete in HTML 5 and wasn't useful here anyway. |
| | 196 | +** Unnecessary type="" attribute removed for CSS and JS. |
| | 197 | +** If $wgWellFormedXml is set to false, some bytes will be shaved off of HTML |
| | 198 | + output by omitting some things like quotation marks where HTML 5 allows. |
| 196 | 199 | * Added crop for inline images. |
| 197 | 200 | |
| 198 | 201 | === Bug fixes in 1.16 === |