2 namespace mdref\Formatter
;
6 use ReflectionExtension
;
10 protected $docref = "https://php.net/manual/en/%s";
12 "language.types.declarations#language.types.declarations.%s" => ["void", "mixed"],
13 "language.types.%s" => ["null", "boolean", "integer", "float", "string", "resource", "array", "callable", "iterable"],
14 "language.types.null" => ["NULL"],
15 "language.types.boolean" => ["true", "TRUE", "false", "FALSE", "bool", "BOOL"],
16 "language.types.integer" => ["int", "long"],
17 "language.types.float" => ["double", "real"],
18 "language.types.object" => ["stdClass"],
19 "language.types.callable" => ["callback"],
20 "language.types.enumerations" => ["enum"],
21 "language.references" => ["reference"],
23 protected $exts = ["standard", "core", "spl", "json", "date"];
26 protected Formatter
$fmt
29 public function wrap(DOMText
$node, $pld) : void
{
32 $split = "[&?\(\)\|\"'\s\][\.,-]+";
33 $items = preg_split("/($split)/", $node->textContent
, 0, PREG_SPLIT_DELIM_CAPTURE
);
34 foreach ($items as $item) {
35 if (preg_match("/^($split|[[:punct:]+])*$/", $item)) {
36 $nodes[] = $node->ownerDocument
->createTextNode($item);
40 $new = $this->wrapType($node, $item, $pld)
41 ?
: $this->wrapKeyWord($node, $item, $pld)
42 ?
: $this->wrapSpecial($node, $item, $pld);
49 $nodes[] = $node->ownerDocument
->createTextNode($item);
53 $parent = $node->parentNode
;
54 $new_node = array_pop($nodes);
55 $parent->replaceChild($new_node, $node);
56 foreach ($nodes as $prev_node) {
57 $parent->insertBefore($prev_node, $new_node);
62 protected function getType(string $item) : ?
string {
65 foreach ($this->types
as $doc => $list) foreach ($list as $type) {
66 $types[$type] = sprintf($this->docref
, sprintf($doc, $type));
68 foreach ($this->exts
as $ext) foreach ((new ReflectionExtension($ext))->getClassNames() as $class) {
69 $types[$class] = sprintf($this->docref
, "class." . strtolower($class));
73 $item = trim($item, "\\");
74 if (!isset($types[$item])) {
79 protected function wrapType(DOMText
$node, string $item, $pld) : ?DOMNode
{
80 if (!($type = $this->getType($item))) {
83 $a = $node->ownerDocument
->createElement("a");
84 $a->setAttribute("href", $type);
85 $a->textContent
= $item;
86 $code = $node->ownerDocument
->createElement("code");
87 $code->insertBefore($a);
91 protected function wrapKeyword(DOMText
$node, string $item, $pld) : DomNode|
array|
null {
94 if ($node->parentNode
->nodeName
!== "h1") {
99 if ($node->parentNode
->nodeName
=== "h1") {
101 $node->ownerDocument
->createElement("br"),
102 $node->ownerDocument
->createEntityReference("nbsp"),
103 $new = $node->ownerDocument
->createElement("em")
105 $new->textContent
= $item;
120 $new = $node->ownerDocument
->createElement("em");
121 $new->textContent
= $item;
127 protected function isFirstDeclaration(DOMNode
$node, string $item, bool $is_slug = false) : bool {
128 return $node->parentNode
->nodeName
=== "li"
129 && !$node->ownerDocument
->getElementById($is_slug ?
$item : $this->fmt
->formatSlug($item));
132 protected function isVar(string $item) : bool {
133 return str_starts_with($item, "\$");
136 protected function wrapVar(DOMNode
$node, string $item, $pld) : DOMNode
{
137 $ele = $node->ownerDocument
->createElement("span");
138 $ele->setAttribute("class", "var");
139 $ele->textContent
= $item;
141 if (!empty($pld->currentSection
)) {
142 $slug = $this->fmt
->formatSlug($item);
143 if ($this->isFirstDeclaration($node, $slug, true)) {
144 $perm = $this->fmt
->createPermaLink($ele, $slug, $pld);
145 $ele->insertBefore($perm);
151 protected function isNamespaced(DOMNode
$node, string $item, $pld) : bool {
152 return str_contains($item, "\\") ||
str_contains($item, "::");
155 protected function wrapNamespaced(DOMNode
$node, string $item, $pld) : ?DOMNode
{
156 $href = preg_replace("/\\\\|::/", "/", trim($item, "\\:"));
158 $repo = $pld->refs
->getRepoForEntry($href, $canonical);
161 if (!empty($canonical)) {
164 $link = $node->ownerDocument
->createElement("a");
165 $link->setAttribute("href", $href);
166 $link->textContent
= $item;
170 $hash = basename($href);
171 $href = dirname($href);
172 $repo = $pld->refs
->getRepoForEntry($href, $canonical);
174 if (!empty($canonical)) {
177 $link = $node->ownerDocument
->createElement("a");
178 $link->setAttribute("href", "$href#$hash");
179 $link->textContent
= $item;
186 protected function wrapConstant(DOMNode
$node, string $item, $pld) : ?DOMNode
{
188 if (!empty($pld->currentSection
)) {
189 switch ($pld->currentSection
) {
196 if (preg_match("/^[A-Z]({$strict}[A-Z0-9_v])+\$/", $item)) {
197 // assume some constant
198 $span = $node->ownerDocument
->createElement("span");
199 $span->setAttribute("class", "constant");
200 $span->textContent
= $item;
201 if (!$strict && $pld->currentSection
=== "Constants:" && $node->parentNode
->nodeName
=== "li" && $node->parentNode
->firstChild
=== $node) {
202 $perm = $this->fmt
->createPermaLink($span, $this->fmt
->formatSlug($item), $pld);
203 $span->insertBefore($perm);
211 protected function wrapSpecial(DOMNode
$node, string $item, $pld) : ?DOMNode
{
212 if ($this->isVar($item)) {
213 if (($ele = $this->wrapVar($node, $item, $pld))) {
217 if ($this->isNamespaced($node, $item, $pld)) {
218 if (($ele = $this->wrapNamespaced($node, $item, $pld))) {
222 return $this->wrapConstant($node, $item, $pld);