Module: Dommy::Internal::AriaSnapshot

Defined in:
lib/dommy/internal/aria_snapshot.rb

Overview

Serializes an AccessibilityTree into a Playwright-compatible ARIA snapshot (a YAML-ish indented outline). Each accessible node is a line

- <role> "<name>" [flag] [level=N]:

with a trailing ":" only when it has children, 2-space indentation per depth, and significant text as - text: "…". The synthetic root is not printed (a document has no top line), matching Playwright.

Constant Summary collapse

FLAG_ORDER =

The serialized flags, in fixed render order. A boolean flag renders only when true or "mixed"; level renders as [level=N]. readonly and required are computed (AriaState) but NOT serialized — Playwright emits neither in its snapshot — so they stay out of this list.

%i[checked disabled expanded level pressed selected].freeze

Class Method Summary collapse

Class Method Details

.emit(node, depth, lines) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/dommy/internal/aria_snapshot.rb', line 30

def emit(node, depth, lines)
  indent = "  " * depth
  if node.text?
    lines << "#{indent}- text: #{quote(node.name)}"
    return
  end

  header = "#{indent}- #{node.role}"
  header += " #{quote(node.name)}" unless node.name.to_s.empty?
  flags(node.states).each { |flag| header += " #{flag}" }
  header += ":" unless node.children.empty?
  lines << header

  node.children.each { |child| emit(child, depth + 1, lines) }
end

.flags(states) ⇒ Object

The bracketed flag tokens for a node's states, in FLAG_ORDER. Booleans render only when true/"mixed"; a "mixed" value renders [flag=mixed].



48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/dommy/internal/aria_snapshot.rb', line 48

def flags(states)
  FLAG_ORDER.filter_map do |key|
    value = states[key]
    if key == :level
      "[level=#{value}]" if value
    elsif value == "mixed"
      "[#{key}=mixed]"
    elsif value == true
      "[#{key}]"
    end
  end
end

.quote(text) ⇒ Object



61
# File 'lib/dommy/internal/aria_snapshot.rb', line 61

def quote(text) = "\"#{text.to_s.gsub("\\", "\\\\\\\\").gsub("\"", "\\\"")}\""

.serialize(root) ⇒ Object



22
23
24
25
26
27
28
# File 'lib/dommy/internal/aria_snapshot.rb', line 22

def serialize(root)
  lines = []
  root.children.each { |child| emit(child, 0, lines) }
  return "" if lines.empty?

  "#{lines.join("\n")}\n"
end