1<?php 2 3namespace dokuwiki\plugin\prosemirror\schema; 4 5/** 6 * Class Node 7 * 8 * @package dokuwiki\plugin\prosemirror\schema 9 * @link http://prosemirror.net/ref.html#model.Node 10 */ 11class Node implements \JsonSerializable 12{ 13 14 /** @var string The type of node that this is */ 15 protected $type; 16 17 /** @var Node[] holding the node's children */ 18 protected $content = []; 19 20 /** @var string For text nodes, this contains the node's text content. */ 21 protected $text = null; 22 23 /** @var Mark[] The marks (things like whether it is emphasized or part of a link) associated with this node */ 24 protected $marks = []; 25 26 /** @var array list of attributes */ 27 protected $attrs = []; 28 29 /** 30 * Node constructor. 31 * 32 * @param string $type 33 */ 34 public function __construct($type) 35 { 36 $this->type = $type; 37 if ($type == 'text') { 38 $this->setText(''); 39 } 40 } 41 42 /** 43 * @param Node $child 44 */ 45 public function addChild(Node $child) 46 { 47 if ($this->type == 'text') { 48 throw new \RuntimeException('TextNodes may not have children'); 49 } 50 $this->content[] = $child; 51 } 52 53 /** 54 * @param Mark $mark 55 */ 56 public function addMark(Mark $mark) 57 { 58 $this->marks[] = $mark; 59 } 60 61 /** 62 * @return string 63 */ 64 public function getType() 65 { 66 return $this->type; 67 } 68 69 /** 70 * @return string 71 */ 72 public function getText() 73 { 74 return $this->text; 75 } 76 77 /** 78 * @param string $text 79 */ 80 public function setText($text) 81 { 82 if ($this->type != 'text') { 83 throw new \RuntimeException('Non-TextNodes may not have text'); 84 } 85 $this->text = $text; 86 } 87 88 /** 89 * @param string $key Attribute key to get or set 90 * @param null $value Attribute value to set, null to get 91 * 92 * @return $this|mixed Either the wanted value or the Node itself 93 */ 94 public function attr($key, $value = null) 95 { 96 if (is_null($value)) { 97 if (isset($this->attrs[$key])) { 98 return $this->attrs[$key]; 99 } else { 100 return null; 101 } 102 } 103 104 $this->attrs[$key] = $value; 105 return $this; 106 } 107 108 /** 109 * Specify data which should be serialized to JSON 110 * 111 * @link http://php.net/manual/en/jsonserializable.jsonserialize.php 112 * @return mixed data which can be serialized by <b>json_encode</b>, 113 * which is a value of any type other than a resource. 114 * @since 5.4.0 115 */ 116 function jsonSerialize() 117 { 118 $json = [ 119 'type' => $this->type, 120 ]; 121 if ($this->type == 'text') { 122 $json['text'] = $this->text; 123 } elseif ($this->content) { 124 $json['content'] = $this->content; 125 } 126 127 if ($this->marks) { 128 $json['marks'] = $this->marks; 129 } 130 if ($this->attrs) { 131 $json['attrs'] = $this->attrs; 132 } 133 134 return $json; 135 } 136 137 /** 138 * Check if any child nodes have been added to this node 139 * 140 * @return bool 141 */ 142 public function hasContent() { 143 return !empty($this->content); 144 } 145 146 /** 147 * Trim all whitespace from the beginning of this node's content 148 * 149 * If this is a text-node then this node's text is left-trimmed 150 * 151 * If the first node in the content is afterwards only an empty string, then it is removed 152 * 153 * @return void 154 */ 155 public function trimContentLeft() { 156 if ($this->hasContent()) { 157 $this->content[0]->trimContentLeft(); 158 if ($this->content[0]->getText() === '') { 159 array_shift($this->content); 160 } 161 return; 162 } 163 if ($this->text !== null) { 164 $this->text = ltrim($this->text); 165 } 166 } 167 168 /** 169 * Trim all whitespace from the end of this node's content 170 * 171 * If this is a text-node then this node's text is right-trimmed 172 * 173 * If the last node in the content is afterwards only an empty string, then it is removed 174 * 175 * @return void 176 */ 177 public function trimContentRight() { 178 if ($this->hasContent()) { 179 $contentLength = count($this->content) - 1; 180 $this->content[$contentLength]->trimContentRight(); 181 if ($this->content[$contentLength]->getText() === '') { 182 array_pop($this->content); 183 } 184 return; 185 } 186 if ($this->text !== null) { 187 $this->text = rtrim($this->text); 188 } 189 } 190} 191