elements. * * @since 1.16 */ class Html { /** @var bool[] List of void elements from HTML5, section 8.1.2 as of 2016-09-19 */ private static $voidElements = [ 'area' => true, 'base' => true, 'br' => true, 'col' => true, 'embed' => true, 'hr' => true, 'img' => true, 'input' => true, 'keygen' => true, 'link' => true, 'meta' => true, 'param' => true, 'source' => true, 'track' => true, 'wbr' => true, ]; /** * Boolean attributes, which may have the value omitted entirely. Manually * collected from the HTML5 spec as of 2011-08-12. * @var bool[] */ private static $boolAttribs = [ 'async' => true, 'autofocus' => true, 'autoplay' => true, 'checked' => true, 'controls' => true, 'default' => true, 'defer' => true, 'disabled' => true, 'formnovalidate' => true, 'hidden' => true, 'ismap' => true, 'itemscope' => true, 'loop' => true, 'multiple' => true, 'muted' => true, 'novalidate' => true, 'open' => true, 'pubdate' => true, 'readonly' => true, 'required' => true, 'reversed' => true, 'scoped' => true, 'seamless' => true, 'selected' => true, 'truespeed' => true, 'typemustmatch' => true, ]; /** * Modifies a set of attributes meant for button elements. * * @param array $attrs HTML attributes in an associative array * @param string[] $modifiers Unused * @return array Modified attributes array * @deprecated since 1.42 No-op */ public static function buttonAttributes( array $attrs, array $modifiers = [] ) { wfDeprecated( __METHOD__, '1.42' ); return $attrs; } /** * Modifies a set of attributes meant for text input elements. * * @param array $attrs An attribute array. * @return array Modified attributes array * @deprecated since 1.42 No-op */ public static function getTextInputAttributes( array $attrs ) { wfDeprecated( __METHOD__, '1.42' ); return $attrs; } /** * Returns an HTML link element in a string. * * @param string $text The text of the element. Will be escaped (not raw HTML) * @param array $attrs Associative array of attributes, e.g., [ * 'href' => 'https://www.mediawiki.org/' ]. See expandAttributes() for * further documentation. * @param string[] $modifiers Unused * @return string Raw HTML */ public static function linkButton( $text, array $attrs, array $modifiers = [] ) { return self::element( 'a', $attrs, $text ); } /** * Returns an HTML input element in a string. * * @param string $contents Plain text label for the button value * @param array $attrs Associative array of attributes, e.g., [ * 'href' => 'https://www.mediawiki.org/' ]. See expandAttributes() for * further documentation. * @param string[] $modifiers Unused * @return string Raw HTML */ public static function submitButton( $contents, array $attrs = [], array $modifiers = [] ) { $attrs['type'] = 'submit'; $attrs['value'] = $contents; return self::element( 'input', $attrs ); } /** * 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. * * 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. * * @param string $element The element's name, e.g., 'a' * @param-taint $element tainted * @param array $attribs Associative array of attributes, e.g., [ * 'href' => 'https://www.mediawiki.org/' ]. See expandAttributes() for * further documentation. * @param-taint $attribs escapes_html * @param string $contents The raw HTML contents of the element: *not* * escaped! * @param-taint $contents tainted * @return string Raw HTML * @return-taint escaped */ public static function rawElement( $element, $attribs = [], $contents = '' ) { $start = self::openElement( $element, $attribs ); if ( isset( self::$voidElements[$element] ) ) { return $start; } else { return $start . $contents . self::closeElement( $element ); } } /** * Identical to rawElement(), but HTML-escapes $contents (like * Xml::element()). * * @param string $element Name of the element, e.g., 'a' * @param-taint $element tainted * @param array $attribs Associative array of attributes, e.g., [ * 'href' => 'https://www.mediawiki.org/' ]. See expandAttributes() for * further documentation. * @param-taint $attribs escapes_html * @param string $contents * @param-taint $contents escapes_html * * @return string * @return-taint escaped */ public static function element( $element, $attribs = [], $contents = '' ) { return self::rawElement( $element, $attribs, strtr( $contents ?? '', [ // 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 string $element Name of the element, e.g., 'a' * @param array $attribs Associative array of attributes, e.g., [ * 'href' => 'https://www.mediawiki.org/' ]. See expandAttributes() for * further documentation. * * @return string */ public static function openElement( $element, $attribs = [] ) { $attribs = (array)$attribs; // This is not required in HTML5, but let's do it anyway, for // consistency and better compression. $element = strtolower( $element ); // Some people were abusing this by passing things like // 'h1 id="foo" to $element, which we don't want. if ( str_contains( $element, ' ' ) ) { wfWarn( __METHOD__ . " given element name with space '$element'" ); } // Remove invalid input types if ( $element == 'input' ) { $validTypes = [ 'hidden' => true, 'text' => true, 'password' => true, 'checkbox' => true, 'radio' => true, 'file' => true, 'submit' => true, 'image' => true, 'reset' => true, 'button' => true, // HTML input types 'datetime' => true, 'datetime-local' => true, 'date' => true, 'month' => true, 'time' => true, 'week' => true, 'number' => true, 'range' => true, 'email' => true, 'url' => true, 'search' => true, 'tel' => true, 'color' => true, ]; if ( isset( $attribs['type'] ) && !isset( $validTypes[$attribs['type']] ) ) { unset( $attribs['type'] ); } } // According to standard the default type for