lazycodex-ai 5.0.0-beta.85 → 5.0.0-beta.87

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/index.js +68 -41
  3. package/dist/cli-node/index.js +68 -41
  4. package/package.json +1 -1
  5. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  6. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +2 -0
  7. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  8. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  9. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  10. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  11. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  12. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  13. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  14. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  15. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
  16. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  17. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  18. package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus/gpt-6.md +1 -1
  19. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  20. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  21. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  22. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  23. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  24. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  25. package/packages/omo-codex/plugin/components/ultrawork/README.md +1 -1
  26. package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +2 -2
  27. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +63 -89
  28. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  29. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  30. package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +1 -1
  31. package/packages/omo-codex/plugin/components/ulw-execute-continuation/directive.md +2 -2
  32. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
  33. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
  34. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +63 -89
  35. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
  36. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  37. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/define-goal.md +2 -3
  38. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +2 -2
  39. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  40. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  41. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  42. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  43. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  44. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  45. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  46. package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
  47. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  48. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  49. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  50. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  51. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  52. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  53. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  54. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  55. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  56. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  57. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  58. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  59. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  60. package/packages/omo-codex/plugin/package-lock.json +12 -12
  61. package/packages/omo-codex/plugin/package.json +1 -1
  62. package/packages/omo-codex/plugin/scripts/materialize-shared-upstreams.mjs +8 -2
  63. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +2 -2
  64. package/packages/omo-codex/plugin/skills/browser/ATTRIBUTION.md +26 -14
  65. package/packages/omo-codex/plugin/skills/browser/SKILL.md +65 -52
  66. package/packages/omo-codex/plugin/skills/browser/references/commands.md +81 -66
  67. package/packages/omo-codex/plugin/skills/browser/references/install.md +31 -34
  68. package/packages/omo-codex/plugin/skills/browser/references/owned-engine/README.md +41 -21
  69. package/packages/omo-codex/plugin/skills/browser/references/owned-engine/frames-and-humans.md +33 -20
  70. package/packages/omo-codex/plugin/skills/browser/references/owned-engine/ladder.md +24 -22
  71. package/packages/omo-codex/plugin/skills/browser/references/owned-engine/network.md +35 -15
  72. package/packages/omo-codex/plugin/skills/browser/references/recipes/1password.md +13 -11
  73. package/packages/omo-codex/plugin/skills/browser/references/remote.md +5 -4
  74. package/packages/omo-codex/plugin/skills/browser/runtime/omowright/index.js +1534 -0
  75. package/packages/omo-codex/plugin/skills/browser/runtime/omowright/manifest.json +9 -0
  76. package/packages/omo-codex/plugin/skills/browser/runtime/omowright/page-bundle.js +1395 -0
  77. package/packages/omo-codex/plugin/skills/browser/scripts/browser-doctor.mjs +37 -32
  78. package/packages/omo-codex/plugin/skills/browser/scripts/browser-install.mjs +31 -44
  79. package/packages/omo-codex/plugin/skills/browser/scripts/omowright.mjs +25 -0
  80. package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -2
  81. package/packages/omo-codex/plugin/skills/debugging/references/methodology/06-fix.md +3 -3
  82. package/packages/omo-codex/plugin/skills/debugging/references/methodology/08-qa.md +1 -1
  83. package/packages/omo-codex/plugin/skills/debugging/references/tools/browser-qa.md +104 -0
  84. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +1 -1
  85. package/packages/omo-codex/plugin/skills/frontend/references/design/clone-from-url.md +1 -1
  86. package/packages/omo-codex/plugin/skills/programming/SKILL.md +12 -18
  87. package/packages/omo-codex/plugin/skills/programming/references/rust/README.md +43 -15
  88. package/packages/omo-codex/plugin/skills/programming/references/rust/api-design.md +81 -0
  89. package/packages/omo-codex/plugin/skills/programming/references/rust/async-tokio.md +60 -28
  90. package/packages/omo-codex/plugin/skills/programming/references/rust/axum-stack.md +1 -13
  91. package/packages/omo-codex/plugin/skills/programming/references/rust/cargo-strict.md +44 -8
  92. package/packages/omo-codex/plugin/skills/programming/references/rust/clap-stack.md +8 -3
  93. package/packages/omo-codex/plugin/skills/programming/references/rust/concurrency.md +66 -52
  94. package/packages/omo-codex/plugin/skills/programming/references/rust/libraries.md +35 -25
  95. package/packages/omo-codex/plugin/skills/programming/references/rust/macros.md +63 -0
  96. package/packages/omo-codex/plugin/skills/programming/references/rust/one-liners.md +5 -3
  97. package/packages/omo-codex/plugin/skills/programming/references/rust/proptest-insta.md +8 -0
  98. package/packages/omo-codex/plugin/skills/programming/references/rust/type-state.md +50 -12
  99. package/packages/omo-codex/plugin/skills/programming/references/rust/unsafe-discipline.md +34 -6
  100. package/packages/omo-codex/plugin/skills/programming/references/rust/zero-cost-safety.md +62 -52
  101. package/packages/omo-codex/plugin/skills/programming/references/rust-ub/miri-sanitizers-loom.md +1 -1
  102. package/packages/omo-codex/plugin/skills/programming/references/rust-ub/ub-taxonomy.md +6 -3
  103. package/packages/omo-codex/plugin/skills/programming/scripts/rust/check-no-excuse-rules.sh +86 -75
  104. package/packages/omo-codex/plugin/skills/programming/scripts/rust/new-project.py +31 -28
  105. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +1 -1
  106. package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +27 -20
  107. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +1 -1
  108. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +32 -100
  109. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +5 -11
  110. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/playwright.md +20 -37
  111. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +63 -89
  112. package/packages/omo-codex/plugin/skills/ulw-execute/SKILL.md +4 -4
  113. package/packages/omo-codex/plugin/skills/ulw-loop/references/define-goal.md +2 -3
  114. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +2 -2
  115. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +1 -1
  116. package/packages/omo-codex/plugin/skills/visual-qa/references/browser-setup.md +46 -46
  117. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +2 -2
  118. package/packages/omo-codex/scripts/install-dist/install-local.mjs +4 -2
  119. package/packages/prompts-core/prompts/ultrawork/codex.md +63 -89
  120. package/packages/shared-skills/skills/browser/ATTRIBUTION.md +26 -14
  121. package/packages/shared-skills/skills/browser/SKILL.md +65 -52
  122. package/packages/shared-skills/skills/browser/references/commands.md +81 -66
  123. package/packages/shared-skills/skills/browser/references/install.md +31 -34
  124. package/packages/shared-skills/skills/browser/references/owned-engine/README.md +41 -21
  125. package/packages/shared-skills/skills/browser/references/owned-engine/frames-and-humans.md +33 -20
  126. package/packages/shared-skills/skills/browser/references/owned-engine/ladder.md +24 -22
  127. package/packages/shared-skills/skills/browser/references/owned-engine/network.md +35 -15
  128. package/packages/shared-skills/skills/browser/references/recipes/1password.md +13 -11
  129. package/packages/shared-skills/skills/browser/references/remote.md +5 -4
  130. package/packages/shared-skills/skills/browser/runtime/omowright/index.js +1534 -0
  131. package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +9 -0
  132. package/packages/shared-skills/skills/browser/runtime/omowright/page-bundle.js +1395 -0
  133. package/packages/shared-skills/skills/browser/scripts/browser-doctor.mjs +37 -32
  134. package/packages/shared-skills/skills/browser/scripts/browser-install.mjs +31 -44
  135. package/packages/shared-skills/skills/browser/scripts/omowright.mjs +25 -0
  136. package/packages/shared-skills/skills/debugging/SKILL.md +2 -2
  137. package/packages/shared-skills/skills/debugging/references/methodology/06-fix.md +3 -3
  138. package/packages/shared-skills/skills/debugging/references/methodology/08-qa.md +1 -1
  139. package/packages/shared-skills/skills/debugging/references/tools/browser-qa.md +104 -0
  140. package/packages/shared-skills/skills/frontend/SKILL.md +1 -1
  141. package/packages/shared-skills/skills/frontend/references/design/clone-from-url.md +1 -1
  142. package/packages/shared-skills/skills/programming/SKILL.md +12 -18
  143. package/packages/shared-skills/skills/programming/references/rust/README.md +43 -15
  144. package/packages/shared-skills/skills/programming/references/rust/api-design.md +81 -0
  145. package/packages/shared-skills/skills/programming/references/rust/async-tokio.md +60 -28
  146. package/packages/shared-skills/skills/programming/references/rust/axum-stack.md +1 -13
  147. package/packages/shared-skills/skills/programming/references/rust/cargo-strict.md +44 -8
  148. package/packages/shared-skills/skills/programming/references/rust/clap-stack.md +8 -3
  149. package/packages/shared-skills/skills/programming/references/rust/concurrency.md +66 -52
  150. package/packages/shared-skills/skills/programming/references/rust/libraries.md +35 -25
  151. package/packages/shared-skills/skills/programming/references/rust/macros.md +63 -0
  152. package/packages/shared-skills/skills/programming/references/rust/one-liners.md +5 -3
  153. package/packages/shared-skills/skills/programming/references/rust/proptest-insta.md +8 -0
  154. package/packages/shared-skills/skills/programming/references/rust/type-state.md +50 -12
  155. package/packages/shared-skills/skills/programming/references/rust/unsafe-discipline.md +34 -6
  156. package/packages/shared-skills/skills/programming/references/rust/zero-cost-safety.md +62 -52
  157. package/packages/shared-skills/skills/programming/references/rust-ub/miri-sanitizers-loom.md +1 -1
  158. package/packages/shared-skills/skills/programming/references/rust-ub/ub-taxonomy.md +6 -3
  159. package/packages/shared-skills/skills/programming/scripts/rust/check-no-excuse-rules.sh +86 -75
  160. package/packages/shared-skills/skills/programming/scripts/rust/check-no-excuse-rules.test.ts +83 -0
  161. package/packages/shared-skills/skills/programming/scripts/rust/new-project.py +31 -28
  162. package/packages/shared-skills/skills/review-work/SKILL.md +1 -1
  163. package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +27 -20
  164. package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +1 -1
  165. package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +32 -100
  166. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +5 -11
  167. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/playwright.md +20 -37
  168. package/packages/shared-skills/skills/ulw-execute/SKILL.md +4 -4
  169. package/packages/shared-skills/skills/visual-qa/SKILL.md +1 -1
  170. package/packages/shared-skills/skills/visual-qa/references/browser-setup.md +46 -46
  171. package/packages/omo-codex/plugin/skills/browser/scripts/browser-env.mjs +0 -41
  172. package/packages/omo-codex/plugin/skills/debugging/references/tools/playwright-cli.md +0 -112
  173. package/packages/omo-codex/plugin/skills/programming/scripts/rust/check-no-excuse-rules.py +0 -296
  174. package/packages/shared-skills/skills/browser/scripts/browser-env.mjs +0 -41
  175. package/packages/shared-skills/skills/debugging/references/tools/playwright-cli.md +0 -112
  176. package/packages/shared-skills/skills/programming/scripts/rust/check-no-excuse-rules.py +0 -296
