<?php
-# Copyright (C) 2009 Aryeh Gregor
+# Copyright © 2009 Aryeh Gregor
# http://www.mediawiki.org/
#
# This program is free software; you can redistribute it and/or modify
* 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.
+ *
+ * @since 1.16
*/
class Html {
# List of void elements from HTML5, section 9.1.2 as of 2009-08-10
* @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()).
+ */
+ 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).
+ */
+ 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 <html> and <head> tags can be omitted under
+ # pretty much any sane circumstances, if they have no attributes. See:
+ # <http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html#optional-tags>
+ if ( !$wgWellFormedXml && !$attribs
+ && in_array( $element, array( 'html', 'head' ) ) ) {
+ return '';
+ }
+
# Remove HTML5-only attributes if we aren't doing HTML5
if ( !$wgHtml5 ) {
if ( $element == 'input' ) {
}
}
- $start = "<$element" . self::expandAttributes(
- self::dropDefaults( $element, $attribs ) );
- if ( in_array( $element, self::$voidElements ) ) {
- if ( $wgWellFormedXml ) {
- return "$start />";
- }
- return "$start>";
- } else {
- return "$start>$contents</$element>";
- }
+ return "<$element" . self::expandAttributes(
+ self::dropDefaults( $element, $attribs ) ) . '>';
}
/**
- * Identical to rawElement(), but HTML-escapes $contents (like
- * Xml::element()).
+ * Returns "</$element>", except if $wgWellFormedXml is off, in which case
+ * it returns the empty string when that's guaranteed to be safe.
+ *
+ * @param $element string Name of the element, e.g., 'a'
+ * @return string A closing tag, if required
*/
- 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.
- '&' => '&',
- '<' => '<'
- ) ) );
+ public static function closeElement( $element ) {
+ global $wgWellFormedXml;
+
+ $element = strtolower( $element );
+
+ # Reference:
+ # http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html#optional-tags
+ if ( !$wgWellFormedXml && in_array( $element, array(
+ 'html',
+ 'head',
+ 'body',
+ 'li',
+ 'dt',
+ 'dd',
+ 'tr',
+ 'td',
+ 'th',
+ ) ) ) {
+ return '';
+ }
+ return "</$element>";
}
/**
"\t" => '	'
);
if ( $wgWellFormedXml ) {
- # '<' must be escaped in attributes for XML for some
- # reason, per spec: http://www.w3.org/TR/xml/#NT-AttValue
+ # This is allowed per spec: <http://www.w3.org/TR/xml/#NT-AttValue>
+ # But reportedly it breaks some XML tools? FIXME: is this
+ # really true?
$map['<'] = '<';
}
$ret .= " $key=$quote" . strtr( $value, $map ) . $quote;
global $wgHtml5;
$attribs['name'] = $name;
if ( !$wgHtml5 ) {
- if ( !array_key_exists('cols', $attribs) )
+ if ( !isset( $attribs['cols'] ) )
$attribs['cols'] = "";
- if ( !array_key_exists('rows', $attribs) )
+ if ( !isset( $attribs['rows'] ) )
$attribs['rows'] = "";
}
return self::element( 'textarea', $attribs, $value );