8 * This class repesents a list of key symbols used by an
9 * HTML document, such as element (tag) names, attribute
10 * names, and CSS class names.
16 * Array(string $element => int $count).
18 public $elements = [];
22 * Array(string $class => int $count).
28 * Array(string $attr => int $count).
30 public $attributes = [];
36 public static function scan($html) {
37 $symbols = new static();
38 $doc = new \
DOMDocumentWrapper($html, 'text/html');
39 $symbols->scanNode($doc->root
);
43 protected function scanNode(\DOMNode
$node) {
44 if ($node instanceof \DOMElement
) {
46 self
::increment($this->elements
, $node->tagName
);
48 foreach ($node->childNodes
as $childNode) {
49 $this->scanNode($childNode);
52 foreach ($node->attributes
as $attribute) {
53 $this->scanNode($attribute);
57 elseif ($node instanceof \DOMAttr
) {
58 self
::increment($this->attributes
, $node->nodeName
);
60 if ($node->nodeName
=== 'class') {
61 $classes = $this->parseClasses($node->nodeValue
);
62 foreach ($classes as $class) {
63 self
::increment($this->classes
, $class);
71 * Ex: 'crm-icon fa-mail'
73 * Ex: ['crm-icon', 'fa-mail']
75 protected function parseClasses($expr) {
76 if ($expr === '' ||
$expr === NULL ||
$expr === FALSE) {
79 if (strpos($expr, '{{') === FALSE) {
80 return explode(' ', $expr);
82 if (preg_match_all(';([a-zA-Z\-_]+|\{\{.*\}\}) ;U', "$expr ", $m)) {
85 error_log("Failed to parse CSS classes: $expr");
89 private static function increment(&$arr, $key) {
90 if (!isset($arr[$key])) {