Completed
Push — master ( 30aab1...cadcfa )
by Asmir
07:00
created

Elements::isA()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 2
1
<?php
2
/**
3
 * Provide general element functions.
4
 */
5
namespace Masterminds\HTML5;
6
7
/**
8
 * This class provides general information about HTML5 elements,
9
 * including syntactic and semantic issues.
10
 * Parsers and serializers can
11
 * use this class as a reference point for information about the rules
12
 * of various HTML5 elements.
13
 *
14
 * @todo consider using a bitmask table lookup. There is enough overlap in
15
 *       naming that this could significantly shrink the size and maybe make it
16
 *       faster. See the Go teams implementation at https://code.google.com/p/go/source/browse/html/atom.
17
 */
18
class Elements
19
{
20
21
    /**
22
     * Indicates an element is described in the specification.
23
     */
24
    const KNOWN_ELEMENT = 1;
25
26
    // From section 8.1.2: "script", "style"
27
    // From 8.2.5.4.7 ("in body" insertion mode): "noembed"
28
    // From 8.4 "style", "xmp", "iframe", "noembed", "noframes"
29
    /**
30
     * Indicates the contained text should be processed as raw text.
31
     */
32
    const TEXT_RAW = 2;
33
34
    // From section 8.1.2: "textarea", "title"
35
    /**
36
     * Indicates the contained text should be processed as RCDATA.
37
     */
38
    const TEXT_RCDATA = 4;
39
40
    /**
41
     * Indicates the tag cannot have content.
42
     */
43
    const VOID_TAG = 8;
44
45
    // "address", "article", "aside", "blockquote", "center", "details", "dialog", "dir", "div", "dl",
46
    // "fieldset", "figcaption", "figure", "footer", "header", "hgroup", "menu",
47
    // "nav", "ol", "p", "section", "summary", "ul"
48
    // "h1", "h2", "h3", "h4", "h5", "h6"
49
    // "pre", "listing"
50
    // "form"
51
    // "plaintext"
52
    /**
53
     * Indicates that if a previous event is for a P tag, that element
54
     * should be considered closed.
55
     */
56
    const AUTOCLOSE_P = 16;
57
58
    /**
59
     * Indicates that the text inside is plaintext (pre).
60
     */
61
    const TEXT_PLAINTEXT = 32;
62
63
    // See https://developer.mozilla.org/en-US/docs/HTML/Block-level_elements
64
    /**
65
     * Indicates that the tag is a block.
66
     */
67
    const BLOCK_TAG = 64;
68
69
    /**
70
     * Indicates that the tag allows only inline elements as child nodes.
71
     */
72
    const BLOCK_ONLY_INLINE = 128;
73
74
    /**
75
     * The HTML5 elements as defined in http://dev.w3.org/html5/markup/elements.html.
76
     *
77
     * @var array
78
     */
79
    public static $html5 = array(
80
        "a" => 1,
81
        "abbr" => 1,
82
        "address" => 65, // NORMAL | BLOCK_TAG
83
        "area" => 9, // NORMAL | VOID_TAG
84
        "article" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
85
        "aside" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
86
        "audio" => 1, // NORMAL
87
        "b" => 1,
88
        "base" => 9, // NORMAL | VOID_TAG
89
        "bdi" => 1,
90
        "bdo" => 1,
91
        "blockquote" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
92
        "body" => 1,
93
        "br" => 9, // NORMAL | VOID_TAG
94
        "button" => 1,
95
        "canvas" => 65, // NORMAL | BLOCK_TAG
96
        "caption" => 1,
97
        "cite" => 1,
98
        "code" => 1,
99
        "col" => 9, // NORMAL | VOID_TAG
100
        "colgroup" => 1,
101
        "command" => 9, // NORMAL | VOID_TAG
102
                        // "data" => 1, // This is highly experimental and only part of the whatwg spec (not w3c). See https://developer.mozilla.org/en-US/docs/HTML/Element/data
103
        "datalist" => 1,
104
        "dd" => 65, // NORMAL | BLOCK_TAG
105
        "del" => 1,
106
        "details" => 17, // NORMAL | AUTOCLOSE_P,
107
        "dfn" => 1,
108
        "dialog" => 17, // NORMAL | AUTOCLOSE_P,
109
        "div" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
110
        "dl" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
111
        "dt" => 1,
112
        "em" => 1,
113
        "embed" => 9, // NORMAL | VOID_TAG
114
        "fieldset" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
115
        "figcaption" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
116
        "figure" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
117
        "footer" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
118
        "form" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
119
        "h1" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
120
        "h2" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
121
        "h3" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
122
        "h4" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
123
        "h5" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
124
        "h6" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
125
        "head" => 1,
126
        "header" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
127
        "hgroup" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
128
        "hr" => 73, // NORMAL | VOID_TAG
129
        "html" => 1,
130
        "i" => 1,
131
        "iframe" => 3, // NORMAL | TEXT_RAW
132
        "img" => 9, // NORMAL | VOID_TAG
133
        "input" => 9, // NORMAL | VOID_TAG
134
        "kbd" => 1,
135
        "ins" => 1,
136
        "keygen" => 9, // NORMAL | VOID_TAG
137
        "label" => 1,
138
        "legend" => 1,
139
        "li" => 1,
140
        "link" => 9, // NORMAL | VOID_TAG
141
        "map" => 1,
142
        "mark" => 1,
143
        "menu" => 17, // NORMAL | AUTOCLOSE_P,
144
        "meta" => 9, // NORMAL | VOID_TAG
145
        "meter" => 1,
146
        "nav" => 17, // NORMAL | AUTOCLOSE_P,
147
        "noscript" => 65, // NORMAL | BLOCK_TAG
148
        "object" => 1,
149
        "ol" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
150
        "optgroup" => 1,
151
        "option" => 1,
152
        "output" => 65, // NORMAL | BLOCK_TAG
153
        "p" => 209, // NORMAL | AUTOCLOSE_P | BLOCK_TAG | BLOCK_ONLY_INLINE
154
        "param" => 9, // NORMAL | VOID_TAG
155
        "pre" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
156
        "progress" => 1,
157
        "q" => 1,
158
        "rp" => 1,
159
        "rt" => 1,
160
        "ruby" => 1,
161
        "s" => 1,
162
        "samp" => 1,
163
        "script" => 3, // NORMAL | TEXT_RAW
164
        "section" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
165
        "select" => 1,
166
        "small" => 1,
167
        "source" => 9, // NORMAL | VOID_TAG
168
        "span" => 1,
169
        "strong" => 1,
170
        "style" => 3, // NORMAL | TEXT_RAW
171
        "sub" => 1,
172
        "summary" => 17, // NORMAL | AUTOCLOSE_P,
173
        "sup" => 1,
174
        "table" => 65, // NORMAL | BLOCK_TAG
175
        "tbody" => 1,
176
        "td" => 1,
177
        "textarea" => 5, // NORMAL | TEXT_RCDATA
178
        "tfoot" => 65, // NORMAL | BLOCK_TAG
179
        "th" => 1,
180
        "thead" => 1,
181
        "time" => 1,
182
        "title" => 5, // NORMAL | TEXT_RCDATA
183
        "tr" => 1,
184
        "track" => 9, // NORMAL | VOID_TAG
185
        "u" => 1,
186
        "ul" => 81, // NORMAL | AUTOCLOSE_P | BLOCK_TAG
187
        "var" => 1,
188
        "video" => 65, // NORMAL | BLOCK_TAG
189
        "wbr" => 9, // NORMAL | VOID_TAG
190
191
        // Legacy?
192
        'basefont' => 8, // VOID_TAG
193
        'bgsound' => 8, // VOID_TAG
194
        'noframes' => 2, // RAW_TEXT
195
        'frame' => 9, // NORMAL | VOID_TAG
196
        'frameset' => 1,
197
        'center' => 16,
198
        'dir' => 16,
199
        'listing' => 16, // AUTOCLOSE_P
200
        'plaintext' => 48, // AUTOCLOSE_P | TEXT_PLAINTEXT
201
        'applet' => 0,
202
        'marquee' => 0,
203
        'isindex' => 8, // VOID_TAG
204
        'xmp' => 20, // AUTOCLOSE_P | VOID_TAG | RAW_TEXT
205
        'noembed' => 2 // RAW_TEXT
206
        );
207
208
    /**
209
     * The MathML elements.
210
     * See http://www.w3.org/wiki/MathML/Elements.
211
     *
212
     * In our case we are only concerned with presentation MathML and not content
213
     * MathML. There is a nice list of this subset at https://developer.mozilla.org/en-US/docs/MathML/Element.
214
     *
215
     * @var array
216
     */
217
    public static $mathml = array(
218
        "maction" => 1,
219
        "maligngroup" => 1,
220
        "malignmark" => 1,
221
        "math" => 1,
222
        "menclose" => 1,
223
        "merror" => 1,
224
        "mfenced" => 1,
225
        "mfrac" => 1,
226
        "mglyph" => 1,
227
        "mi" => 1,
228
        "mlabeledtr" => 1,
229
        "mlongdiv" => 1,
230
        "mmultiscripts" => 1,
231
        "mn" => 1,
232
        "mo" => 1,
233
        "mover" => 1,
234
        "mpadded" => 1,
235
        "mphantom" => 1,
236
        "mroot" => 1,
237
        "mrow" => 1,
238
        "ms" => 1,
239
        "mscarries" => 1,
240
        "mscarry" => 1,
241
        "msgroup" => 1,
242
        "msline" => 1,
243
        "mspace" => 1,
244
        "msqrt" => 1,
245
        "msrow" => 1,
246
        "mstack" => 1,
247
        "mstyle" => 1,
248
        "msub" => 1,
249
        "msup" => 1,
250
        "msubsup" => 1,
251
        "mtable" => 1,
252
        "mtd" => 1,
253
        "mtext" => 1,
254
        "mtr" => 1,
255
        "munder" => 1,
256
        "munderover" => 1
257
    );
258
259
    /**
260
     * The svg elements.
261
     *
262
     * The Mozilla documentation has a good list at https://developer.mozilla.org/en-US/docs/SVG/Element.
263
     * The w3c list appears to be lacking in some areas like filter effect elements.
264
     * That list can be found at http://www.w3.org/wiki/SVG/Elements.
265
     *
266
     * Note, FireFox appears to do a better job rendering filter effects than chrome.
267
     * While they are in the spec I'm not sure how widely implemented they are.
268
     *
269
     * @var array
270
     */
271
    public static $svg = array(
272
        "a" => 1,
273
        "altGlyph" => 1,
274
        "altGlyphDef" => 1,
275
        "altGlyphItem" => 1,
276
        "animate" => 1,
277
        "animateColor" => 1,
278
        "animateMotion" => 1,
279
        "animateTransform" => 1,
280
        "circle" => 1,
281
        "clipPath" => 1,
282
        "color-profile" => 1,
283
        "cursor" => 1,
284
        "defs" => 1,
285
        "desc" => 1,
286
        "ellipse" => 1,
287
        "feBlend" => 1,
288
        "feColorMatrix" => 1,
289
        "feComponentTransfer" => 1,
290
        "feComposite" => 1,
291
        "feConvolveMatrix" => 1,
292
        "feDiffuseLighting" => 1,
293
        "feDisplacementMap" => 1,
294
        "feDistantLight" => 1,
295
        "feFlood" => 1,
296
        "feFuncA" => 1,
297
        "feFuncB" => 1,
298
        "feFuncG" => 1,
299
        "feFuncR" => 1,
300
        "feGaussianBlur" => 1,
301
        "feImage" => 1,
302
        "feMerge" => 1,
303
        "feMergeNode" => 1,
304
        "feMorphology" => 1,
305
        "feOffset" => 1,
306
        "fePointLight" => 1,
307
        "feSpecularLighting" => 1,
308
        "feSpotLight" => 1,
309
        "feTile" => 1,
310
        "feTurbulence" => 1,
311
        "filter" => 1,
312
        "font" => 1,
313
        "font-face" => 1,
314
        "font-face-format" => 1,
315
        "font-face-name" => 1,
316
        "font-face-src" => 1,
317
        "font-face-uri" => 1,
318
        "foreignObject" => 1,
319
        "g" => 1,
320
        "glyph" => 1,
321
        "glyphRef" => 1,
322
        "hkern" => 1,
323
        "image" => 1,
324
        "line" => 1,
325
        "linearGradient" => 1,
326
        "marker" => 1,
327
        "mask" => 1,
328
        "metadata" => 1,
329
        "missing-glyph" => 1,
330
        "mpath" => 1,
331
        "path" => 1,
332
        "pattern" => 1,
333
        "polygon" => 1,
334
        "polyline" => 1,
335
        "radialGradient" => 1,
336
        "rect" => 1,
337
        "script" => 3, // NORMAL | RAW_TEXT
338
        "set" => 1,
339
        "stop" => 1,
340
        "style" => 3, // NORMAL | RAW_TEXT
341
        "svg" => 1,
342
        "switch" => 1,
343
        "symbol" => 1,
344
        "text" => 1,
345
        "textPath" => 1,
346
        "title" => 1,
347
        "tref" => 1,
348
        "tspan" => 1,
349
        "use" => 1,
350
        "view" => 1,
351
        "vkern" => 1
352
    );
353
354
    /**
355
     * Some attributes in SVG are case sensetitive.
356
     *
357
     * This map contains key/value pairs with the key as the lowercase attribute
358
     * name and the value with the correct casing.
359
     */
360
    public static $svgCaseSensitiveAttributeMap = array(
361
        'attributename' => 'attributeName',
362
        'attributetype' => 'attributeType',
363
        'basefrequency' => 'baseFrequency',
364
        'baseprofile' => 'baseProfile',
365
        'calcmode' => 'calcMode',
366
        'clippathunits' => 'clipPathUnits',
367
        'contentscripttype' => 'contentScriptType',
368
        'contentstyletype' => 'contentStyleType',
369
        'diffuseconstant' => 'diffuseConstant',
370
        'edgemode' => 'edgeMode',
371
        'externalresourcesrequired' => 'externalResourcesRequired',
372
        'filterres' => 'filterRes',
373
        'filterunits' => 'filterUnits',
374
        'glyphref' => 'glyphRef',
375
        'gradienttransform' => 'gradientTransform',
376
        'gradientunits' => 'gradientUnits',
377
        'kernelmatrix' => 'kernelMatrix',
378
        'kernelunitlength' => 'kernelUnitLength',
379
        'keypoints' => 'keyPoints',
380
        'keysplines' => 'keySplines',
381
        'keytimes' => 'keyTimes',
382
        'lengthadjust' => 'lengthAdjust',
383
        'limitingconeangle' => 'limitingConeAngle',
384
        'markerheight' => 'markerHeight',
385
        'markerunits' => 'markerUnits',
386
        'markerwidth' => 'markerWidth',
387
        'maskcontentunits' => 'maskContentUnits',
388
        'maskunits' => 'maskUnits',
389
        'numoctaves' => 'numOctaves',
390
        'pathlength' => 'pathLength',
391
        'patterncontentunits' => 'patternContentUnits',
392
        'patterntransform' => 'patternTransform',
393
        'patternunits' => 'patternUnits',
394
        'pointsatx' => 'pointsAtX',
395
        'pointsaty' => 'pointsAtY',
396
        'pointsatz' => 'pointsAtZ',
397
        'preservealpha' => 'preserveAlpha',
398
        'preserveaspectratio' => 'preserveAspectRatio',
399
        'primitiveunits' => 'primitiveUnits',
400
        'refx' => 'refX',
401
        'refy' => 'refY',
402
        'repeatcount' => 'repeatCount',
403
        'repeatdur' => 'repeatDur',
404
        'requiredextensions' => 'requiredExtensions',
405
        'requiredfeatures' => 'requiredFeatures',
406
        'specularconstant' => 'specularConstant',
407
        'specularexponent' => 'specularExponent',
408
        'spreadmethod' => 'spreadMethod',
409
        'startoffset' => 'startOffset',
410
        'stddeviation' => 'stdDeviation',
411
        'stitchtiles' => 'stitchTiles',
412
        'surfacescale' => 'surfaceScale',
413
        'systemlanguage' => 'systemLanguage',
414
        'tablevalues' => 'tableValues',
415
        'targetx' => 'targetX',
416
        'targety' => 'targetY',
417
        'textlength' => 'textLength',
418
        'viewbox' => 'viewBox',
419
        'viewtarget' => 'viewTarget',
420
        'xchannelselector' => 'xChannelSelector',
421
        'ychannelselector' => 'yChannelSelector',
422
        'zoomandpan' => 'zoomAndPan'
423
    );
424
425
    /**
426
     * Some SVG elements are case sensetitive.
427
     * This map contains these.
428
     *
429
     * The map contains key/value store of the name is lowercase as the keys and
430
     * the correct casing as the value.
431
     */
432
    public static $svgCaseSensitiveElementMap = array(
433
        'altglyph' => 'altGlyph',
434
        'altglyphdef' => 'altGlyphDef',
435
        'altglyphitem' => 'altGlyphItem',
436
        'animatecolor' => 'animateColor',
437
        'animatemotion' => 'animateMotion',
438
        'animatetransform' => 'animateTransform',
439
        'clippath' => 'clipPath',
440
        'feblend' => 'feBlend',
441
        'fecolormatrix' => 'feColorMatrix',
442
        'fecomponenttransfer' => 'feComponentTransfer',
443
        'fecomposite' => 'feComposite',
444
        'feconvolvematrix' => 'feConvolveMatrix',
445
        'fediffuselighting' => 'feDiffuseLighting',
446
        'fedisplacementmap' => 'feDisplacementMap',
447
        'fedistantlight' => 'feDistantLight',
448
        'feflood' => 'feFlood',
449
        'fefunca' => 'feFuncA',
450
        'fefuncb' => 'feFuncB',
451
        'fefuncg' => 'feFuncG',
452
        'fefuncr' => 'feFuncR',
453
        'fegaussianblur' => 'feGaussianBlur',
454
        'feimage' => 'feImage',
455
        'femerge' => 'feMerge',
456
        'femergenode' => 'feMergeNode',
457
        'femorphology' => 'feMorphology',
458
        'feoffset' => 'feOffset',
459
        'fepointlight' => 'fePointLight',
460
        'fespecularlighting' => 'feSpecularLighting',
461
        'fespotlight' => 'feSpotLight',
462
        'fetile' => 'feTile',
463
        'feturbulence' => 'feTurbulence',
464
        'foreignobject' => 'foreignObject',
465
        'glyphref' => 'glyphRef',
466
        'lineargradient' => 'linearGradient',
467
        'radialgradient' => 'radialGradient',
468
        'textpath' => 'textPath'
469
    );
470
471
    /**
472
     * Check whether the given element meets the given criterion.
473
     *
474
     * Example:
475
     *
476
     * Elements::isA('script', Elements::TEXT_RAW); // Returns true.
477
     *
478
     * Elements::isA('script', Elements::TEXT_RCDATA); // Returns false.
479
     *
480
     * @param string $name
481
     *            The element name.
482
     * @param int $mask
483
     *            One of the constants on this class.
484
     * @return boolean true if the element matches the mask, false otherwise.
485
     */
486 107
    public static function isA($name, $mask)
487
    {
488 107
        if (! static::isElement($name)) {
489 16
            return false;
490
        }
491
492 106
        return (static::element($name) & $mask) == $mask;
493
    }
494
495
    /**
496
     * Test if an element is a valid html5 element.
497
     *
498
     * @param string $name
499
     *            The name of the element.
500
     *
501
     * @return bool True if a html5 element and false otherwise.
502
     */
503 110
    public static function isHtml5Element($name)
504
    {
505
        // html5 element names are case insensetitive. Forcing lowercase for the check.
506
        // Do we need this check or will all data passed here already be lowercase?
507 110
        return isset(static::$html5[strtolower($name)]);
508
    }
509
510
    /**
511
     * Test if an element name is a valid MathML presentation element.
512
     *
513
     * @param string $name
514
     *            The name of the element.
515
     *
516
     * @return bool True if a MathML name and false otherwise.
517
     */
518 25
    public static function isMathMLElement($name)
519
    {
520
        // MathML is case-sensetitive unlike html5 elements.
521 25
        return isset(static::$mathml[$name]);
522
    }
523
524
    /**
525
     * Test if an element is a valid SVG element.
526
     *
527
     * @param string $name
528
     *            The name of the element.
529
     *
530
     * @return boolean True if a SVG element and false otherise.
531
     */
532 22
    public static function isSvgElement($name)
533
    {
534
        // SVG is case-sensetitive unlike html5 elements.
535 22
        return isset(static::$svg[$name]);
536
    }
537
538
    /**
539
     * Is an element name valid in an html5 document.
540
     *
541
     * This includes html5 elements along with other allowed embedded content
542
     * such as svg and mathml.
543
     *
544
     * @param string $name
545
     *            The name of the element.
546
     *
547
     * @return bool True if valid and false otherwise.
548
     */
549 108
    public static function isElement($name)
550
    {
551 108
        return static::isHtml5Element($name) || static::isMathMLElement($name) || static::isSvgElement($name);
552
    }
553
554
    /**
555
     * Get the element mask for the given element name.
556
     *
557
     * @param string $name
558
     *            The name of the element.
559
     *
560
     * @return int|bool The element mask or false if element does not exist.
561
     */
562 108
    public static function element($name)
563
    {
564 108
        if (isset(static::$html5[$name])) {
565 107
            return static::$html5[$name];
566
        }
567 24
        if (isset(static::$svg[$name])) {
568 9
            return static::$svg[$name];
569
        }
570 20
        if (isset(static::$mathml[$name])) {
571 7
            return static::$mathml[$name];
572
        }
573
574 17
        return false;
575
    }
576
577
    /**
578
     * Normalize a SVG element name to its proper case and form.
579
     *
580
     * @param string $name
581
     *            The name of the element.
582
     *
583
     * @return string The normalized form of the element name.
584
     */
585 9
    public static function normalizeSvgElement($name)
586
    {
587 9
        $name = strtolower($name);
588 9
        if (isset(static::$svgCaseSensitiveElementMap[$name])) {
589 4
            $name = static::$svgCaseSensitiveElementMap[$name];
590 4
        }
591
592 9
        return $name;
593
    }
594
595
    /**
596
     * Normalize a SVG attribute name to its proper case and form.
597
     *
598
     * @param string $name
599
     *            The name of the attribute.
600
     *
601
     * @return string The normalized form of the attribute name.
602
     */
603 9
    public static function normalizeSvgAttribute($name)
604
    {
605 9
        $name = strtolower($name);
606 9
        if (isset(static::$svgCaseSensitiveAttributeMap[$name])) {
607 6
            $name = static::$svgCaseSensitiveAttributeMap[$name];
608 6
        }
609
610 9
        return $name;
611
    }
612
613
    /**
614
     * Normalize a MathML attribute name to its proper case and form.
615
     *
616
     * Note, all MathML element names are lowercase.
617
     *
618
     * @param string $name
619
     *            The name of the attribute.
620
     *
621
     * @return string The normalized form of the attribute name.
622
     */
623 5
    public static function normalizeMathMlAttribute($name)
624
    {
625 5
        $name = strtolower($name);
626
627
        // Only one attribute has a mixed case form for MathML.
628 5
        if ($name == 'definitionurl') {
629 5
            $name = 'definitionURL';
630 5
        }
631
632 5
        return $name;
633
    }
634
}
635