uilint-react 0.2.9 → 0.2.10
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/README.md +35 -31
- package/dist/DevTool.d.ts +3 -3
- package/dist/DevTool.d.ts.map +1 -1
- package/dist/components/ui-lint/ElementBadges.d.ts.map +1 -1
- package/dist/components/ui-lint/InspectionPanel.d.ts.map +1 -1
- package/dist/components/ui-lint/LocatorOverlay.d.ts.map +1 -1
- package/dist/components/ui-lint/ScanResultsPopover.d.ts.map +1 -1
- package/dist/components/ui-lint/UILintUI.d.ts +5 -0
- package/dist/components/ui-lint/UILintUI.d.ts.map +1 -0
- package/dist/components/ui-lint/hooks/index.d.ts +4 -0
- package/dist/components/ui-lint/hooks/index.d.ts.map +1 -0
- package/dist/components/ui-lint/hooks/useAutoScans.d.ts +5 -0
- package/dist/components/ui-lint/hooks/useAutoScans.d.ts.map +1 -0
- package/dist/components/ui-lint/hooks/useDevToolEventHandlers.d.ts +5 -0
- package/dist/components/ui-lint/hooks/useDevToolEventHandlers.d.ts.map +1 -0
- package/dist/components/ui-lint/hooks/useNavigationDetection.d.ts +6 -0
- package/dist/components/ui-lint/hooks/useNavigationDetection.d.ts.map +1 -0
- package/dist/components/ui-lint/index.d.ts +1 -2
- package/dist/components/ui-lint/index.d.ts.map +1 -1
- package/dist/components/ui-lint/store.d.ts +18 -6
- package/dist/components/ui-lint/store.d.ts.map +1 -1
- package/dist/components/ui-lint/toolbar/icons.d.ts +4 -0
- package/dist/components/ui-lint/toolbar/icons.d.ts.map +1 -1
- package/dist/components/ui-lint/toolbar/index.d.ts.map +1 -1
- package/dist/components/ui-lint/toolbar/tabs/ConfigureTab.d.ts.map +1 -1
- package/dist/components/ui-lint/toolbar/tabs/ESLintTab.d.ts.map +1 -1
- package/dist/components/ui-lint/toolbar/tabs/VisionTab.d.ts.map +1 -1
- package/dist/components/ui-lint/types.d.ts +80 -35
- package/dist/components/ui-lint/types.d.ts.map +1 -1
- package/dist/devtools-types.d.ts +31 -0
- package/dist/devtools.js +93 -93
- package/dist/devtools.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12953 -42
- package/dist/index.js.map +1 -1
- package/dist/scanner/vision-capture.d.ts +1 -1
- package/dist/scanner/vision-capture.d.ts.map +1 -1
- package/dist/{vision-capture-EIrYA_XF.js → vision-capture-l4ZJB8M8.js} +89 -76
- package/dist/vision-capture-l4ZJB8M8.js.map +1 -0
- package/package.json +5 -4
- package/dist/ElementBadges-H5_y7fLt.js +0 -672
- package/dist/ElementBadges-H5_y7fLt.js.map +0 -1
- package/dist/VisionIssueBadge-Bw_1zmLh.js +0 -154
- package/dist/VisionIssueBadge-Bw_1zmLh.js.map +0 -1
- package/dist/components/ui-lint/UILintProvider.d.ts +0 -11
- package/dist/components/ui-lint/UILintProvider.d.ts.map +0 -1
- package/dist/index-Cu1-cGo1.js +0 -12839
- package/dist/index-Cu1-cGo1.js.map +0 -1
- package/dist/vision-capture-EIrYA_XF.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"vision-capture-EIrYA_XF.js","sources":["../src/scanner/vision-capture.ts"],"sourcesContent":["/**\n * Vision Capture Module\n *\n * Provides screenshot capture and element manifest building for vision-based analysis.\n * Uses html-to-image for DOM-to-image capture.\n */\n\n/**\n * Element manifest entry for vision analysis\n */\nexport interface ElementManifest {\n /** Unique ID (data-ui-lint-id if present, otherwise generated) */\n id: string;\n /** Visible text content (truncated to 100 chars) */\n text: string;\n /** data-loc value: \"path:line:column\" */\n dataLoc: string;\n /** Bounding rectangle */\n rect: { x: number; y: number; width: number; height: number };\n /** HTML tag name */\n tagName: string;\n /** Inferred semantic role (button, heading, link, etc.) */\n role?: string;\n /** Total instances with same dataLoc (if deduplicated) */\n instanceCount?: number;\n}\n\n/**\n * Vision analysis issue from the LLM\n */\nexport interface VisionIssue {\n /** Text of the element this issue refers to */\n elementText: string;\n /** Issue description */\n message: string;\n /** Issue category */\n category:\n | \"spacing\"\n | \"alignment\"\n | \"color\"\n | \"typography\"\n | \"layout\"\n | \"contrast\"\n | \"visual-hierarchy\"\n // backward/defensive (older payloads or custom models)\n | \"other\";\n /** Severity level */\n severity: \"error\" | \"warning\" | \"info\";\n /** Matched dataLoc from manifest (filled in after text matching) */\n dataLoc?: string;\n /** Matched element ID (filled in after text matching) */\n elementId?: string;\n}\n\n/**\n * Vision analysis result\n */\nexport interface VisionAnalysisResult {\n /** Route/path that was analyzed */\n route: string;\n /** Timestamp of capture */\n timestamp: number;\n /** Screenshot as base64 data URL */\n screenshotDataUrl?: string;\n /** Element manifest */\n manifest: ElementManifest[];\n /** Issues found by vision analysis */\n issues: VisionIssue[];\n /** Analysis duration in ms */\n analysisTime: number;\n /** Error message if analysis failed */\n error?: string;\n}\n\n/**\n * Tags to skip when collecting manifest\n */\nconst SKIP_TAGS = new Set([\n \"SCRIPT\",\n \"STYLE\",\n \"SVG\",\n \"PATH\",\n \"CIRCLE\",\n \"RECT\",\n \"LINE\",\n \"POLYGON\",\n \"POLYLINE\",\n \"ELLIPSE\",\n \"NOSCRIPT\",\n \"TEMPLATE\",\n \"SLOT\",\n]);\n\n/**\n * Max instances per dataLoc to include in manifest (for deduplication)\n */\nconst MAX_INSTANCES_PER_DATALOC = 3;\n\n/**\n * Max text length for element text\n */\nconst MAX_TEXT_LENGTH = 100;\n\n/**\n * Infer semantic role from element\n */\nfunction inferRole(element: Element): string | undefined {\n const tagName = element.tagName.toUpperCase();\n\n // Check explicit role attribute\n const explicitRole = element.getAttribute(\"role\");\n if (explicitRole) return explicitRole;\n\n // Infer from tag name\n switch (tagName) {\n case \"BUTTON\":\n return \"button\";\n case \"A\":\n return \"link\";\n case \"H1\":\n case \"H2\":\n case \"H3\":\n case \"H4\":\n case \"H5\":\n case \"H6\":\n return \"heading\";\n case \"INPUT\": {\n const type = (element as HTMLInputElement).type;\n if (type === \"submit\" || type === \"button\") return \"button\";\n if (type === \"checkbox\") return \"checkbox\";\n if (type === \"radio\") return \"radio\";\n return \"textbox\";\n }\n case \"TEXTAREA\":\n return \"textbox\";\n case \"SELECT\":\n return \"combobox\";\n case \"IMG\":\n return \"img\";\n case \"NAV\":\n return \"navigation\";\n case \"MAIN\":\n return \"main\";\n case \"HEADER\":\n return \"banner\";\n case \"FOOTER\":\n return \"contentinfo\";\n case \"ASIDE\":\n return \"complementary\";\n case \"ARTICLE\":\n return \"article\";\n case \"SECTION\":\n return \"region\";\n case \"FORM\":\n return \"form\";\n case \"TABLE\":\n return \"table\";\n case \"UL\":\n case \"OL\":\n return \"list\";\n case \"LI\":\n return \"listitem\";\n default:\n return undefined;\n }\n}\n\n/**\n * Get visible text content from element\n */\nfunction getVisibleText(element: Element): string {\n // Try innerText first (respects visibility)\n const innerText = (element as HTMLElement).innerText?.trim();\n if (innerText) {\n return innerText.length > MAX_TEXT_LENGTH\n ? innerText.slice(0, MAX_TEXT_LENGTH) + \"…\"\n : innerText;\n }\n\n // Fallback to aria-label\n const ariaLabel = element.getAttribute(\"aria-label\");\n if (ariaLabel) return ariaLabel;\n\n // Fallback to title\n const title = element.getAttribute(\"title\");\n if (title) return title;\n\n // Fallback to placeholder for inputs\n const placeholder = element.getAttribute(\"placeholder\");\n if (placeholder) return placeholder;\n\n // Fallback to alt for images\n const alt = element.getAttribute(\"alt\");\n if (alt) return alt;\n\n return \"\";\n}\n\n/**\n * Check if element is visible\n */\nfunction isElementVisible(element: Element): boolean {\n const htmlEl = element as HTMLElement;\n\n // Check computed style\n const style = window.getComputedStyle(htmlEl);\n if (style.display === \"none\") return false;\n if (style.visibility === \"hidden\") return false;\n if (style.opacity === \"0\") return false;\n\n // Check dimensions\n const rect = element.getBoundingClientRect();\n if (rect.width === 0 && rect.height === 0) return false;\n\n // Check if in viewport (with some margin)\n if (rect.bottom < -100 || rect.top > window.innerHeight + 100) return false;\n if (rect.right < -100 || rect.left > window.innerWidth + 100) return false;\n\n return true;\n}\n\n/**\n * Check if element rect intersects with a region\n */\nfunction rectIntersectsRegion(\n rect: DOMRect,\n region: { x: number; y: number; width: number; height: number }\n): boolean {\n const rectRight = rect.left + rect.width;\n const rectBottom = rect.top + rect.height;\n const regionRight = region.x + region.width;\n const regionBottom = region.y + region.height;\n\n // Check if rectangles overlap\n return !(\n rect.left > regionRight ||\n rectRight < region.x ||\n rect.top > regionBottom ||\n rectBottom < region.y\n );\n}\n\n/**\n * Collect element manifest from DOM\n *\n * Scans all elements with data-loc attributes and builds a manifest\n * with deduplication for repeated elements (e.g., list items).\n *\n * @param container - Container element to scan (default: document.body)\n * @param region - Optional region to filter elements (only include elements within this region)\n */\nexport function collectElementManifest(\n container: Element = document.body,\n region?: { x: number; y: number; width: number; height: number }\n): ElementManifest[] {\n const manifest: ElementManifest[] = [];\n const dataLocCounts = new Map<string, number>();\n const dataLocInstances = new Map<string, ElementManifest[]>();\n\n // Find all elements with data-loc\n const elements = container.querySelectorAll(\"[data-loc]\");\n\n for (const element of elements) {\n // Skip UILint's own elements\n if (element.closest(\"[data-ui-lint]\")) continue;\n\n // Skip certain tag types\n if (SKIP_TAGS.has(element.tagName)) continue;\n\n // Skip hidden elements\n if (!isElementVisible(element)) continue;\n\n // Skip elements outside the region (if region is specified)\n const rect = element.getBoundingClientRect();\n if (region && !rectIntersectsRegion(rect, region)) continue;\n\n const dataLoc = element.getAttribute(\"data-loc\");\n if (!dataLoc) continue;\n\n // Track instance count\n const currentCount = dataLocCounts.get(dataLoc) || 0;\n dataLocCounts.set(dataLoc, currentCount + 1);\n\n // Get or create instances array for this dataLoc\n let instances = dataLocInstances.get(dataLoc);\n if (!instances) {\n instances = [];\n dataLocInstances.set(dataLoc, instances);\n }\n\n // Only collect up to MAX_INSTANCES_PER_DATALOC\n if (instances.length >= MAX_INSTANCES_PER_DATALOC) continue;\n\n const text = getVisibleText(element);\n const id =\n element.getAttribute(\"data-ui-lint-id\") ||\n `loc:${dataLoc}#${currentCount}`;\n\n const entry: ElementManifest = {\n id,\n text,\n dataLoc,\n rect: {\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n },\n tagName: element.tagName.toLowerCase(),\n role: inferRole(element),\n };\n\n instances.push(entry);\n }\n\n // Build final manifest with instance counts\n for (const [dataLoc, instances] of dataLocInstances) {\n const totalCount = dataLocCounts.get(dataLoc) || instances.length;\n\n instances.forEach((entry, index) => {\n // Add instance count to first entry if there are more than shown\n if (index === 0 && totalCount > instances.length) {\n entry.instanceCount = totalCount;\n }\n manifest.push(entry);\n });\n }\n\n return manifest;\n}\n\n/**\n * Match vision issues to manifest entries by element text\n *\n * The LLM returns issues with elementText; we need to map back to dataLoc\n */\nexport function matchIssuesToManifest(\n issues: VisionIssue[],\n manifest: ElementManifest[]\n): VisionIssue[] {\n return issues.map((issue) => {\n // Try exact match first\n let match = manifest.find(\n (m) => m.text.toLowerCase() === issue.elementText.toLowerCase()\n );\n\n // Try partial match (text starts with or contains)\n if (!match) {\n match = manifest.find(\n (m) =>\n m.text.toLowerCase().includes(issue.elementText.toLowerCase()) ||\n issue.elementText.toLowerCase().includes(m.text.toLowerCase())\n );\n }\n\n if (match) {\n return {\n ...issue,\n dataLoc: match.dataLoc,\n elementId: match.id,\n };\n }\n\n return issue;\n });\n}\n\n/**\n * Capture screenshot of the current page\n *\n * Uses html-to-image library for DOM-to-image capture.\n * Falls back to canvas if html-to-image is not available.\n */\nexport async function captureScreenshot(): Promise<string> {\n // Try to use html-to-image if available\n const htmlToImage = await import(\"html-to-image\").catch(() => null);\n\n if (!htmlToImage) {\n throw new Error(\n \"Screenshot capture unavailable: `html-to-image` failed to load (check the uilint-react bundle/deps)\"\n );\n }\n\n try {\n const dataUrl = await htmlToImage.toPng(document.body, {\n // Keep file size down for WS transport\n pixelRatio: 1,\n cacheBust: true,\n filter: (node) => {\n // Skip UILint overlay elements\n if (node instanceof Element && node.closest(\"[data-ui-lint]\")) {\n return false;\n }\n return true;\n },\n });\n return dataUrl;\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n const msg = err.message || \"Unknown error\";\n\n // Common failure modes: cross-origin images/fonts taint the canvas.\n const hint = /tainted|cross[- ]origin|CORS|security/i.test(msg)\n ? \" Hint: this is often caused by cross-origin images/fonts; try removing external images or ensuring they allow CORS.\"\n : \"\";\n\n throw new Error(\n `Screenshot capture failed (html-to-image): ${msg}.${hint}`\n );\n }\n}\n\n/**\n * Capture screenshot of a specific region of the page\n *\n * @param region - The region to capture (in viewport coordinates)\n */\nexport async function captureScreenshotRegion(region: {\n x: number;\n y: number;\n width: number;\n height: number;\n}): Promise<string> {\n // Try to use html-to-image if available\n const htmlToImage = await import(\"html-to-image\").catch(() => null);\n\n if (!htmlToImage) {\n throw new Error(\n \"Screenshot capture unavailable: `html-to-image` failed to load (check the uilint-react bundle/deps)\"\n );\n }\n\n try {\n // Capture the full page first, then crop to the region\n // This is more reliable than trying to capture a specific element\n const dataUrl = await htmlToImage.toPng(document.body, {\n pixelRatio: 1,\n cacheBust: true,\n filter: (node) => {\n // Skip UILint overlay elements\n if (node instanceof Element && node.closest(\"[data-ui-lint]\")) {\n return false;\n }\n return true;\n },\n });\n\n // Crop the image to the selected region using canvas\n return await cropImageToRegion(dataUrl, region);\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n const msg = err.message || \"Unknown error\";\n\n // Common failure modes: cross-origin images/fonts taint the canvas.\n const hint = /tainted|cross[- ]origin|CORS|security/i.test(msg)\n ? \" Hint: this is often caused by cross-origin images/fonts; try removing external images or ensuring they allow CORS.\"\n : \"\";\n\n throw new Error(\n `Screenshot capture failed (html-to-image): ${msg}.${hint}`\n );\n }\n}\n\n/**\n * Crop an image data URL to a specific region\n */\nasync function cropImageToRegion(\n dataUrl: string,\n region: { x: number; y: number; width: number; height: number }\n): Promise<string> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = () => {\n try {\n // Create a canvas for cropping\n const canvas = document.createElement(\"canvas\");\n canvas.width = region.width;\n canvas.height = region.height;\n\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n reject(new Error(\"Failed to get canvas context\"));\n return;\n }\n\n // Draw the cropped region\n ctx.drawImage(\n img,\n region.x,\n region.y,\n region.width,\n region.height,\n 0,\n 0,\n region.width,\n region.height\n );\n\n // Convert to data URL\n const croppedDataUrl = canvas.toDataURL(\"image/png\");\n resolve(croppedDataUrl);\n } catch (error) {\n reject(\n new Error(\n `Failed to crop image: ${\n error instanceof Error ? error.message : String(error)\n }`\n )\n );\n }\n };\n img.onerror = () => {\n reject(new Error(\"Failed to load image for cropping\"));\n };\n img.src = dataUrl;\n });\n}\n\n/**\n * Get current route from URL\n */\nexport function getCurrentRoute(): string {\n const path = window.location.pathname;\n // Normalize: remove trailing slashes, handle index\n const normalized = path.replace(/\\/+$/, \"\") || \"/\";\n return normalized;\n}\n\n/**\n * Generate filename-safe timestamp\n */\nexport function generateTimestamp(): string {\n return new Date().toISOString().replace(/[:.]/g, \"-\");\n}\n\n/**\n * Build vision analysis request payload\n */\nexport function buildVisionAnalysisPayload(options: {\n screenshotDataUrl?: string;\n manifest: ElementManifest[];\n route: string;\n /** Screenshot filename saved under `.uilint/screenshots` (e.g. uilint-...png) */\n screenshotFile?: string;\n}) {\n return {\n type: \"vision:analyze\" as const,\n route: options.route,\n timestamp: Date.now(),\n screenshot: options.screenshotDataUrl,\n screenshotFile: options.screenshotFile,\n manifest: options.manifest,\n };\n}\n"],"names":["SKIP_TAGS","MAX_INSTANCES_PER_DATALOC","MAX_TEXT_LENGTH","inferRole","element","tagName","explicitRole","type","getVisibleText","innerText","ariaLabel","title","placeholder","alt","isElementVisible","htmlEl","style","rect","rectIntersectsRegion","region","rectRight","rectBottom","regionRight","regionBottom","collectElementManifest","container","manifest","dataLocCounts","dataLocInstances","elements","dataLoc","currentCount","instances","text","entry","totalCount","index","captureScreenshot","htmlToImage","node","error","msg","hint","captureScreenshotRegion","dataUrl","cropImageToRegion","resolve","reject","img","canvas","ctx","croppedDataUrl","getCurrentRoute","generateTimestamp"],"mappings":"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"}
|