-
-
Save Zegnat/4fcfff20741a5f78a73bc7b717fd8396 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace Zegnat; | |
final class PleaseNo | |
{ | |
/** | |
* Returns a DOM element’s text content as if the DOM had been rendered through an | |
* approximate implementation of the HTML specification’s innerText getter. | |
* | |
* @see https://html.spec.whatwg.org/#dom-innertext | |
**/ | |
public function innerText(\DOMElement $element): string | |
{ | |
if ($this->isBeingRendered($element) === false) { | |
return $element->textContent; | |
} | |
$count = 0; | |
$output = ''; | |
foreach ($this->innerTextCollectionSteps($element) as $item) { | |
if ($output !== '' && is_int($item) && $item > $count) { | |
$count = $item; | |
} elseif (is_string($item) && $item !== '') { | |
$output .= str_repeat("\n", $count) . $item; | |
$count = 0; | |
} | |
} | |
return $output; | |
} | |
/** | |
* Check if a DOM node should be rendered per section 14 Rendering of the HTML | |
* specification. If a node’s `display` value is none, it is not being rendered. | |
* | |
* For non-Element nodes it is assumed they use whatever value the closest Element | |
* parent is using. | |
* | |
* @TODO Decide if noscript elements are rendered. | |
* @TODO Decide if elements that represent nothing (e.g. template) are rendered. | |
* @TODO Check if any parent elements are not being rendered, as this cascades down. | |
* | |
* @see https://html.spec.whatwg.org/#hidden-elements 14.3.1 Hidden elements | |
* @see https://html.spec.whatwg.org/#tables-2 14.3.9 Tables | |
**/ | |
private function isBeingRendered(\DOMNode $element): bool | |
{ | |
// When this runs on a non-Element, walk up the tree to the closest element. | |
while (!$element instanceof \DOMElement) { | |
$element = $element->parentNode; | |
} | |
// List of elements that always have `display: none`. | |
$elements = ['area', 'base', 'basefont', 'datalist', 'head', 'link', 'meta', | |
'noembed', 'noframes', 'param', 'rp', 'script', 'source', 'style', 'template', | |
'track', 'title']; | |
// List of elements that are still rendered with the hidden attribute set. | |
$exceptions = ['embed', 'colgroup', 'col', 'thead', 'tbody', 'tfoot', 'tr', 'td', | |
'th']; | |
// List of parents that stop a form element from rendering. | |
$form = ['table', 'thead', 'tbody', 'tfoot', 'tr']; | |
// Figure it out! | |
$name = strtolower($element->tagName); | |
return !(in_array($name, $elements) || | |
$element->hasAttribute('hidden') && !in_array($name, $exceptions) || | |
$name === 'input' && strtolower($element->getAttribute('type')) === 'hidden' || | |
$name === 'form' && in_array(strtolower($element->parentNode->tagName), $form)); | |
} | |
/** | |
* @TODO Implement. | |
* | |
* @see https://html.spec.whatwg.org/#inner-text-collection-steps | |
**/ | |
private function innerTextCollectionSteps(\DOMNode $node): array | |
{ | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment