auto-webmcp 0.3.9 → 0.3.11
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.
- package/dist/analyzer.d.ts +1 -1
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/auto-webmcp.cjs.js +67 -7
- package/dist/auto-webmcp.cjs.js.map +3 -3
- package/dist/auto-webmcp.esm.js +67 -7
- package/dist/auto-webmcp.esm.js.map +3 -3
- package/dist/auto-webmcp.iife.js +1 -1
- package/dist/auto-webmcp.iife.js.map +3 -3
- package/dist/discovery.d.ts.map +1 -1
- package/dist/interceptor.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/auto-webmcp.esm.js
CHANGED
|
@@ -631,6 +631,19 @@ function resolveNativeControlFallbackKey(control) {
|
|
|
631
631
|
}
|
|
632
632
|
return null;
|
|
633
633
|
}
|
|
634
|
+
function resolveAriaElementKey(el) {
|
|
635
|
+
if (el.dataset["webmcpName"])
|
|
636
|
+
return sanitizeName(el.dataset["webmcpName"]);
|
|
637
|
+
if (el.id && !AUTO_GENERATED_ID_RE.test(el.id))
|
|
638
|
+
return sanitizeName(el.id);
|
|
639
|
+
const label = el.getAttribute("aria-label");
|
|
640
|
+
if (label)
|
|
641
|
+
return sanitizeName(label);
|
|
642
|
+
const placeholder = el.getAttribute("placeholder");
|
|
643
|
+
if (placeholder)
|
|
644
|
+
return sanitizeName(placeholder);
|
|
645
|
+
return null;
|
|
646
|
+
}
|
|
634
647
|
function collectAriaControls(form) {
|
|
635
648
|
const selector = ARIA_ROLES_TO_SCAN.map((r) => `[role="${r}"]`).join(", ");
|
|
636
649
|
const rawResults = [];
|
|
@@ -889,6 +902,22 @@ function buildSchemaFromInputs(inputs) {
|
|
|
889
902
|
const processedRadioGroups = /* @__PURE__ */ new Set();
|
|
890
903
|
const processedCheckboxGroups = /* @__PURE__ */ new Set();
|
|
891
904
|
for (const control of inputs) {
|
|
905
|
+
if (!(control instanceof HTMLInputElement) && !(control instanceof HTMLTextAreaElement) && !(control instanceof HTMLSelectElement)) {
|
|
906
|
+
const fieldKey2 = resolveAriaElementKey(control);
|
|
907
|
+
if (!fieldKey2)
|
|
908
|
+
continue;
|
|
909
|
+
if (!isControlVisible(control))
|
|
910
|
+
continue;
|
|
911
|
+
const prop = { type: "string" };
|
|
912
|
+
prop.title = control.getAttribute("aria-label") ?? fieldKey2;
|
|
913
|
+
const desc2 = control.getAttribute("aria-description") ?? control.getAttribute("aria-describedby") ? null : null;
|
|
914
|
+
if (desc2)
|
|
915
|
+
prop.description = desc2;
|
|
916
|
+
properties[fieldKey2] = prop;
|
|
917
|
+
fieldElements.set(fieldKey2, control);
|
|
918
|
+
required.push(fieldKey2);
|
|
919
|
+
continue;
|
|
920
|
+
}
|
|
892
921
|
const rawName = control.name;
|
|
893
922
|
const fieldKey = (rawName ? sanitizeName(rawName) : null) || resolveNativeControlFallbackKey(control);
|
|
894
923
|
if (!fieldKey)
|
|
@@ -1284,10 +1313,32 @@ function fillAriaField(el, value) {
|
|
|
1284
1313
|
}
|
|
1285
1314
|
const htmlEl = el;
|
|
1286
1315
|
if (htmlEl.isContentEditable) {
|
|
1287
|
-
htmlEl.
|
|
1316
|
+
htmlEl.focus();
|
|
1317
|
+
const range = document.createRange();
|
|
1318
|
+
range.selectNodeContents(htmlEl);
|
|
1319
|
+
const sel = window.getSelection();
|
|
1320
|
+
sel?.removeAllRanges();
|
|
1321
|
+
sel?.addRange(range);
|
|
1322
|
+
let handled = false;
|
|
1323
|
+
try {
|
|
1324
|
+
const dt = new DataTransfer();
|
|
1325
|
+
dt.setData("text/plain", String(value ?? ""));
|
|
1326
|
+
const ev = new ClipboardEvent("paste", {
|
|
1327
|
+
bubbles: true,
|
|
1328
|
+
cancelable: true,
|
|
1329
|
+
composed: true,
|
|
1330
|
+
clipboardData: dt
|
|
1331
|
+
});
|
|
1332
|
+
handled = !htmlEl.dispatchEvent(ev);
|
|
1333
|
+
} catch {
|
|
1334
|
+
}
|
|
1335
|
+
if (!handled) {
|
|
1336
|
+
document.execCommand("insertText", false, String(value ?? ""));
|
|
1337
|
+
}
|
|
1338
|
+
} else {
|
|
1339
|
+
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
1340
|
+
el.dispatchEvent(new Event("change", { bubbles: true }));
|
|
1288
1341
|
}
|
|
1289
|
-
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
1290
|
-
el.dispatchEvent(new Event("change", { bubbles: true }));
|
|
1291
1342
|
}
|
|
1292
1343
|
function serializeFormData(form, params, fieldEls) {
|
|
1293
1344
|
const result = {};
|
|
@@ -1560,10 +1611,10 @@ async function scanOrphanInputs(config) {
|
|
|
1560
1611
|
return;
|
|
1561
1612
|
const SUBMIT_BTN_SELECTOR = '[type="submit"]:not([disabled]), button[data-variant="primary"]:not([disabled])';
|
|
1562
1613
|
const SUBMIT_BTN_GROUPING_SELECTOR = '[type="submit"], button[data-variant="primary"]';
|
|
1563
|
-
const SUBMIT_TEXT_RE = /subscribe|submit|sign[\s-]?up|send|join|go|search/i;
|
|
1614
|
+
const SUBMIT_TEXT_RE = /subscribe|submit|sign[\s-]?up|send|join|go|search|post|tweet|publish/i;
|
|
1564
1615
|
const orphanInputs = Array.from(
|
|
1565
1616
|
document.querySelectorAll(
|
|
1566
|
-
|
|
1617
|
+
'input:not(form input), textarea:not(form textarea), select:not(form select), [role="textbox"]:not(form [role="textbox"]):not(input):not(textarea), [role="searchbox"]:not(form [role="searchbox"]):not(input):not(textarea), [contenteditable="true"]:not(form [contenteditable="true"]):not(input):not(textarea)'
|
|
1567
1618
|
)
|
|
1568
1619
|
).filter((el) => {
|
|
1569
1620
|
if (el instanceof HTMLInputElement && ORPHAN_EXCLUDED_TYPES.has(el.type.toLowerCase())) {
|
|
@@ -1619,6 +1670,15 @@ async function scanOrphanInputs(config) {
|
|
|
1619
1670
|
if (submitBtn)
|
|
1620
1671
|
console.log(`[auto-webmcp] orphan: using disabled submit button as reference: "${submitBtn.textContent?.trim()}"`);
|
|
1621
1672
|
}
|
|
1673
|
+
if (!submitBtn) {
|
|
1674
|
+
const containerBtns = Array.from(container.querySelectorAll("button")).filter((b) => {
|
|
1675
|
+
const r = b.getBoundingClientRect();
|
|
1676
|
+
return r.width > 0 && r.height > 0 && !b.disabled && SUBMIT_TEXT_RE.test(b.textContent ?? "");
|
|
1677
|
+
});
|
|
1678
|
+
submitBtn = containerBtns[containerBtns.length - 1] ?? null;
|
|
1679
|
+
if (submitBtn)
|
|
1680
|
+
console.log(`[auto-webmcp] orphan: using text-matched button in container: "${submitBtn.textContent?.trim()}"`);
|
|
1681
|
+
}
|
|
1622
1682
|
if (!submitBtn) {
|
|
1623
1683
|
const pageBtns = Array.from(document.querySelectorAll("button")).filter(
|
|
1624
1684
|
(b) => {
|
|
@@ -1638,10 +1698,10 @@ async function scanOrphanInputs(config) {
|
|
|
1638
1698
|
const AUTO_ID_RE = /^_r_[0-9a-z]+_$/i;
|
|
1639
1699
|
for (const el of inputs) {
|
|
1640
1700
|
const id = el.id && !AUTO_ID_RE.test(el.id) ? el.id : null;
|
|
1641
|
-
const key = el.name || el.dataset["webmcpName"] || id || el.getAttribute("aria-label") ||
|
|
1701
|
+
const key = el.name || el.getAttribute("name") || el.dataset["webmcpName"] || id || el.getAttribute("aria-label") || el.getAttribute("placeholder") || null;
|
|
1642
1702
|
const safeKey = key ? key.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 64) : null;
|
|
1643
1703
|
const matched = !!(safeKey && schemaProps[safeKey]);
|
|
1644
|
-
console.log(`[auto-webmcp] orphan: field (name="${el.name}" id="${el.id}") rawKey="${key}" safeKey="${safeKey}" matched=${matched}`);
|
|
1704
|
+
console.log(`[auto-webmcp] orphan: field (name="${el.name ?? ""}" id="${el.id}") rawKey="${key}" safeKey="${safeKey}" matched=${matched}`);
|
|
1645
1705
|
if (matched) {
|
|
1646
1706
|
inputPairs.push({ key: safeKey, el });
|
|
1647
1707
|
}
|