diff options
-rw-r--r-- | src/HTML5/Elements.php | 88 | ||||
-rw-r--r-- | test/HTML5/ElementsTest.php | 305 |
2 files changed, 279 insertions, 114 deletions
diff --git a/src/HTML5/Elements.php b/src/HTML5/Elements.php index d437960..ad58363 100644 --- a/src/HTML5/Elements.php +++ b/src/HTML5/Elements.php @@ -1,6 +1,13 @@ <?php namespace HTML5; +/** + * Provide general element functions. + * + * @todo consider using a bitmask table lookup. There is enought overlap in + * naming that this could significantly shrink the size and maybe make it + * faster. See the Go teams implementation at https://code.google.com/p/go/source/browse/html/atom. + */ class Elements { const TEXT_RAW = 0x01; @@ -126,6 +133,56 @@ class Elements { ); /** + * The MathML elements. See http://www.w3.org/wiki/MathML/Elements. + * + * In our case we are only concerned with presentation MathML and not content + * MathML. There is a nice list of this subset at https://developer.mozilla.org/en-US/docs/MathML/Element. + * + * @var array + */ + public static $mathml = array( + "maction" => 1, + "maligngroup" => 1, + "malignmark" => 1, + "math" => 1, + "menclose" => 1, + "merror" => 1, + "mfenced" => 1, + "mfrac" => 1, + "mglyph" => 1, + "mi" => 1, + "mlabeledtr" => 1, + "mlongdiv" => 1, + "mmultiscripts" => 1, + "mn" => 1, + "mo" => 1, + "mover" => 1, + "mpadded" => 1, + "mphantom" => 1, + "mroot" => 1, + "mrow" => 1, + "ms" => 1, + "mscarries" => 1, + "mscarry" => 1, + "msgroup" => 1, + "msline" => 1, + "mspace" => 1, + "msqrt" => 1, + "msrow" => 1, + "mstack" => 1, + "mstyle" => 1, + "msub" => 1, + "msup" => 1, + "msubsup" => 1, + "mtable" => 1, + "mtd" => 1, + "mtext" => 1, + "mtr" => 1, + "munder" => 1, + "munderover" => 1, + ); + + /** * Test if an element is a valid html5 element. * * @param string $name @@ -140,4 +197,35 @@ class Elements { // Do we need this check or will all data passed here already be lowercase? return isset(self::$elements[strtolower($name)]); } + + /** + * Test if an element name is a valid MathML presentation element. + * + * @param string $name + * The name of the element. + * + * @return bool + * True if a MathML name and false otherwise. + */ + public static function isMathMLElement($name) { + + // MathML is case-sensetitive unlike html5 elements. + return isset(self::$mathml[$name]); + } + + /** + * Is an element name valid in an html5 document. + * + * This includes html5 elements along with other allowed embedded content + * such as svg and mathml. + * + * @param string $name + * The name of the element. + * + * @return bool + * True if valid and false otherwise. + */ + public function isElement($name) { + return self::isHtml5Element($name) || self::isMathMLElement($name); + } } diff --git a/test/HTML5/ElementsTest.php b/test/HTML5/ElementsTest.php index d3ba43b..318b210 100644 --- a/test/HTML5/ElementsTest.php +++ b/test/HTML5/ElementsTest.php @@ -7,121 +7,164 @@ require_once 'TestCase.php'; class ElementsTest extends TestCase { + public $html5Elements = array( + "a", + "abbr", + "address", + "area", + "article", + "aside", + "audio", + "b", + "base", + "bdi", + "bdo", + "blockquote", + "body", + "br", + "button", + "canvas", + "caption", + "cite", + "code", + "col", + "colgroup", + "command", + //"data", + "datalist", + "dd", + "del", + "details", + "dfn", + "dialog", + "div", + "dl", + "dt", + "em", + "embed", + "fieldset", + "figcaption", + "figure", + "footer", + "form", + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "head", + "header", + "hgroup", + "hr", + "html", + "i", + "iframe", + "img", + "input", + "ins", + "kbd", + "keygen", + "label", + "legend", + "li", + "link", + "map", + "mark", + "menu", + "meta", + "meter", + "nav", + "noscript", + "object", + "ol", + "optgroup", + "option", + "output", + "p", + "param", + "pre", + "progress", + "q", + "rp", + "rt", + "ruby", + "s", + "samp", + "script", + "section", + "select", + "small", + "source", + "span", + "strong", + "style", + "sub", + "summary", + "sup", + "table", + "tbody", + "td", + "textarea", + "tfoot", + "th", + "thead", + "time", + "title", + "tr", + "track", + "u", + "ul", + "var", + "video", + "wbr", + ); + + public $mathmlElements = array( + "maction", + "maligngroup", + "malignmark", + "math", + "menclose", + "merror", + "mfenced", + "mfrac", + "mglyph", + "mi", + "mlabeledtr", + "mlongdiv", + "mmultiscripts", + "mn", + "mo", + "mover", + "mpadded", + "mphantom", + "mroot", + "mrow", + "ms", + "mscarries", + "mscarry", + "msgroup", + "msline", + "mspace", + "msqrt", + "msrow", + "mstack", + "mstyle", + "msub", + "msup", + "msubsup", + "mtable", + "mtd", + "mtext", + "mtr", + "munder", + "munderover", + ); + public function testIsHtml5Element() { - $html5 = array( - "a", - "abbr", - "address", - "area", - "article", - "aside", - "audio", - "b", - "base", - "bdi", - "bdo", - "blockquote", - "body", - "br", - "button", - "canvas", - "caption", - "cite", - "code", - "col", - "colgroup", - "command", - //"data", - "datalist", - "dd", - "del", - "details", - "dfn", - "dialog", - "div", - "dl", - "dt", - "em", - "embed", - "fieldset", - "figcaption", - "figure", - "footer", - "form", - "h1", - "h2", - "h3", - "h4", - "h5", - "h6", - "head", - "header", - "hgroup", - "hr", - "html", - "i", - "iframe", - "img", - "input", - "ins", - "kbd", - "keygen", - "label", - "legend", - "li", - "link", - "map", - "mark", - "menu", - "meta", - "meter", - "nav", - "noscript", - "object", - "ol", - "optgroup", - "option", - "output", - "p", - "param", - "pre", - "progress", - "q", - "rp", - "rt", - "ruby", - "s", - "samp", - "script", - "section", - "select", - "small", - "source", - "span", - "strong", - "style", - "sub", - "summary", - "sup", - "table", - "tbody", - "td", - "textarea", - "tfoot", - "th", - "thead", - "time", - "title", - "tr", - "track", - "u", - "ul", - "var", - "video", - "wbr", - ); - - foreach ($html5 as $element) { + + foreach ($this->html5Elements as $element) { $this->assertTrue(Elements::isHtml5Element($element), 'html5 element test failed on: ' . $element); $this->assertTrue(Elements::isHtml5Element(strtoupper($element)), 'html5 element test failed on: ' . strtoupper($element)); @@ -133,8 +176,42 @@ class ElementsTest extends TestCase { $this->assertFalse(Elements::isHtml5Element(strtoupper($element)), 'html5 element test failed on: ' . strtoupper($element)); } + } + + public function testIsMathMLElement() { + foreach ($this->mathmlElements as $element) { + $this->assertTrue(Elements::isMathMLElement($element), 'MathML element test failed on: ' . $element); + + // MathML is case sensetitive so these should all fail. + $this->assertFalse(Elements::isMathMLElement(strtoupper($element)), 'MathML element test failed on: ' . strtoupper($element)); + } + + $nonMathML = array('foo', 'bar', 'baz'); + foreach ($nonMathML as $element) { + $this->assertFalse(Elements::isMathMLElement($element), 'MathML element test failed on: ' . $element); + } + } + + public function testIsElement() { + foreach ($this->html5Elements as $element) { + $this->assertTrue(Elements::isElement($element), 'html5 element test failed on: ' . $element); + + $this->assertTrue(Elements::isElement(strtoupper($element)), 'html5 element test failed on: ' . strtoupper($element)); + } + foreach ($this->mathmlElements as $element) { + $this->assertTrue(Elements::isElement($element), 'MathML element test failed on: ' . $element); + + // MathML is case sensetitive so these should all fail. + $this->assertFalse(Elements::isElement(strtoupper($element)), 'MathML element test failed on: ' . strtoupper($element)); + } + $nonhtml5 = array('foo', 'bar', 'baz'); + foreach ($nonhtml5 as $element) { + $this->assertFalse(Elements::isElement($element), 'html5 element test failed on: ' . $element); + + $this->assertFalse(Elements::isElement(strtoupper($element)), 'html5 element test failed on: ' . strtoupper($element)); + } } }
\ No newline at end of file |