elements. * * @since 1.16 */ class Html { // List of void elements from HTML5, section 8.1.2 as of 2011-08-12 private static $voidElements = array( 'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr', ); // Boolean attributes, which may have the value omitted entirely. Manually // collected from the HTML5 spec as of 2011-08-12. private static $boolAttribs = array( 'async', 'autofocus', 'autoplay', 'checked', 'controls', 'default', 'defer', 'disabled', 'formnovalidate', 'hidden', 'ismap', 'itemscope', 'loop', 'multiple', 'muted', 'novalidate', 'open', 'pubdate', 'readonly', 'required', 'reversed', 'scoped', 'seamless', 'selected', 'truespeed', 'typemustmatch', // HTML5 Microdata '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 * values. If you're hardcoding all the attributes, or there are none, you * should probably just type out the html element yourself. * * This is quite similar to Xml::tags(), 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. * * @param string $element The element's name, e.g., 'a' * @param array $attribs Associative array of attributes, e.g., array( * 'href' => 'http://www.mediawiki.org/' ). See expandAttributes() for * further documentation. * @param string $contents The raw HTML contents of the element: *not* * escaped! * @return string Raw HTML */ public static function rawElement( $element, $attribs = array(), $contents = '' ) { global $wgWellFormedXml; $start = self::openElement( $element, $attribs ); if ( in_array( $element, self::$voidElements ) ) { if ( $wgWellFormedXml ) { // Silly XML. return substr( $start, 0, -1 ) . ' />'; } return $start; } else { return "$start$contents" . self::closeElement( $element ); } } /** * Identical to rawElement(), but HTML-escapes $contents (like * Xml::element()). * * @param $element string * @param $attribs array * @param $contents string * * @return string */ public static function element( $element, $attribs = array(), $contents = '' ) { return self::rawElement( $element, $attribs, strtr( $contents, array( // There's no point in escaping quotes, >, etc. in the contents of // elements. '&' => '&', '<' => '<' ) ) ); } /** * Identical to rawElement(), but has no third parameter and omits the end * tag (and the self-closing '/' in XML mode for empty elements). * * @param $element string * @param $attribs array * * @return string */ public static function openElement( $element, $attribs = array() ) { global $wgHtml5, $wgWellFormedXml; $attribs = (array)$attribs; // This is not required in HTML5, but let's do it anyway, for // consistency and better compression. $element = strtolower( $element ); // In text/html, initial and tags can be omitted under // pretty much any sane circumstances, if they have no attributes. See: // if ( !$wgWellFormedXml && !$attribs && in_array( $element, array( 'html', 'head' ) ) ) { return ''; } // Remove invalid input types if ( $element == 'input' ) { $validTypes = array( 'hidden', 'text', 'password', 'checkbox', 'radio', 'file', 'submit', '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', ) ); } 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