Blame view

public/vendor/masterminds/html5/src/HTML5/Parser/TreeBuildingRules.php 3.2 KB
86143e36f   Андрей Ларионов   Коммит вторник
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
  <?php
  
  namespace Masterminds\HTML5\Parser;
  
  /**
   * Handles special-case rules for the DOM tree builder.
   *
   * Many tags have special rules that need to be accomodated on an
   * individual basis. This class handles those rules.
   *
   * See section 8.1.2.4 of the spec.
   *
   * @todo - colgroup and col special behaviors
   *       - body and head special behaviors
   */
  class TreeBuildingRules
  {
      protected static $tags = array(
          'li' => 1,
          'dd' => 1,
          'dt' => 1,
          'rt' => 1,
          'rp' => 1,
          'tr' => 1,
          'th' => 1,
          'td' => 1,
          'thead' => 1,
          'tfoot' => 1,
          'tbody' => 1,
          'table' => 1,
          'optgroup' => 1,
          'option' => 1,
      );
  
      /**
       * Returns true if the given tagname has special processing rules.
       */
      public function hasRules($tagname)
      {
          return isset(static::$tags[$tagname]);
      }
  
      /**
       * Evaluate the rule for the current tag name.
       *
       * This may modify the existing DOM.
       *
       * @return \DOMElement The new Current DOM element.
       */
      public function evaluate($new, $current)
      {
          switch ($new->tagName) {
              case 'li':
                  return $this->handleLI($new, $current);
              case 'dt':
              case 'dd':
                  return $this->handleDT($new, $current);
              case 'rt':
              case 'rp':
                  return $this->handleRT($new, $current);
              case 'optgroup':
                  return $this->closeIfCurrentMatches($new, $current, array(
                      'optgroup',
                  ));
              case 'option':
                  return $this->closeIfCurrentMatches($new, $current, array(
                      'option',
                  ));
              case 'tr':
                  return $this->closeIfCurrentMatches($new, $current, array(
                      'tr',
                  ));
              case 'td':
              case 'th':
                  return $this->closeIfCurrentMatches($new, $current, array(
                      'th',
                      'td',
                  ));
              case 'tbody':
              case 'thead':
              case 'tfoot':
              case 'table': // Spec isn't explicit about this, but it's necessary.
  
                  return $this->closeIfCurrentMatches($new, $current, array(
                      'thead',
                      'tfoot',
                      'tbody',
                  ));
          }
  
          return $current;
      }
  
      protected function handleLI($ele, $current)
      {
          return $this->closeIfCurrentMatches($ele, $current, array(
              'li',
          ));
      }
  
      protected function handleDT($ele, $current)
      {
          return $this->closeIfCurrentMatches($ele, $current, array(
              'dt',
              'dd',
          ));
      }
  
      protected function handleRT($ele, $current)
      {
          return $this->closeIfCurrentMatches($ele, $current, array(
              'rt',
              'rp',
          ));
      }
  
      protected function closeIfCurrentMatches($ele, $current, $match)
      {
          if (in_array($current->tagName, $match, true)) {
              $current->parentNode->appendChild($ele);
          } else {
              $current->appendChild($ele);
          }
  
          return $ele;
      }
  }