@@ -0,0 +1,1395 @@
1
+ (function() {
2
+ const ROLE_MAP = {
3
+ a: "link",
4
+ button: "button",
5
+ iframe: "iframe",
6
+ select: "combobox",
7
+ textarea: "textbox",
8
+ h1: "heading",
9
+ h2: "heading",
10
+ h3: "heading",
11
+ h4: "heading",
12
+ h5: "heading",
13
+ h6: "heading",
14
+ canvas: "canvas",
15
+ svg: "image",
16
+ img: "image",
17
+ nav: "navigation",
18
+ main: "main",
19
+ header: "banner",
20
+ footer: "contentinfo",
21
+ section: "region",
22
+ article: "article",
23
+ aside: "complementary",
24
+ form: "form",
25
+ table: "table",
26
+ ul: "list",
27
+ ol: "list",
28
+ li: "listitem",
29
+ p: "paragraph",
30
+ label: "label"
31
+ };
32
+ const VALID_ARIA_ROLES = /* @__PURE__ */ new Set([
33
+ "alert",
34
+ "alertdialog",
35
+ "application",
36
+ "article",
37
+ "banner",
38
+ "blockquote",
39
+ "button",
40
+ "caption",
41
+ "cell",
42
+ "checkbox",
43
+ "code",
44
+ "columnheader",
45
+ "combobox",
46
+ "complementary",
47
+ "contentinfo",
48
+ "definition",
49
+ "deletion",
50
+ "dialog",
51
+ "directory",
52
+ "document",
53
+ "emphasis",
54
+ "feed",
55
+ "figure",
56
+ "form",
57
+ "generic",
58
+ "grid",
59
+ "gridcell",
60
+ "group",
61
+ "heading",
62
+ "img",
63
+ "insertion",
64
+ "link",
65
+ "list",
66
+ "listbox",
67
+ "listitem",
68
+ "log",
69
+ "main",
70
+ "mark",
71
+ "marquee",
72
+ "math",
73
+ "meter",
74
+ "menu",
75
+ "menubar",
76
+ "menuitem",
77
+ "menuitemcheckbox",
78
+ "menuitemradio",
79
+ "navigation",
80
+ "none",
81
+ "note",
82
+ "option",
83
+ "paragraph",
84
+ "presentation",
85
+ "progressbar",
86
+ "radio",
87
+ "radiogroup",
88
+ "region",
89
+ "row",
90
+ "rowgroup",
91
+ "rowheader",
92
+ "scrollbar",
93
+ "search",
94
+ "searchbox",
95
+ "separator",
96
+ "slider",
97
+ "spinbutton",
98
+ "status",
99
+ "strong",
100
+ "subscript",
101
+ "superscript",
102
+ "switch",
103
+ "tab",
104
+ "table",
105
+ "tablist",
106
+ "tabpanel",
107
+ "term",
108
+ "textbox",
109
+ "time",
110
+ "timer",
111
+ "toolbar",
112
+ "tooltip",
113
+ "tree",
114
+ "treegrid",
115
+ "treeitem"
116
+ ]);
117
+ function getExplicitAriaRole(element) {
118
+ return (element.getAttribute("role") || "").split(" ").map((role) => role.trim().toLowerCase()).filter(Boolean).find((role) => VALID_ARIA_ROLES.has(role)) || null;
119
+ }
120
+ function isContentEditableElement(element) {
121
+ if (!(element instanceof HTMLElement)) return false;
122
+ return element.contentEditable === "true" || element.contentEditable === "plaintext-only";
123
+ }
124
+ function getImplicitRole(element) {
125
+ const tag = element.tagName.toLowerCase();
126
+ const type = element.getAttribute("type");
127
+ if (isContentEditableElement(element)) return "textbox";
128
+ if (tag === "input") {
129
+ if (type === "submit" || type === "button") return "button";
130
+ if (type === "checkbox") return "checkbox";
131
+ if (type === "radio") return "radio";
132
+ if (type === "file") return "button";
133
+ return "textbox";
134
+ }
135
+ return ROLE_MAP[tag] || "generic";
136
+ }
137
+ function getRole(element) {
138
+ const explicitRole = getExplicitAriaRole(element);
139
+ if (!explicitRole) return getImplicitRole(element);
140
+ if (explicitRole === "presentation" || explicitRole === "none") return getImplicitRole(element);
141
+ return explicitRole;
142
+ }
143
+ const INTERACTIVE_TAGS = /* @__PURE__ */ new Set([
144
+ "a",
145
+ "button",
146
+ "input",
147
+ "select",
148
+ "textarea",
149
+ "details",
150
+ "summary"
151
+ ]);
152
+ const INTERACTIVE_REF_ROLES = /* @__PURE__ */ new Set([
153
+ "button",
154
+ "link",
155
+ "textbox",
156
+ "checkbox",
157
+ "radio",
158
+ "combobox",
159
+ "listbox",
160
+ "menuitem",
161
+ "menuitemcheckbox",
162
+ "menuitemradio",
163
+ "option",
164
+ "searchbox",
165
+ "slider",
166
+ "spinbutton",
167
+ "switch",
168
+ "tab",
169
+ "treeitem"
170
+ ]);
171
+ const CONTENT_REF_ROLES = /* @__PURE__ */ new Set([
172
+ "cell",
173
+ "gridcell",
174
+ "columnheader",
175
+ "rowheader",
176
+ "listitem",
177
+ "article",
178
+ "region",
179
+ "main",
180
+ "navigation"
181
+ ]);
182
+ const ARIA_LEVEL_ROLES = /* @__PURE__ */ new Set([
183
+ "heading",
184
+ "listitem",
185
+ "row",
186
+ "treeitem"
187
+ ]);
188
+ const ARIA_SELECTED_ROLES = /* @__PURE__ */ new Set([
189
+ "gridcell",
190
+ "option",
191
+ "row",
192
+ "tab",
193
+ "rowheader",
194
+ "columnheader",
195
+ "treeitem"
196
+ ]);
197
+ const ARIA_CHECKED_ROLES = /* @__PURE__ */ new Set([
198
+ "checkbox",
199
+ "radio",
200
+ "menuitemcheckbox",
201
+ "menuitemradio",
202
+ "switch"
203
+ ]);
204
+ /** Roles where `aria-readonly` is meaningful for editability checks. */
205
+ const ARIA_READONLY_ROLES = /* @__PURE__ */ new Set([
206
+ "checkbox",
207
+ "combobox",
208
+ "grid",
209
+ "gridcell",
210
+ "listbox",
211
+ "radiogroup",
212
+ "slider",
213
+ "spinbutton",
214
+ "textbox",
215
+ "columnheader",
216
+ "rowheader",
217
+ "searchbox",
218
+ "switch",
219
+ "treegrid"
220
+ ]);
221
+ const ARIA_DISABLED_ROLES = /* @__PURE__ */ new Set([
222
+ "application",
223
+ "button",
224
+ "composite",
225
+ "gridcell",
226
+ "group",
227
+ "input",
228
+ "link",
229
+ "menuitem",
230
+ "scrollbar",
231
+ "separator",
232
+ "tab",
233
+ "checkbox",
234
+ "columnheader",
235
+ "combobox",
236
+ "grid",
237
+ "listbox",
238
+ "menu",
239
+ "menubar",
240
+ "menuitemcheckbox",
241
+ "menuitemradio",
242
+ "option",
243
+ "radio",
244
+ "radiogroup",
245
+ "row",
246
+ "rowheader",
247
+ "searchbox",
248
+ "select",
249
+ "slider",
250
+ "spinbutton",
251
+ "switch",
252
+ "tablist",
253
+ "textbox",
254
+ "toolbar",
255
+ "tree",
256
+ "treegrid",
257
+ "treeitem"
258
+ ]);
259
+ const NATIVE_HEADING_LEVELS = {
260
+ h1: 1,
261
+ h2: 2,
262
+ h3: 3,
263
+ h4: 4,
264
+ h5: 5,
265
+ h6: 6
266
+ };
267
+ /** */
268
+ function getAriaLevel(element, role) {
269
+ if (!ARIA_LEVEL_ROLES.has(role)) return void 0;
270
+ const tag = element.tagName.toLowerCase();
271
+ if (role === "heading") {
272
+ const nativeLevel = NATIVE_HEADING_LEVELS[tag];
273
+ if (nativeLevel) return nativeLevel;
274
+ }
275
+ const ariaLevel = Number(element.getAttribute("aria-level"));
276
+ if (Number.isInteger(ariaLevel) && ariaLevel >= 1) return ariaLevel;
277
+ }
278
+ const LANDMARK_TAGS = /* @__PURE__ */ new Set([
279
+ "h1",
280
+ "h2",
281
+ "h3",
282
+ "h4",
283
+ "h5",
284
+ "h6",
285
+ "nav",
286
+ "main",
287
+ "header",
288
+ "footer",
289
+ "section",
290
+ "article",
291
+ "aside"
292
+ ]);
293
+ const SKIP_TAGS = /* @__PURE__ */ new Set([
294
+ "script",
295
+ "style",
296
+ "meta",
297
+ "link",
298
+ "title",
299
+ "noscript"
300
+ ]);
301
+ function getAriaBoolean(attr) {
302
+ if (attr === null) return void 0;
303
+ return attr.toLowerCase() === "true";
304
+ }
305
+ /** Escape double quotes and newlines in text. */
306
+ const escapeSnapshotText = (text) => text.replace(/"/g, "\\\"").replace(/\n/g, "\\n");
307
+ /** Replace consecutive whitespace characters with a single space and trim the result. */
308
+ const normalizeWhitespace = (text) => text.trim();
309
+ function shouldInsertSpaceBetween(left, right) {
310
+ const trimmedLeft = left.trimEnd();
311
+ const trimmedRight = right.trimStart();
312
+ if (!trimmedLeft || !trimmedRight) return false;
313
+ return /[\p{L}\p{N}]$/u.test(trimmedLeft) && /^[\p{L}\p{N}]/u.test(trimmedRight);
314
+ }
315
+ /** Merge adjacent strings with whitespace normalization and boundary-safe spacing. */
316
+ function mergeStringBuffer(buffer) {
317
+ let merged = "";
318
+ for (const part of buffer) {
319
+ if (!part) continue;
320
+ if (!merged) {
321
+ merged = part;
322
+ continue;
323
+ }
324
+ if (shouldInsertSpaceBetween(merged, part)) merged += " ";
325
+ merged += part;
326
+ }
327
+ return normalizeWhitespace(merged);
328
+ }
329
+ function getCSSContent(element, pseudo) {
330
+ try {
331
+ const style = window.getComputedStyle(element, pseudo);
332
+ if (!style) return "";
333
+ if (style.display === "none" || style.visibility === "hidden") return "";
334
+ const content = (style.content || "").trim();
335
+ if (!content || content === "none" || content === "normal") return "";
336
+ const matches = [...content.matchAll(/"((?:\\.|[^"\\])*)"|'((?:\\.|[^'\\])*)'/g)];
337
+ if (!matches.length) return "";
338
+ return matches.map((match) => match[1] ?? match[2] ?? "").map((text) => text.replace(/\\n/g, "\n").replace(/\\r/g, "\r").replace(/\\t/g, " ").replace(/\\f/g, "\f").replace(/\\(["'\\])/g, "$1")).join("");
339
+ } catch {
340
+ return "";
341
+ }
342
+ }
343
+ let _cache;
344
+ let _cacheHidden;
345
+ /** Start per-snapshot caching. Call at beginning of generateAccessibilityTree. */
346
+ function beginAccNameCaches() {
347
+ _cache = /* @__PURE__ */ new Map();
348
+ _cacheHidden = /* @__PURE__ */ new Map();
349
+ }
350
+ /** End per-snapshot caching. Call in finally block after generateAccessibilityTree. */
351
+ function endAccNameCaches() {
352
+ _cache = void 0;
353
+ _cacheHidden = void 0;
354
+ }
355
+ const NAME_FROM_CONTENT_ROLES = /* @__PURE__ */ new Set([
356
+ "button",
357
+ "link",
358
+ "heading",
359
+ "cell",
360
+ "columnheader",
361
+ "rowheader",
362
+ "tooltip",
363
+ "tab",
364
+ "menuitem",
365
+ "menuitemcheckbox",
366
+ "menuitemradio",
367
+ "treeitem",
368
+ "option",
369
+ "listitem",
370
+ "row",
371
+ "term"
372
+ ]);
373
+ const PROHIBITS_NAMING = /* @__PURE__ */ new Set([
374
+ "caption",
375
+ "code",
376
+ "definition",
377
+ "deletion",
378
+ "emphasis",
379
+ "generic",
380
+ "insertion",
381
+ "mark",
382
+ "paragraph",
383
+ "presentation",
384
+ "strong",
385
+ "subscript",
386
+ "superscript",
387
+ "term",
388
+ "time"
389
+ ]);
390
+ function getIdRefs(element, attrValue) {
391
+ if (!attrValue) return [];
392
+ const doc = element.ownerDocument;
393
+ return attrValue.split(/\s+/).filter(Boolean).map((id) => doc.getElementById(id)).filter(Boolean);
394
+ }
395
+ function isHiddenForAria(element) {
396
+ if (element.getAttribute("aria-hidden") === "true") return true;
397
+ try {
398
+ const style = window.getComputedStyle(element);
399
+ if (style.display === "none" || style.visibility === "hidden") return true;
400
+ } catch {}
401
+ return false;
402
+ }
403
+ function getLabels(element) {
404
+ const labels = [];
405
+ const id = element.getAttribute("id");
406
+ if (id) {
407
+ const forLabels = element.ownerDocument.querySelectorAll(`label[for="${id.replace(/"/g, "\\\"")}"]`);
408
+ labels.push(...Array.from(forLabels));
409
+ }
410
+ let parent = element.parentElement;
411
+ while (parent) {
412
+ if (parent.tagName.toLowerCase() === "label") {
413
+ labels.push(parent);
414
+ break;
415
+ }
416
+ parent = parent.parentElement;
417
+ }
418
+ return labels;
419
+ }
420
+ const MAX_ACCNAME_DEPTH = 10;
421
+ function getAccNameInternal(element, opts) {
422
+ if (opts.depth >= MAX_ACCNAME_DEPTH) return "";
423
+ if (opts.visitedElements.has(element)) return "";
424
+ opts.visitedElements.add(element);
425
+ if (!opts.includeHidden && !opts.inLabelledBy && !opts.inLabel) {
426
+ if (isHiddenForAria(element)) return "";
427
+ }
428
+ if (!opts.inLabelledBy) {
429
+ const refs = getIdRefs(element, element.getAttribute("aria-labelledby"));
430
+ if (refs.length) {
431
+ const name = refs.map((ref) => getAccNameInternal(ref, {
432
+ ...opts,
433
+ depth: opts.depth + 1,
434
+ visitedElements: new Set(opts.visitedElements),
435
+ inLabelledBy: true
436
+ })).join(" ").replace(/\s+/g, " ").trim();
437
+ if (name) return name;
438
+ }
439
+ }
440
+ const ariaLabel = element.getAttribute("aria-label")?.trim();
441
+ if (ariaLabel) return ariaLabel;
442
+ const role = getRole(element);
443
+ const tag = element.tagName.toLowerCase();
444
+ if ([
445
+ "input",
446
+ "textarea",
447
+ "select",
448
+ "meter",
449
+ "progress",
450
+ "output"
451
+ ].includes(tag) && !opts.inLabel && !opts.inLabelledBy) {
452
+ const labels = getLabels(element);
453
+ if (labels.length) {
454
+ const name = labels.map((lbl) => getAccNameInternal(lbl, {
455
+ ...opts,
456
+ depth: opts.depth + 1,
457
+ visitedElements: new Set(opts.visitedElements),
458
+ inLabel: true
459
+ })).join(" ").replace(/\s+/g, " ").trim();
460
+ if (name) return name;
461
+ }
462
+ }
463
+ if (tag === "area" || tag === "img" || tag === "input" && element.getAttribute("type") === "image") {
464
+ const alt = element.getAttribute("alt");
465
+ if (alt !== null) return alt.trim();
466
+ }
467
+ if (tag === "fieldset") {
468
+ const legend = element.querySelector(":scope > legend");
469
+ if (legend) return getAccNameInternal(legend, {
470
+ ...opts,
471
+ depth: opts.depth + 1,
472
+ visitedElements: new Set(opts.visitedElements)
473
+ });
474
+ }
475
+ if (tag === "figure") {
476
+ const figcaption = element.querySelector(":scope > figcaption");
477
+ if (figcaption) return getAccNameInternal(figcaption, {
478
+ ...opts,
479
+ depth: opts.depth + 1,
480
+ visitedElements: new Set(opts.visitedElements)
481
+ });
482
+ }
483
+ if (tag === "table") {
484
+ const caption = element.querySelector(":scope > caption");
485
+ if (caption) return getAccNameInternal(caption, {
486
+ ...opts,
487
+ depth: opts.depth + 1,
488
+ visitedElements: new Set(opts.visitedElements)
489
+ });
490
+ }
491
+ if (tag === "select") {
492
+ const sel = element;
493
+ const selected = sel.selectedIndex >= 0 ? sel.options[sel.selectedIndex] : null;
494
+ if (selected) return selected.textContent?.trim() || "";
495
+ }
496
+ if (NAME_FROM_CONTENT_ROLES.has(role) || opts.inLabelledBy || opts.inLabel) {
497
+ const parts = [];
498
+ const before = getCSSContent(element, "::before");
499
+ if (before) parts.push(before);
500
+ for (const child of element.childNodes) if (child.nodeType === Node.TEXT_NODE) {
501
+ const text = child.textContent || "";
502
+ if (text) parts.push(text);
503
+ } else if (child.nodeType === Node.ELEMENT_NODE) {
504
+ const childText = getAccNameInternal(child, {
505
+ ...opts,
506
+ depth: opts.depth + 1,
507
+ visitedElements: new Set(opts.visitedElements)
508
+ });
509
+ if (childText) parts.push(childText);
510
+ }
511
+ const after = getCSSContent(element, "::after");
512
+ if (after) parts.push(after);
513
+ const text = parts.join("").replace(/\s+/g, " ").trim();
514
+ if (text) return text;
515
+ }
516
+ if (tag === "input") {
517
+ const type = (element.getAttribute("type") || "text").toLowerCase();
518
+ if (type === "submit" || type === "button") {
519
+ const val = element.value;
520
+ if (val?.trim()) return val.trim();
521
+ }
522
+ }
523
+ const placeholder = element.getAttribute("placeholder")?.trim();
524
+ if (placeholder) return placeholder;
525
+ const title = element.getAttribute("title")?.trim();
526
+ if (title) return title;
527
+ return "";
528
+ }
529
+ /**
530
+ * Compute the W3C-compliant accessible name for an element.
531
+ * Cached within a snapshot call when used with beginAccNameCaches/endAccNameCaches.
532
+ */
533
+ function getAccessibleName(element, includeHidden = false) {
534
+ const cache = includeHidden ? _cacheHidden : _cache;
535
+ if (cache) {
536
+ const cached = cache.get(element);
537
+ if (cached !== void 0) return cached;
538
+ }
539
+ const role = getRole(element);
540
+ let name = "";
541
+ if (!PROHIBITS_NAMING.has(role)) name = getAccNameInternal(element, {
542
+ includeHidden,
543
+ visitedElements: /* @__PURE__ */ new Set(),
544
+ inLabelledBy: false,
545
+ inLabel: false,
546
+ depth: 0
547
+ });
548
+ name = name.replace(/\s+/g, " ").trim().substring(0, 300);
549
+ if (cache) cache.set(element, name);
550
+ return name;
551
+ }
552
+ let _registry = null;
553
+ let _refs = null;
554
+ let _signatureAssigned = null;
555
+ let _refCounter = 0;
556
+ let _visibilityCache = null;
557
+ const OMOWRIGHT_REF_SYMBOL = Symbol("omowright_ref");
558
+ const USER_PASSWORD_REDACTED = "[redacted]";
559
+ function getRefPrefix(ref) {
560
+ return ref.match(/^(f\d+)?e\d+$/)?.[1] ?? "";
561
+ }
562
+ const ROLE_SELECTOR_RE = /^\[role=["'](\w+)["']\]$/;
563
+ function querySelectorWithImplicitRole(selector) {
564
+ const match = selector.match(ROLE_SELECTOR_RE);
565
+ if (!match) return null;
566
+ const targetRole = match[1];
567
+ for (const el of Array.from(document.querySelectorAll("*"))) if (getRole(el) === targetRole) return el;
568
+ return null;
569
+ }
570
+ function getAriaDisabled(element, role) {
571
+ if (!ARIA_DISABLED_ROLES.has(role)) return false;
572
+ if ([
573
+ "button",
574
+ "input",
575
+ "select",
576
+ "textarea",
577
+ "option",
578
+ "optgroup"
579
+ ].includes(element.tagName.toLowerCase()) && element.matches(":disabled")) return true;
580
+ for (let current = element; current; current = getParentElementAcrossShadowBoundary(current)) if (getAriaBoolean(current.getAttribute("aria-disabled")) === true) return true;
581
+ return false;
582
+ }
583
+ function getAriaChecked(element, role) {
584
+ if (element instanceof HTMLInputElement && (element.type === "checkbox" || element.type === "radio")) return element.checked;
585
+ if (!ARIA_CHECKED_ROLES.has(role)) return false;
586
+ return getAriaBoolean(element.getAttribute("aria-checked")) === true;
587
+ }
588
+ function getAriaSelected(element, role) {
589
+ if (element.tagName.toLowerCase() === "option") return element.selected;
590
+ if (!ARIA_SELECTED_ROLES.has(role)) return false;
591
+ return getAriaBoolean(element.getAttribute("aria-selected")) === true;
592
+ }
593
+ function getTextboxValue(element) {
594
+ if (isContentEditableElement(element)) return element.innerText ?? element.textContent ?? "";
595
+ if (!(element instanceof HTMLInputElement) && !(element instanceof HTMLTextAreaElement)) return null;
596
+ if (element instanceof HTMLInputElement && [
597
+ "checkbox",
598
+ "radio",
599
+ "file"
600
+ ].includes(element.type)) return null;
601
+ if (element instanceof HTMLInputElement && element.type === "password") return element.value ? USER_PASSWORD_REDACTED : "";
602
+ return element.value;
603
+ }
604
+ function getAriaOwnedElements(element) {
605
+ const owns = element.getAttribute("aria-owns");
606
+ if (!owns) return [];
607
+ const ownedElements = [];
608
+ const seen = /* @__PURE__ */ new Set();
609
+ for (const id of owns.split(/\s+/)) {
610
+ if (!id) continue;
611
+ const owned = element.ownerDocument.getElementById(id);
612
+ if (!owned || owned === element || seen.has(owned)) continue;
613
+ seen.add(owned);
614
+ ownedElements.push(owned);
615
+ }
616
+ return ownedElements;
617
+ }
618
+ function normalizeName(name) {
619
+ return name.replace(/\s+/g, " ").trim().substring(0, 100);
620
+ }
621
+ function getLayoutSize(element) {
622
+ const layout = element;
623
+ return {
624
+ width: layout.offsetWidth ?? -1,
625
+ height: layout.offsetHeight ?? -1
626
+ };
627
+ }
628
+ function getContainingShadowHost(element) {
629
+ const root = typeof element.getRootNode === "function" ? element.getRootNode() : null;
630
+ if (typeof ShadowRoot !== "undefined" && root instanceof ShadowRoot) return root.host;
631
+ return null;
632
+ }
633
+ function getParentElementAcrossShadowBoundary(element) {
634
+ return element.parentElement ?? getContainingShadowHost(element);
635
+ }
636
+ function getLightAndShadowChildNodes(element) {
637
+ const nodes = Array.from(element.childNodes);
638
+ if (element.shadowRoot) nodes.push(...Array.from(element.shadowRoot.childNodes));
639
+ return nodes;
640
+ }
641
+ function hasClippedZeroSizeBox(element, style) {
642
+ const overflowClips = style.overflow === "hidden" || style.overflow === "clip" || style.overflowX === "hidden" || style.overflowX === "clip" || style.overflowY === "hidden" || style.overflowY === "clip";
643
+ const { width, height } = getLayoutSize(element);
644
+ return overflowClips && (width === 0 || height === 0);
645
+ }
646
+ /**
647
+ * Checks whether an element is rendered and visible to the user.
648
+ * Merges the ancestor walk for display:contents detection with the main
649
+ * visibility loop to avoid a redundant second traversal.
650
+ */
651
+ function isVisible(element) {
652
+ if (_visibilityCache) {
653
+ const cached = _visibilityCache.get(element);
654
+ if (cached !== void 0) return cached;
655
+ }
656
+ const result = isVisibleUncached(element);
657
+ if (_visibilityCache) _visibilityCache.set(element, result);
658
+ return result;
659
+ }
660
+ function isVisibleUncached(element) {
661
+ if (element.getAttribute("aria-hidden") === "true") return false;
662
+ const targetVisibility = window.getComputedStyle(element).visibility;
663
+ let hasContentsAncestor = false;
664
+ for (let current = element; current && current !== document.documentElement; current = getParentElementAcrossShadowBoundary(current)) {
665
+ const style = window.getComputedStyle(current);
666
+ if (style.display === "contents") {
667
+ hasContentsAncestor = true;
668
+ continue;
669
+ }
670
+ if (style.display === "none") return false;
671
+ if (hasClippedZeroSizeBox(current, style)) return false;
672
+ const { width, height } = getLayoutSize(current);
673
+ if (current.tagName === "IFRAME" && (width === 0 || height === 0)) return false;
674
+ if (style.visibility === "hidden" && targetVisibility !== "visible") return false;
675
+ if (Number.parseFloat(style.opacity) === 0) return false;
676
+ }
677
+ if (typeof element.checkVisibility === "function") {
678
+ if (!element.checkVisibility({
679
+ checkOpacity: true,
680
+ checkVisibilityCSS: true
681
+ }) && !hasContentsAncestor) return false;
682
+ }
683
+ if (element instanceof HTMLElement) {
684
+ const rect = element.getBoundingClientRect();
685
+ if (rect.width > 0 && rect.height > 0 && (rect.right <= 0 || rect.bottom <= 0)) {
686
+ const style = window.getComputedStyle(element);
687
+ if (style.overflowX !== "visible" && style.overflowY !== "visible") return false;
688
+ }
689
+ }
690
+ return true;
691
+ }
692
+ function getInteractivitySignals(element) {
693
+ const tag = element.tagName.toLowerCase();
694
+ const role = getExplicitAriaRole(element);
695
+ const tabIndex = element.getAttribute("tabindex");
696
+ const hasTabIndex = tabIndex !== null && tabIndex !== "-1";
697
+ const hasOnClick = element.hasAttribute("onclick");
698
+ const hasCursorPointer = window.getComputedStyle(element).cursor === "pointer";
699
+ const isInteractiveTag = INTERACTIVE_TAGS.has(tag);
700
+ const isRoleInteractive = role === "button" || role === "link";
701
+ const isContentEditable = element.getAttribute("contenteditable") === "true";
702
+ let hasPointerInteraction = hasCursorPointer;
703
+ if (hasCursorPointer && !hasOnClick && !hasTabIndex) {
704
+ const parent = element.parentElement;
705
+ if (parent && window.getComputedStyle(parent).cursor === "pointer") hasPointerInteraction = false;
706
+ }
707
+ const hints = [];
708
+ if (hasPointerInteraction) hints.push("cursor:pointer");
709
+ if (hasOnClick) hints.push("onclick");
710
+ if (hasTabIndex) hints.push("tabindex");
711
+ return {
712
+ interactive: isInteractiveTag || hasOnClick || hasTabIndex || isRoleInteractive || isContentEditable || hasPointerInteraction,
713
+ isInteractiveTag,
714
+ hints
715
+ };
716
+ }
717
+ function isInteractive(element) {
718
+ return getInteractivitySignals(element).interactive;
719
+ }
720
+ const SCROLLABLE_OVERFLOW_VALUES = /* @__PURE__ */ new Set([
721
+ "auto",
722
+ "scroll",
723
+ "overlay"
724
+ ]);
725
+ function isScrollable(element) {
726
+ const tag = element.tagName.toLowerCase();
727
+ if (tag === "html" || tag === "body") return false;
728
+ const style = window.getComputedStyle(element);
729
+ if (!SCROLLABLE_OVERFLOW_VALUES.has(style.overflowX) && !SCROLLABLE_OVERFLOW_VALUES.has(style.overflowY)) return false;
730
+ return element.scrollHeight > element.clientHeight + 1 || element.scrollWidth > element.clientWidth + 1;
731
+ }
732
+ function isLandmark(element) {
733
+ const tag = element.tagName.toLowerCase();
734
+ const explicitRole = getExplicitAriaRole(element);
735
+ return LANDMARK_TAGS.has(tag) || !!explicitRole && explicitRole !== "presentation" && explicitRole !== "none";
736
+ }
737
+ function shouldTraverse(element, options) {
738
+ const tag = element.tagName.toLowerCase();
739
+ if (SKIP_TAGS.has(tag)) return false;
740
+ if (element.getAttribute("aria-hidden") === "true" && element.children.length === 0) return false;
741
+ if (!options.showHidden && !isVisible(element)) {
742
+ if (tag === "input") {
743
+ const type = element.type;
744
+ if (type === "radio" || type === "checkbox") return true;
745
+ }
746
+ return false;
747
+ }
748
+ return true;
749
+ }
750
+ function shouldIncludeNode(element, options) {
751
+ const role = getRole(element);
752
+ if (options.interactive) return role === "canvas" || isInteractive(element) || isScrollable(element) || isLandmark(element);
753
+ if (isInteractive(element)) return true;
754
+ if (isScrollable(element)) return true;
755
+ if (isLandmark(element)) return true;
756
+ if (getAccessibleName(element).length > 0) return true;
757
+ return role !== "generic" && role !== "image";
758
+ }
759
+ function getOrCreateRefId(element, role, name, refPrefix = "") {
760
+ const writeRefMeta = (ref) => {
761
+ const metaRole = getRole(element);
762
+ const metaName = getAccessibleName(element).substring(0, 100);
763
+ const signature = `${metaRole}::${metaName}`;
764
+ const nth = _signatureAssigned.get(signature) ?? 0;
765
+ _signatureAssigned.set(signature, nth + 1);
766
+ _refs[ref] = {
767
+ role: metaRole,
768
+ name: metaName,
769
+ tagName: element.tagName,
770
+ inputType: element.type || void 0,
771
+ ariaLabel: element.getAttribute("aria-label") || void 0,
772
+ placeholder: element.getAttribute("placeholder") || void 0,
773
+ nthAmongSameSignature: nth
774
+ };
775
+ };
776
+ const cached = element[OMOWRIGHT_REF_SYMBOL];
777
+ if (cached && cached.role === role && cached.name === name && getRefPrefix(cached.ref) === refPrefix) {
778
+ _registry.set(cached.ref, element);
779
+ writeRefMeta(cached.ref);
780
+ return cached.ref;
781
+ }
782
+ const ref = refPrefix.length > 0 ? `${refPrefix}e${++_refCounter}` : "e" + ++_refCounter;
783
+ element[OMOWRIGHT_REF_SYMBOL] = {
784
+ role,
785
+ name,
786
+ ref
787
+ };
788
+ _registry.set(ref, element);
789
+ writeRefMeta(ref);
790
+ return ref;
791
+ }
792
+ function findDuplicateRefIds(rootNode) {
793
+ const refCounts = /* @__PURE__ */ new Map();
794
+ const visit = (node) => {
795
+ if (node.refId) refCounts.set(node.refId, (refCounts.get(node.refId) ?? 0) + 1);
796
+ for (const child of node.children) if (typeof child !== "string") visit(child);
797
+ };
798
+ visit(rootNode);
799
+ return [...refCounts.entries()].filter(([, count]) => count > 1).map(([refId]) => refId).sort();
800
+ }
801
+ function toSnapshotNode(element, refPrefix = "") {
802
+ const role = getRole(element);
803
+ const roleLower = role.toLowerCase();
804
+ const interactivity = getInteractivitySignals(element);
805
+ const name = normalizeName(getAccessibleName(element));
806
+ const hidden = !isVisible(element);
807
+ const scrollable = isScrollable(element);
808
+ const shouldHaveRef = roleLower === "iframe" || roleLower === "canvas" || scrollable || interactivity.interactive || INTERACTIVE_REF_ROLES.has(roleLower) || CONTENT_REF_ROLES.has(roleLower) && name.length > 0;
809
+ let nodeRefId;
810
+ if (shouldHaveRef) nodeRefId = getOrCreateRefId(element, role, name, refPrefix);
811
+ if (role === "generic" && !nodeRefId && !hidden) return null;
812
+ const hints = [];
813
+ if (interactivity.interactive && !interactivity.isInteractiveTag && interactivity.hints.length > 0) hints.push(...interactivity.hints);
814
+ const href = element.getAttribute("href");
815
+ const type = element.getAttribute("type");
816
+ const placeholder = element.getAttribute("placeholder");
817
+ const level = getAriaLevel(element, role);
818
+ const checked = getAriaChecked(element, roleLower);
819
+ const selected = getAriaSelected(element, roleLower);
820
+ const focused = element.ownerDocument.activeElement === element;
821
+ const disabled = getAriaDisabled(element, roleLower);
822
+ const textboxValue = getTextboxValue(element);
823
+ const rect = roleLower === "canvas" ? element.getBoundingClientRect() : null;
824
+ return {
825
+ role,
826
+ name,
827
+ level,
828
+ hidden: hidden || void 0,
829
+ scrollable: scrollable || void 0,
830
+ checked: checked || void 0,
831
+ selected: selected || void 0,
832
+ focused: focused || void 0,
833
+ disabled: disabled || void 0,
834
+ refId: nodeRefId,
835
+ hints,
836
+ href: href ?? void 0,
837
+ type: type ?? void 0,
838
+ placeholder: placeholder ?? void 0,
839
+ size: rect ? `${Math.round(rect.width)}x${Math.round(rect.height)}` : void 0,
840
+ element,
841
+ children: textboxValue !== null ? [textboxValue] : []
842
+ };
843
+ }
844
+ /** True when a node carries no semantic payload beyond its role — safe to unwrap or collapse. */
845
+ function isBareWrapper(node) {
846
+ return !node.name && !node.level && !node.hidden && !node.scrollable && !node.checked && !node.selected && !node.focused && !node.disabled && !node.refId && node.hints.length === 0 && !node.href && !node.type && !node.placeholder && !node.size;
847
+ }
848
+ function normalizeStringChildren(rootNode) {
849
+ const paragraphLeafToText = (node) => {
850
+ if (node.role !== "paragraph") return null;
851
+ if (!isBareWrapper(node)) return null;
852
+ if (node.children.some((child) => typeof child !== "string")) return null;
853
+ return mergeStringBuffer(node.children) || "";
854
+ };
855
+ const flushChildren = (buffer, normalizedChildren) => {
856
+ if (!buffer.length) return;
857
+ const text = mergeStringBuffer(buffer);
858
+ if (text) normalizedChildren.push(text);
859
+ buffer.length = 0;
860
+ };
861
+ const visit = (node) => {
862
+ const normalizedChildren = [];
863
+ const buffer = [];
864
+ for (const child of node.children) {
865
+ if (typeof child === "string") {
866
+ buffer.push(child);
867
+ continue;
868
+ }
869
+ visit(child);
870
+ const paragraphText = paragraphLeafToText(child);
871
+ if (paragraphText !== null) {
872
+ if (paragraphText) buffer.push(paragraphText);
873
+ continue;
874
+ }
875
+ flushChildren(buffer, normalizedChildren);
876
+ normalizedChildren.push(child);
877
+ }
878
+ flushChildren(buffer, normalizedChildren);
879
+ node.children = normalizedChildren.length ? normalizedChildren : [];
880
+ if (node.children.length === 1 && node.children[0] === node.name) node.children = [];
881
+ };
882
+ visit(rootNode);
883
+ }
884
+ function normalizeGenericRoles(node) {
885
+ const hasRefInSubtree = (children) => {
886
+ for (const child of children) {
887
+ if (typeof child === "string") continue;
888
+ if (child.refId) return true;
889
+ if (hasRefInSubtree(child.children)) return true;
890
+ }
891
+ return false;
892
+ };
893
+ const normalizeChildren = (current) => {
894
+ const result = [];
895
+ for (const child of current.children) {
896
+ if (typeof child === "string") {
897
+ result.push(child);
898
+ continue;
899
+ }
900
+ const normalized = normalizeChildren(child);
901
+ result.push(...normalized);
902
+ }
903
+ if (current.hidden && !current.refId && !hasRefInSubtree(result)) return [];
904
+ const singleChild = result.length === 1 && typeof result[0] !== "string" ? result[0] : null;
905
+ if (current.role === "paragraph" && isBareWrapper(current) && !!singleChild && singleChild.role === "paragraph") return singleChild ? [singleChild] : [];
906
+ if (current.role === "generic" && !current.hidden && !current.name && result.length <= 1 && result.every((child) => typeof child !== "string" && !!child.refId)) {
907
+ const flattened = [];
908
+ for (const child of result) if (typeof child !== "string") flattened.push(child);
909
+ return flattened;
910
+ }
911
+ current.children = result;
912
+ return [current];
913
+ };
914
+ normalizeChildren(node);
915
+ }
916
+ function withoutWhitespace(text) {
917
+ return normalizeWhitespace(text).replace(/\s+/g, "");
918
+ }
919
+ function mergeTextLeafChildren(node) {
920
+ const textLeafRoles = /* @__PURE__ */ new Set([
921
+ "generic",
922
+ "heading",
923
+ "paragraph",
924
+ "label"
925
+ ]);
926
+ const getLeafText = (child) => {
927
+ if (typeof child === "string") return normalizeWhitespace(child) || null;
928
+ if (!textLeafRoles.has(child.role)) return null;
929
+ if (child.hidden) return null;
930
+ if (!child.name || child.children.length > 0) return null;
931
+ return child.name;
932
+ };
933
+ const visit = (current) => {
934
+ for (const child of current.children) if (typeof child !== "string") visit(child);
935
+ if (current.hidden) return;
936
+ if (!current.refId || current.children.length === 0) return;
937
+ if (current.children.length > 3) return;
938
+ const texts = [];
939
+ for (const child of current.children) {
940
+ const text = getLeafText(child);
941
+ if (!text) return;
942
+ texts.push(text);
943
+ }
944
+ const merged = normalizeName(texts.join(" "));
945
+ if (!merged) return;
946
+ if (!current.name) {
947
+ current.name = merged;
948
+ current.children = [];
949
+ return;
950
+ }
951
+ if (withoutWhitespace(current.name) === withoutWhitespace(merged)) current.children = [];
952
+ };
953
+ visit(node);
954
+ }
955
+ function snapshotNodeToString(node) {
956
+ const parts = [node.role];
957
+ if (node.name) parts.push(`"${escapeSnapshotText(node.name)}"`);
958
+ if (node.refId) parts.push(`[ref=${node.refId}]`);
959
+ if (node.level && node.level > 0) parts.push(`[level=${node.level}]`);
960
+ if (node.hidden) parts.push("[hidden]");
961
+ if (node.scrollable) parts.push("[scrollable]");
962
+ if (node.checked) parts.push("[checked]");
963
+ if (node.disabled) parts.push("[disabled]");
964
+ if (node.focused) parts.push("[focused]");
965
+ if (node.selected) parts.push("[selected]");
966
+ if (node.placeholder) parts.push(`[placeholder="${escapeSnapshotText(node.placeholder)}"]`);
967
+ if (node.size) parts.push(`[size=${node.size}]`);
968
+ return parts.join(" ");
969
+ }
970
+ function renderSnapshotTree(node, depth, lines) {
971
+ const isRoot = node.role === "fragment";
972
+ const childDepth = isRoot ? depth : depth + 1;
973
+ const indent = " ".repeat(depth);
974
+ const childIndent = " ".repeat(childDepth);
975
+ if (!isRoot) {
976
+ const nodeString = snapshotNodeToString(node);
977
+ const textChildren = node.children.filter((child) => typeof child === "string");
978
+ const elementChildren = node.children.filter((child) => typeof child !== "string");
979
+ const hasSelectOptions = node.element?.tagName.toLowerCase() === "select";
980
+ if (textChildren.length === 1 && elementChildren.length === 0 && !hasSelectOptions) {
981
+ const text = normalizeWhitespace(textChildren[0] || "");
982
+ if (text) lines.push(`${indent}- ${nodeString}: "${escapeSnapshotText(text)}"`);
983
+ else lines.push(`${indent}- ${nodeString}`);
984
+ return;
985
+ }
986
+ const hasChildren = node.children.length > 0 || hasSelectOptions;
987
+ lines.push(`${indent}- ${nodeString}${hasChildren ? ":" : ""}`);
988
+ if (hasSelectOptions) {
989
+ const selectEl = node.element;
990
+ for (const option of Array.from(selectEl.options)) {
991
+ let optionLine = `${childIndent}- option`;
992
+ const optionText = option.textContent?.trim() || "";
993
+ if (optionText) {
994
+ const truncated = optionText.replace(/\s+/g, " ").substring(0, 100);
995
+ optionLine += ` "${escapeSnapshotText(truncated)}"`;
996
+ }
997
+ if (option.selected) optionLine += " (selected)";
998
+ if (option.value && option.value !== optionText) optionLine += ` value="${escapeSnapshotText(option.value)}"`;
999
+ lines.push(optionLine);
1000
+ }
1001
+ }
1002
+ }
1003
+ for (const child of node.children) {
1004
+ if (typeof child === "string") {
1005
+ const text = normalizeWhitespace(child);
1006
+ if (!text) continue;
1007
+ lines.push(`${childIndent}- text: "${escapeSnapshotText(text)}"`);
1008
+ continue;
1009
+ }
1010
+ renderSnapshotTree(child, childDepth, lines);
1011
+ }
1012
+ }
1013
+ const defaultOptions = {
1014
+ interactive: false,
1015
+ maxDepth: 50,
1016
+ showHidden: false,
1017
+ refPrefix: ""
1018
+ };
1019
+ /** Generate the YAML-like accessibility tree for the current page or a subtree. */
1020
+ function generateAccessibilityTree(elementRegistry, _options = {}) {
1021
+ _registry = elementRegistry;
1022
+ _refs = {};
1023
+ _signatureAssigned = /* @__PURE__ */ new Map();
1024
+ _visibilityCache = /* @__PURE__ */ new Map();
1025
+ beginAccNameCaches();
1026
+ try {
1027
+ const options = {
1028
+ ...defaultOptions,
1029
+ ..._options
1030
+ };
1031
+ const maxDepth = options.maxDepth ?? defaultOptions.maxDepth;
1032
+ const treeRoot = {
1033
+ role: "fragment",
1034
+ name: "",
1035
+ hints: [],
1036
+ children: []
1037
+ };
1038
+ const visited = /* @__PURE__ */ new Set();
1039
+ function traverse(element, currentDepth, parentNode) {
1040
+ if (currentDepth > options.maxDepth) return;
1041
+ if (!element?.tagName) return;
1042
+ if (visited.has(element)) return;
1043
+ visited.add(element);
1044
+ const traversable = shouldTraverse(element, options);
1045
+ const includeAsRoot = !options.refId && element === document.body;
1046
+ const hidden = !isVisible(element);
1047
+ const include = includeAsRoot || traversable && (shouldIncludeNode(element, options) || options.showHidden && hidden);
1048
+ if (!traversable && !includeAsRoot) return;
1049
+ let currentNode = null;
1050
+ let targetNode = parentNode;
1051
+ if (include) {
1052
+ currentNode = toSnapshotNode(element, options.refPrefix || "");
1053
+ if (currentNode) {
1054
+ parentNode.children.push(currentNode);
1055
+ targetNode = currentNode;
1056
+ }
1057
+ }
1058
+ if (!include && options.interactive && element.childNodes.length === 0) {
1059
+ const hoistedName = normalizeName(getAccessibleName(element));
1060
+ if (hoistedName && targetNode.role !== "fragment") targetNode.children.push(hoistedName);
1061
+ }
1062
+ if (currentDepth < maxDepth) {
1063
+ const beforeText = getCSSContent(element, "::before");
1064
+ if (beforeText) targetNode.children.push(beforeText);
1065
+ const nextDepth = include && currentNode ? currentDepth + 1 : currentDepth;
1066
+ for (const child of getLightAndShadowChildNodes(element)) {
1067
+ if (child.nodeType === Node.TEXT_NODE) {
1068
+ if (!child.nodeValue || targetNode.role === "textbox") continue;
1069
+ targetNode.children.push(child.nodeValue);
1070
+ continue;
1071
+ }
1072
+ if (child.nodeType === Node.ELEMENT_NODE) traverse(child, nextDepth, targetNode);
1073
+ }
1074
+ for (const child of getAriaOwnedElements(element)) traverse(child, nextDepth, targetNode);
1075
+ const afterText = getCSSContent(element, "::after");
1076
+ if (afterText) targetNode.children.push(afterText);
1077
+ }
1078
+ }
1079
+ if (options.refId) {
1080
+ const element = elementRegistry.get(options.refId);
1081
+ if (!element || !element.isConnected) return {
1082
+ error: `Element with ref_id '${options.refId}' not found. It may have been removed from the page. Use read_page without ref_id to get the current page state.`,
1083
+ tree: "",
1084
+ refs: {}
1085
+ };
1086
+ traverse(element, 0, treeRoot);
1087
+ } else if (options.selector) {
1088
+ const element = document.querySelector(options.selector) ?? querySelectorWithImplicitRole(options.selector);
1089
+ if (!element) return {
1090
+ error: `Element matching selector '${options.selector}' not found. It may have been removed from the page. Use read_page without selector to get the current page state.`,
1091
+ tree: "",
1092
+ refs: {}
1093
+ };
1094
+ traverse(element, 0, treeRoot);
1095
+ } else if (document.body) traverse(document.body, 0, treeRoot);
1096
+ normalizeStringChildren(treeRoot);
1097
+ normalizeGenericRoles(treeRoot);
1098
+ mergeTextLeafChildren(treeRoot);
1099
+ const duplicateRefs = findDuplicateRefIds(treeRoot);
1100
+ if (duplicateRefs.length > 0) return {
1101
+ error: `Snapshot produced duplicate refs: ${duplicateRefs.join(", ")}. Take a new snapshot and retry.`,
1102
+ tree: "",
1103
+ refs: {}
1104
+ };
1105
+ const lines = [];
1106
+ renderSnapshotTree(treeRoot, 0, lines);
1107
+ const tree = lines.join("\n");
1108
+ if (options.maxChars && tree.length > options.maxChars) {
1109
+ let errorMsg = `Output exceeds ${options.maxChars} character limit (${tree.length} characters). `;
1110
+ if (options.refId) errorMsg += "The specified element has too much content. Try specifying a smaller depth parameter or focus on a more specific child element.";
1111
+ else if (options.maxDepth) errorMsg += "Try specifying an even smaller depth parameter or use ref_id to focus on a specific element from the page.";
1112
+ else errorMsg += "Try specifying a depth parameter (e.g., depth: 5) or use ref_id to focus on a specific element from the page.";
1113
+ return {
1114
+ error: errorMsg,
1115
+ tree: "",
1116
+ refs: _refs
1117
+ };
1118
+ }
1119
+ return {
1120
+ tree,
1121
+ refs: _refs
1122
+ };
1123
+ } finally {
1124
+ _registry = null;
1125
+ _refs = null;
1126
+ _signatureAssigned = null;
1127
+ _visibilityCache = null;
1128
+ endAccNameCaches();
1129
+ }
1130
+ }
1131
+ (function setupOmOWrightWorld() {
1132
+ const elementRegistry = /* @__PURE__ */ new Map();
1133
+ let _lastRefs = {};
1134
+ function toElement(node) {
1135
+ if (node instanceof Element) return node;
1136
+ if (node && typeof node === "object" && "parentElement" in node) return node.parentElement;
1137
+ return null;
1138
+ }
1139
+ function takeSnapshot(options) {
1140
+ const rootElement = options?.refId ? elementRegistry.get(options.refId) : void 0;
1141
+ const previousRegistry = new Map(elementRegistry);
1142
+ elementRegistry.clear();
1143
+ if (rootElement && options?.refId) elementRegistry.set(options.refId, rootElement);
1144
+ try {
1145
+ const result = generateAccessibilityTree(elementRegistry, options);
1146
+ _lastRefs = result.refs;
1147
+ return result;
1148
+ } catch {
1149
+ elementRegistry.clear();
1150
+ for (const [key, value] of previousRegistry) elementRegistry.set(key, value);
1151
+ throw new Error("Snapshot failed");
1152
+ }
1153
+ }
1154
+ const DEREF_WALKER_BUDGET = 5e3;
1155
+ function deref(ref) {
1156
+ const el = elementRegistry.get(ref);
1157
+ if (el && el.isConnected) return el;
1158
+ const meta = _lastRefs[ref];
1159
+ if (!meta) return null;
1160
+ const candidates = [];
1161
+ const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT);
1162
+ let node;
1163
+ let visited = 0;
1164
+ while (node = walker.nextNode()) {
1165
+ if (++visited > DEREF_WALKER_BUDGET) break;
1166
+ if (getRole(node) === meta.role && getAccessibleName(node) === meta.name) candidates.push(node);
1167
+ }
1168
+ if (candidates.length === 1) return candidates[0] ?? null;
1169
+ if (meta.nthAmongSameSignature < candidates.length) return candidates[meta.nthAmongSameSignature] ?? null;
1170
+ return null;
1171
+ }
1172
+ function retarget(element, behavior) {
1173
+ let el = toElement(element);
1174
+ if (!el) return null;
1175
+ if (behavior === "none") return el;
1176
+ if (!el.matches("input, textarea, select") && !el.isContentEditable) if (behavior === "button-link") el = el.closest("button, [role=button], a, [role=link]") || el;
1177
+ else el = el.closest("button, [role=button], [role=checkbox], [role=radio]") || el;
1178
+ if (behavior === "follow-label") {
1179
+ if (!el.matches("a, input, textarea, button, select, [role=link], [role=button], [role=checkbox], [role=radio]") && !el.isContentEditable) {
1180
+ const label = el.closest("label");
1181
+ if (label?.control) el = label.control;
1182
+ }
1183
+ }
1184
+ return el;
1185
+ }
1186
+ function resolvePointerTarget(element) {
1187
+ const el = toElement(element);
1188
+ if (!el) return null;
1189
+ if (el instanceof HTMLInputElement && (el.type === "checkbox" || el.type === "radio")) {
1190
+ const visibleLabel = Array.from(el.labels ?? []).find((label) => {
1191
+ const style = label.ownerDocument?.defaultView?.getComputedStyle?.(label);
1192
+ if (style && (style.display === "none" || style.visibility === "hidden")) return false;
1193
+ const rect = label.getBoundingClientRect();
1194
+ return rect.width > 0 && rect.height > 0;
1195
+ });
1196
+ if (visibleLabel) return visibleLabel;
1197
+ }
1198
+ const nativeFormTargetSelector = "input:not([type=\"hidden\"]), select, textarea";
1199
+ const nestedFormTargetSelector = [
1200
+ nativeFormTargetSelector,
1201
+ "[role=\"checkbox\"]",
1202
+ "[role=\"radio\"]",
1203
+ "[role=\"switch\"]"
1204
+ ].join(", ");
1205
+ const formControlHostSelector = [
1206
+ "label",
1207
+ "[role=\"checkbox\"]",
1208
+ "[role=\"radio\"]",
1209
+ "[role=\"switch\"]",
1210
+ "mat-checkbox",
1211
+ "mat-radio-button",
1212
+ "mat-slide-toggle"
1213
+ ].join(", ");
1214
+ const label = el.closest("label");
1215
+ if (label?.control) {
1216
+ const labelStyle = label.ownerDocument?.defaultView?.getComputedStyle?.(label);
1217
+ const labelRect = label.getBoundingClientRect();
1218
+ const controlRect = label.control.getBoundingClientRect();
1219
+ if ((!labelStyle || labelStyle.display !== "none" && labelStyle.visibility !== "hidden") && labelRect.width > 0 && labelRect.height > 0 && (controlRect.width === 0 || controlRect.height === 0)) return label;
1220
+ return label.control;
1221
+ }
1222
+ const formHost = el.closest(formControlHostSelector);
1223
+ const nestedFormTarget = formHost?.querySelector(nestedFormTargetSelector);
1224
+ if (nestedFormTarget && nestedFormTarget !== formHost) return nestedFormTarget;
1225
+ if (el.hasAttribute("aria-checked") || el.hasAttribute("aria-selected")) return el;
1226
+ if (!el.matches("li, [role=listitem], [role=menuitem], [role=option]")) return el;
1227
+ const selector = [
1228
+ nativeFormTargetSelector,
1229
+ "button",
1230
+ "a[href]",
1231
+ "summary",
1232
+ "[role=\"button\"]",
1233
+ "[role=\"checkbox\"]",
1234
+ "[role=\"radio\"]",
1235
+ "[role=\"switch\"]",
1236
+ "[aria-checked]",
1237
+ "[tabindex]:not([tabindex=\"-1\"])"
1238
+ ].join(", ");
1239
+ const candidates = Array.from(el.querySelectorAll(selector)).filter((candidate) => {
1240
+ const rect = candidate.getBoundingClientRect();
1241
+ return rect.width > 0 && rect.height > 0;
1242
+ });
1243
+ if (candidates.length === 0) return el;
1244
+ return candidates.find((candidate) => candidate.matches("input[type=\"checkbox\"], input[type=\"radio\"], [role=\"checkbox\"], [role=\"radio\"], [role=\"switch\"], [aria-checked]")) ?? candidates.find((candidate) => candidate.tabIndex >= 0) ?? candidates[0] ?? el;
1245
+ }
1246
+ function checkHitTarget(element, point) {
1247
+ const el = toElement(element);
1248
+ if (!el) return {
1249
+ ok: false,
1250
+ error: "Node is not an Element"
1251
+ };
1252
+ const isComposedDescendant = (candidate, ancestor) => {
1253
+ let current = candidate;
1254
+ while (current) {
1255
+ if (current === ancestor) return true;
1256
+ if (current instanceof ShadowRoot) {
1257
+ current = current.host;
1258
+ continue;
1259
+ }
1260
+ current = current.parentNode;
1261
+ }
1262
+ return false;
1263
+ };
1264
+ let root = el.ownerDocument;
1265
+ let hitElement = null;
1266
+ while (root) {
1267
+ const candidate = root.elementFromPoint(point.x, point.y);
1268
+ if (!candidate) break;
1269
+ hitElement = candidate;
1270
+ if (isComposedDescendant(candidate, el)) return { ok: true };
1271
+ root = candidate.shadowRoot;
1272
+ }
1273
+ if (!hitElement) {
1274
+ const rect = el.getBoundingClientRect();
1275
+ if (el.isConnected && rect.width > 0 && rect.height > 0) return { ok: true };
1276
+ return {
1277
+ ok: false,
1278
+ error: "Element is obscured at click point"
1279
+ };
1280
+ }
1281
+ if (isComposedDescendant(el, hitElement)) return { ok: true };
1282
+ return {
1283
+ ok: false,
1284
+ error: "Element is obscured by another element"
1285
+ };
1286
+ }
1287
+ async function waitForReady(element, checks, timeoutMs = 5e3) {
1288
+ const el = toElement(element);
1289
+ if (!el) return {
1290
+ ok: false,
1291
+ error: "Node is not an Element (text node or non-Element handle)"
1292
+ };
1293
+ const start = Date.now();
1294
+ while (Date.now() - start < timeoutMs) {
1295
+ if (checks.includes("attached") && !el.isConnected) return {
1296
+ ok: false,
1297
+ error: "Element is detached from the DOM"
1298
+ };
1299
+ if (checks.includes("visible")) {
1300
+ const rect = el.getBoundingClientRect();
1301
+ if (!(el.checkVisibility?.({
1302
+ checkOpacity: false,
1303
+ checkVisibilityCSS: true
1304
+ }) !== false && rect.width > 0 && rect.height > 0)) {
1305
+ await new Promise((r) => setTimeout(r, 16));
1306
+ continue;
1307
+ }
1308
+ }
1309
+ if (checks.includes("enabled") && isDisabled(el)) return {
1310
+ ok: false,
1311
+ error: "Element is disabled"
1312
+ };
1313
+ if (checks.includes("stable")) {
1314
+ const prev = el.getBoundingClientRect();
1315
+ await new Promise((r) => setTimeout(r, 32));
1316
+ const curr = el.getBoundingClientRect();
1317
+ if (prev.x !== curr.x || prev.y !== curr.y || prev.width !== curr.width || prev.height !== curr.height) {
1318
+ if (Date.now() - start + 32 >= timeoutMs) return {
1319
+ ok: false,
1320
+ error: "Element is moving"
1321
+ };
1322
+ continue;
1323
+ }
1324
+ }
1325
+ return { ok: true };
1326
+ }
1327
+ return {
1328
+ ok: false,
1329
+ error: "Timeout waiting for element to be ready"
1330
+ };
1331
+ }
1332
+ function checkEditable(element) {
1333
+ if (isDisabled(element)) return {
1334
+ ok: false,
1335
+ error: "Element is disabled"
1336
+ };
1337
+ const tag = element.tagName;
1338
+ if ([
1339
+ "INPUT",
1340
+ "TEXTAREA",
1341
+ "SELECT"
1342
+ ].includes(tag)) return element.hasAttribute("readonly") ? {
1343
+ ok: false,
1344
+ error: "Element is read-only"
1345
+ } : { ok: true };
1346
+ if (element.getAttribute("contenteditable") === "false") return {
1347
+ ok: false,
1348
+ error: "Element is not editable"
1349
+ };
1350
+ if (ARIA_READONLY_ROLES.has(getRole(element))) return element.getAttribute("aria-readonly") === "true" ? {
1351
+ ok: false,
1352
+ error: "Element is read-only (aria-readonly)"
1353
+ } : { ok: true };
1354
+ if (element.isContentEditable) return { ok: true };
1355
+ return {
1356
+ ok: false,
1357
+ error: "Element does not support editable state"
1358
+ };
1359
+ }
1360
+ function isDisabled(element) {
1361
+ if ([
1362
+ "BUTTON",
1363
+ "INPUT",
1364
+ "SELECT",
1365
+ "TEXTAREA",
1366
+ "OPTION",
1367
+ "OPTGROUP"
1368
+ ].includes(element.tagName)) {
1369
+ if (element.disabled) return true;
1370
+ const fieldset = element.closest("fieldset:disabled");
1371
+ if (fieldset) {
1372
+ const legend = fieldset.querySelector(":scope > legend");
1373
+ if (!legend || !legend.contains(element)) return true;
1374
+ }
1375
+ }
1376
+ let el = element;
1377
+ while (el) {
1378
+ if (el.getAttribute("aria-disabled") === "true") return true;
1379
+ el = el.parentElement;
1380
+ }
1381
+ return false;
1382
+ }
1383
+ globalThis.__omowright = {
1384
+ elementRegistry,
1385
+ snapshotEpoch: 0,
1386
+ takeSnapshot,
1387
+ deref,
1388
+ retarget,
1389
+ resolvePointerTarget,
1390
+ waitForReady,
1391
+ checkHitTarget,
1392
+ checkEditable
1393
+ };
1394
+ })();
1395
+ })();