alanbox 0.1.2 → 0.1.4

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 (94) hide show
  1. package/0boxer/AGENTS.md +26 -0
  2. package/0boxer/src/AGENTS.md +16 -0
  3. package/0boxer/src/cli.js +53 -0
  4. package/0boxer/src/commands/AGENTS.md +16 -0
  5. package/{0commondflowv1 → 0boxer}/src/commands/install.js +56 -0
  6. package/{0commondflowv1 → 1swarmer}/AGENTS.md +14 -12
  7. package/1swarmer/src/AGENTS.md +28 -0
  8. package/{0commondflowv1 → 1swarmer}/src/args.js +8 -1
  9. package/{0commondflowv1 → 1swarmer}/src/cli.js +27 -17
  10. package/1swarmer/src/commands/AGENTS.md +31 -0
  11. package/{0commondflowv1 → 1swarmer}/src/commands/doctor.js +2 -2
  12. package/1swarmer/src/commands/review-file.js +997 -0
  13. package/{0commondflowv1 → 1swarmer}/src/core/AGENTS.md +2 -2
  14. package/{0commondflowv1 → 1swarmer}/src/core/prompt-templates.js +1 -1
  15. package/{0commondflowv1 → 1swarmer}/src/core/storage.js +1 -1
  16. package/{0commondflowv1 → 1swarmer}/src/prompt/AGENTS.md +1 -1
  17. package/{0commondflowv1 → 1swarmer}/src/prompt/default.md +1 -1
  18. package/{0commondflowv1 → 1swarmer}/src/prompt/synthesizer.md +1 -1
  19. package/{0commondflowv1 → 1swarmer}/src/prompt/verifier.md +1 -1
  20. package/{0commondflowv1 → 1swarmer}/src/runner/AGENTS.md +4 -3
  21. package/{0commondflowv1 → 1swarmer}/src/runner/codex-runner.js +23 -3
  22. package/2designer/README.md +42 -0
  23. package/2designer/dist/cdp-engine-4AIWSWXO.js +314 -0
  24. package/2designer/dist/cdp-engine-4AIWSWXO.js.map +1 -0
  25. package/2designer/dist/cdp-engine-SG4K2BCX.js +10 -0
  26. package/2designer/dist/cdp-engine-SG4K2BCX.js.map +1 -0
  27. package/2designer/dist/chunk-7X7PTLZH.js +185 -0
  28. package/2designer/dist/chunk-7X7PTLZH.js.map +1 -0
  29. package/2designer/dist/chunk-DPOWNFOH.js +313 -0
  30. package/2designer/dist/chunk-DPOWNFOH.js.map +1 -0
  31. package/2designer/dist/chunk-ISUUIOO7.js +58 -0
  32. package/2designer/dist/chunk-ISUUIOO7.js.map +1 -0
  33. package/2designer/dist/chunk-NLYFLQ3C.js +74 -0
  34. package/2designer/dist/chunk-NLYFLQ3C.js.map +1 -0
  35. package/2designer/dist/chunk-UVKSRKXR.js +71 -0
  36. package/2designer/dist/chunk-UVKSRKXR.js.map +1 -0
  37. package/2designer/dist/cli.js +748 -0
  38. package/2designer/dist/cli.js.map +1 -0
  39. package/2designer/dist/index.d.ts +118 -0
  40. package/2designer/dist/index.js +37 -0
  41. package/2designer/dist/index.js.map +1 -0
  42. package/2designer/dist/playwright-engine-YXBY3KEN.js +186 -0
  43. package/2designer/dist/playwright-engine-YXBY3KEN.js.map +1 -0
  44. package/2designer/dist/playwright-engine-YXGDTSZ5.js +8 -0
  45. package/2designer/dist/playwright-engine-YXGDTSZ5.js.map +1 -0
  46. package/2designer/dist/tint-UD4CJ7S2.js +7 -0
  47. package/2designer/dist/tint-UD4CJ7S2.js.map +1 -0
  48. package/2designer/dist/tint-YN63MLVN.js +60 -0
  49. package/2designer/dist/tint-YN63MLVN.js.map +1 -0
  50. package/2designer/package.json +56 -0
  51. package/4reporter/README.md +24 -0
  52. package/4reporter/dist/cli.js +464 -0
  53. package/4reporter/dist/cli.js.map +1 -0
  54. package/4reporter/dist/index.d.ts +108 -0
  55. package/4reporter/dist/index.js +445 -0
  56. package/4reporter/dist/index.js.map +1 -0
  57. package/4reporter/package.json +39 -0
  58. package/README.md +20 -9
  59. package/bin/alanbox.js +11 -0
  60. package/bin/designer.js +10 -0
  61. package/bin/reporter.js +11 -0
  62. package/bin/swarmer.js +11 -0
  63. package/cli.js +178 -0
  64. package/hooks/hooks.json +1 -1
  65. package/mcp/README.md +7 -1
  66. package/mcp/config.toml +4 -0
  67. package/package.json +28 -11
  68. package/plugin/AGENTS.md +2 -2
  69. package/plugin/plugin.json +7 -7
  70. package/shared/AGENTS.md +15 -0
  71. package/shared/package-args.js +68 -0
  72. package/skills/AGENTS.md +9 -5
  73. package/skills/aitool/SKILL.md +36 -0
  74. package/skills/desginer/SKILL.md +142 -0
  75. package/skills/swarmer/SKILL.md +146 -0
  76. package/0commondflowv1/src/AGENTS.md +0 -26
  77. package/0commondflowv1/src/commands/AGENTS.md +0 -29
  78. package/bin/multirunagent.js +0 -15
  79. package/skills/aibox-swam/SKILL.md +0 -77
  80. package/skills/sub-codex-doctor/SKILL.md +0 -27
  81. package/skills/sub-codex-swarm/SKILL.md +0 -56
  82. /package/{0commondflowv1 → 1swarmer}/res/three-lens-review.js +0 -0
  83. /package/{0commondflowv1 → 1swarmer}/src/commands/info.js +0 -0
  84. /package/{0commondflowv1 → 1swarmer}/src/commands/swarm/auto.js +0 -0
  85. /package/{0commondflowv1 → 1swarmer}/src/commands/swarm/custom.js +0 -0
  86. /package/{0commondflowv1 → 1swarmer}/src/commands/swarm/index.js +0 -0
  87. /package/{0commondflowv1 → 1swarmer}/src/core/handoff.js +0 -0
  88. /package/{0commondflowv1 → 1swarmer}/src/core/prompt-builder.js +0 -0
  89. /package/{0commondflowv1 → 1swarmer}/src/core/swarm-executor.js +0 -0
  90. /package/{0commondflowv1 → 1swarmer}/src/core/workers.js +0 -0
  91. /package/{0commondflowv1 → 1swarmer}/src/core/workflow-planner.js +0 -0
  92. /package/{0commondflowv1 → 1swarmer}/src/core/workflow-storage.js +0 -0
  93. /package/{0commondflowv1 → 1swarmer}/src/prompt/reviewer.md +0 -0
  94. /package/{0commondflowv1 → 1swarmer}/src/runner/config.json +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts","../src/engine/create-engine.ts","../src/engine/selector.ts","../src/commands/measure.ts","../src/commands/screenshot.ts","../src/commands/overlay.ts","../src/commands/changelist.ts"],"sourcesContent":["import { Command } from 'commander'\nimport { measure } from './commands/measure.js'\nimport { screenshot } from './commands/screenshot.js'\nimport { overlay } from './commands/overlay.js'\nimport { changelist } from './commands/changelist.js'\n\nconst program = new Command()\n\nprogram\n .name('designer')\n .description(\n 'Runtime UI measurement CLI for AI agents: measure CSS/layout, capture screenshots, build overlays, and list visual changes.',\n )\n .version('0.1.0')\n\nprogram.addHelpText('after', `\nWorkflow (agent):\n 1. measure Read element bbox and computed CSS as JSON\n 2. screenshot Capture design/runtime component images\n 3. overlay Compare design image against runtime page\n 4. changelist List changed regions between design/runtime screenshots\n\nEngine selection:\n Default: Playwright (launches headless Chromium)\n --cdp <host:port>: Connect to an existing Chrome/WebView\n\nExamples:\n $ designer measure --url http://localhost:3000 --selector \".dialog\"\n $ designer measure --url http://127.0.0.1:32767/start.html --frame \"#mainFrame\" --selector \"#u0\"\n $ designer screenshot --url http://localhost:3000 --selector \".dialog\" --output runtime.png\n $ designer overlay --design design.png --url http://localhost:3000 --selector \".dialog\" --output overlay.png\n $ designer changelist --design design.png --runtime runtime.png --annotated changes.png\n`)\n\nconst measureCmd = program\n .command('measure')\n .description('Measure an element bbox, computed style, and optional child tree.')\n .requiredOption('--url <url>', 'Target page URL')\n .requiredOption('--selector <selector>', 'CSS selector to measure; prefix ~ for fuzzy class match')\n .option('--frame <selector>', 'Iframe CSS selector; measure --selector inside this frame document')\n .option('--depth <n>', 'Child element depth (0=no children)', '1')\n .option('--cdp <host:port>', 'CDP endpoint')\n .option('--pick <fields>', 'Pick bbox, children, or CSS property names (comma-separated)')\n .option('--format <format>', 'Output format: json | table', 'json')\n .action(measure)\n\nmeasureCmd.addHelpText('after', `\nOutput (json):\n {\n \"selector\": \".dialog\",\n \"bbox\": { \"x\": 100, \"y\": 200, \"width\": 400, \"height\": 300 },\n \"computedStyle\": { \"border-radius\": \"12px\", \"padding\": \"24px\" },\n \"children\": []\n }\n`)\n\nprogram\n .command('screenshot')\n .description('Capture a PNG screenshot of the full page or a specific element.')\n .requiredOption('--url <url>', 'Target page URL')\n .option('--selector <selector>', 'CSS selector; captures element only, prefix ~ for fuzzy class match')\n .option('--output <path>', 'Output file path (default: screenshot-<timestamp>.png)')\n .option('--full-page', 'Capture full scrollable page')\n .option('--cdp <host:port>', 'CDP endpoint')\n .action(screenshot)\n\nconst overlayCmd = program\n .command('overlay')\n .description('Generate a magenta design ghost overlay on top of a live page screenshot.')\n .requiredOption('--design <path>', 'Path to design screenshot (PNG/JPG)')\n .requiredOption('--url <url>', 'Target page URL')\n .option('--selector <selector>', 'CSS selector; composite ghost on element, prefix ~ for fuzzy class match')\n .option('--full-page', 'Capture full scrollable page')\n .option('--output <path>', 'Output file path (default: overlay-<timestamp>.png)')\n .option('--offset-x <px>', 'Horizontal offset of design overlay (full-page mode)')\n .option('--offset-y <px>', 'Vertical offset of design overlay (full-page mode)')\n .option('--scale <ratio>', 'Scale factor for design overlay (1 = 100%)')\n .option('--opacity <0-1>', 'Opacity of design overlay')\n .option('--cdp <host:port>', 'CDP endpoint')\n .action(overlay)\n\noverlayCmd.addHelpText('after', `\nModes:\n Selector:\n $ designer overlay --design design.png --url http://localhost:3000 --selector \".dialog\" --output overlay.png\n\n Direct full-page:\n $ designer overlay --design spec.png --url http://localhost:3000 --offset-x 0 --offset-y 0 --output overlay.png\n\n Without --selector, provide at least --offset-x or --offset-y for direct full-page mode.\n`)\n\nprogram\n .command('changelist')\n .description('Detect changed regions between a design screenshot and a runtime screenshot.')\n .requiredOption('--design <path>', 'Path to design screenshot (PNG/JPG)')\n .option('--runtime <path>', 'Path to runtime screenshot; use this or --url')\n .option('--url <url>', 'Target page URL to capture as runtime screenshot; use this or --runtime')\n .option('--selector <selector>', 'CSS selector when capturing --url; prefix ~ for fuzzy class match')\n .option('--full-page', 'Capture full scrollable page when using --url')\n .option('--cdp <host:port>', 'CDP endpoint when using --url')\n .option('--output <path>', 'Write changelist JSON to file; default prints JSON')\n .option('--annotated <path>', 'Write side-by-side comparison PNG; both mode also writes per-mode PNG files')\n .option('--regions-dir <dir>', 'Write per-region design/runtime/compare PNGs and region JSON by scan mode')\n .option('--mode <mode>', 'both | word-sentence | graphic-large', 'both')\n .option('--threshold <n>', 'Override difference threshold for selected scans')\n .option('--group <px>', 'Override grouping distance for selected scans')\n .option('--min-area <px>', 'Override minimum region area for selected scans')\n .option('--max-area-percent <pct>', 'Override max region area percent for selected scans')\n .action(changelist)\n\nprogram.parse()\n","import type { RuntimeEngine } from './types.js'\r\n\r\nexport interface EngineOptions {\r\n cdp?: string // host:port\r\n url: string\r\n viewport?: { width: number; height: number }\r\n headless?: boolean\r\n}\r\n\r\nexport function resolveEngineType(options: { cdp?: string }): 'cdp' | 'playwright' {\r\n return options.cdp ? 'cdp' : 'playwright'\r\n}\r\n\r\nexport async function createEngine(options: EngineOptions): Promise<RuntimeEngine> {\r\n const type = resolveEngineType(options)\r\n\r\n if (type === 'cdp') {\r\n const { CdpEngine } = await import('./cdp/cdp-engine.js')\r\n const [host, portStr] = options.cdp!.split(':')\r\n const port = parseInt(portStr, 10)\r\n return CdpEngine.create(host, port, options.url)\r\n }\r\n\r\n const { PlaywrightEngine } = await import('./playwright/playwright-engine.js')\r\n return PlaywrightEngine.create(options.url, {\r\n headless: options.headless ?? true,\r\n viewport: options.viewport,\r\n })\r\n}\r\n","/**\r\n * Resolve selector: if starts with ~, convert to [class*=\"...\"] fuzzy match.\r\n * Returns a standard CSS selector.\r\n */\r\nexport function resolveSelector(input: string): string {\r\n if (input.startsWith('~')) {\r\n const keyword = input.slice(1).trim()\r\n return `[class*=\"${keyword}\"]`\r\n }\r\n return input\r\n}\r\n","import type { MeasureResult, ChildElement } from '../engine/types.js'\r\nimport { createEngine } from '../engine/create-engine.js'\r\nimport { resolveSelector } from '../engine/selector.js'\r\n\r\nexport interface MeasureCommandOptions {\n url: string\n selector: string\n frame?: string\n depth: number\n cdp?: string\n format?: 'json' | 'table'\n pick?: string\n}\r\n\r\nexport function buildMeasureOptions(raw: Record<string, any>): MeasureCommandOptions {\r\n if (!raw.url) throw new Error('--url is required')\r\n if (!raw.selector) throw new Error('--selector is required')\r\n return {\r\n url: raw.url,\n selector: resolveSelector(raw.selector),\n frame: raw.frame ? resolveSelector(raw.frame) : undefined,\n depth: raw.depth != null ? parseInt(raw.depth, 10) : 1,\n cdp: raw.cdp,\n format: raw.format ?? 'json',\n pick: raw.pick,\r\n }\r\n}\r\n\r\nexport function formatMeasureResult(result: MeasureResult, format: 'json' | 'table'): string {\r\n if (format === 'table') {\r\n const lines: string[] = []\r\n lines.push(`Selector: ${result.selector}`)\r\n lines.push(`BBox: x=${result.bbox.x} y=${result.bbox.y} w=${result.bbox.width} h=${result.bbox.height}`)\r\n lines.push('')\r\n lines.push('Property'.padEnd(30) + 'Value')\r\n lines.push('-'.repeat(60))\r\n for (const [key, val] of Object.entries(result.computedStyle)) {\r\n lines.push(key.padEnd(30) + val)\r\n }\r\n if (result.children?.length) {\r\n lines.push('')\r\n lines.push(`Children (${result.children.length}):`)\r\n function printChildren(children: ChildElement[], indent: number) {\r\n for (const c of children) {\r\n const pad = ' '.repeat(indent)\r\n lines.push(`${pad}<${c.tag}> .${c.className} [${c.bbox.width}x${c.bbox.height}] ${c.text ?? ''}`)\r\n if (c.children?.length) {\r\n printChildren(c.children, indent + 2)\r\n }\r\n }\r\n }\r\n printChildren(result.children, 2)\r\n }\r\n return lines.join('\\n')\r\n }\r\n return JSON.stringify(result, null, 2)\r\n}\r\n\r\nexport function pickFields(result: MeasureResult, pick: string): string {\r\n if (pick === 'bbox') return JSON.stringify(result.bbox)\r\n if (pick === 'children') return JSON.stringify(result.children ?? [])\r\n // Otherwise treat as comma-separated CSS property names\r\n const props = pick.split(',').map(p => p.trim())\r\n const picked: Record<string, string> = {}\r\n for (const p of props) {\r\n if (result.computedStyle[p] != null) {\r\n picked[p] = result.computedStyle[p]\r\n }\r\n }\r\n return JSON.stringify(picked)\r\n}\r\n\r\nexport async function measure(raw: Record<string, any>): Promise<void> {\r\n const opts = buildMeasureOptions(raw)\r\n const engine = await createEngine({ url: opts.url, cdp: opts.cdp })\r\n try {\r\n const result = await engine.measure(opts.selector, opts.depth, opts.frame)\n if (opts.pick) {\r\n console.log(pickFields(result, opts.pick))\r\n } else {\r\n console.log(formatMeasureResult(result, opts.format ?? 'json'))\r\n }\r\n } finally {\r\n await engine.close()\r\n }\r\n}\r\n","import { writeFile, mkdir } from 'fs/promises'\r\nimport { dirname } from 'path'\r\nimport { createEngine } from '../engine/create-engine.js'\r\nimport { resolveSelector } from '../engine/selector.js'\r\n\r\nexport interface ScreenshotCommandOptions {\r\n url: string\r\n selector?: string\r\n output: string\r\n fullPage?: boolean\r\n cdp?: string\r\n}\r\n\r\nexport function buildScreenshotOptions(raw: Record<string, any>): ScreenshotCommandOptions {\r\n if (!raw.url) throw new Error('--url is required')\r\n return {\r\n url: raw.url,\r\n selector: raw.selector ? resolveSelector(raw.selector) : undefined,\r\n output: raw.output ?? `screenshot-${Date.now()}.png`,\r\n fullPage: raw.fullPage ?? false,\r\n cdp: raw.cdp,\r\n }\r\n}\r\n\r\nexport async function screenshot(raw: Record<string, any>): Promise<void> {\r\n const opts = buildScreenshotOptions(raw)\r\n const engine = await createEngine({ url: opts.url, cdp: opts.cdp })\r\n try {\r\n const buf = await engine.screenshot({\r\n selector: opts.selector,\r\n fullPage: opts.fullPage,\r\n })\r\n await mkdir(dirname(opts.output), { recursive: true }).catch(() => {})\r\n await writeFile(opts.output, buf)\r\n console.log(JSON.stringify({ output: opts.output, bytes: buf.length }))\r\n } finally {\r\n await engine.close()\r\n }\r\n}\r\n","import { writeFile, mkdir } from 'fs/promises'\nimport { resolve, dirname } from 'path'\nimport { createEngine } from '../engine/create-engine.js'\nimport { resolveSelector } from '../engine/selector.js'\n\r\nexport interface OverlayCommandOptions {\n designImagePath: string\n targetUrl: string\n cdp?: string\n output?: string\n selector?: string\n fullPage?: boolean\r\n offsetX?: number\r\n offsetY?: number\r\n scale?: number\r\n opacity?: number\r\n}\r\n\r\nexport function buildOverlayOptions(raw: Record<string, any>): OverlayCommandOptions {\r\n if (!raw.design) throw new Error('--design is required (path to design screenshot)')\r\n if (!raw.url) throw new Error('--url is required (target page URL)')\r\n\r\n return {\n designImagePath: resolve(raw.design),\n targetUrl: raw.url,\n cdp: raw.cdp,\n output: raw.output,\n selector: raw.selector ? resolveSelector(raw.selector) : undefined,\r\n offsetX: raw.offsetX != null ? parseFloat(raw.offsetX) : undefined,\r\n offsetY: raw.offsetY != null ? parseFloat(raw.offsetY) : undefined,\r\n scale: raw.scale != null ? parseFloat(raw.scale) : undefined,\r\n opacity: raw.opacity != null ? parseFloat(raw.opacity) : undefined,\r\n fullPage: raw.fullPage ?? false,\r\n }\r\n}\r\n\r\nasync function captureGhost(opts: OverlayCommandOptions, params: { offsetX: number; offsetY: number; scale: number; opacity: number }): Promise<void> {\r\n const engine = await createEngine({ url: opts.targetUrl, cdp: opts.cdp })\r\n try {\r\n await engine.injectOverlay({\r\n designImagePath: opts.designImagePath,\r\n targetUrl: opts.targetUrl,\r\n offsetX: params.offsetX,\r\n offsetY: params.offsetY,\r\n scale: params.scale,\r\n opacity: params.opacity,\r\n })\r\n const buf = await engine.captureOverlay({ fullPage: opts.fullPage })\r\n const outputPath = opts.output ?? `overlay-${Date.now()}.png`\r\n await mkdir(dirname(resolve(outputPath)), { recursive: true }).catch(() => {})\r\n await writeFile(outputPath, buf)\r\n console.log(JSON.stringify({ output: outputPath, bytes: buf.length }))\r\n } finally {\r\n await engine.close()\r\n }\r\n}\r\n\r\n/**\r\n * Selector mode: screenshot element + Sharp composite with tinted design.\r\n * No CSS positioning — pure pixel-level compositing for zero precision loss.\r\n */\r\nasync function compositeGhost(opts: OverlayCommandOptions): Promise<void> {\r\n const sharp = (await import('sharp')).default\r\n const { tintDesignImage } = await import('../overlay/tint.js')\r\n\r\n const engine = await createEngine({ url: opts.targetUrl, cdp: opts.cdp })\r\n let elementBuf: Buffer\r\n try {\r\n elementBuf = await engine.screenshot({ selector: opts.selector, fullPage: opts.fullPage })\r\n } finally {\r\n await engine.close()\r\n }\r\n\r\n const elementMeta = await sharp(elementBuf).metadata()\r\n const ew = elementMeta.width!\r\n const eh = elementMeta.height!\r\n\r\n const tintedBuf = await tintDesignImage(opts.designImagePath)\r\n const tintedResized = await sharp(tintedBuf)\r\n .resize(ew, eh, { fit: 'contain', background: { r: 0, g: 0, b: 0, alpha: 0 } })\r\n .toBuffer()\r\n\r\n const ghostBuf = await sharp(elementBuf)\r\n .composite([{ input: tintedResized, blend: 'over' }])\r\n .png()\r\n .toBuffer()\r\n\r\n const outputPath = opts.output ?? `overlay-${Date.now()}.png`\r\n await mkdir(dirname(resolve(outputPath)), { recursive: true }).catch(() => {})\r\n await writeFile(outputPath, ghostBuf)\r\n console.log(JSON.stringify({ output: outputPath, bytes: ghostBuf.length, selector: opts.selector, elementSize: { width: ew, height: eh } }))\r\n}\r\n\r\nexport async function overlay(raw: Record<string, any>): Promise<void> {\r\n const opts = buildOverlayOptions(raw)\r\n\r\n // Selector mode — Sharp composite, pixel-precise\r\n if (opts.selector) {\r\n await compositeGhost(opts)\r\n return\r\n }\r\n\r\n // Direct params — headless, no interaction\r\n if (opts.offsetX != null || opts.offsetY != null) {\r\n await captureGhost(opts, {\r\n offsetX: opts.offsetX ?? 0,\r\n offsetY: opts.offsetY ?? 0,\r\n scale: opts.scale ?? 1,\r\n opacity: opts.opacity ?? 1,\r\n })\r\n return\r\n }\r\n\r\n throw new Error('overlay requires --selector for component comparison, or --offset-x/--offset-y for full-page mode')\n}\n","import { readFile, writeFile, mkdir } from 'fs/promises'\nimport { basename, dirname, extname, join, resolve } from 'path'\nimport sharp from 'sharp'\nimport { createEngine } from '../engine/create-engine.js'\nimport { resolveSelector } from '../engine/selector.js'\n\nexport type ChangelistMode = 'word-sentence' | 'graphic-large'\nexport type ChangelistModeOption = ChangelistMode | 'both'\n\nexport interface ChangelistScanConfig {\n id: number\n mode: ChangelistMode\n label: string\n hiddenSlider: boolean\n threshold: number\n group: number\n minArea: number\n maxAreaPercent: number\n}\n\nexport interface ChangeRegion {\n id: number\n scanId: number\n mode: ChangelistMode\n x: number\n y: number\n width: number\n height: number\n area: number\n changedPixels: number\n changedPercent: number\n}\n\nexport interface ChangelistResult {\n design: string\n runtime: string\n size: { width: number; height: number }\n scans: Array<{\n id: number\n mode: ChangelistMode\n label: string\n params: Omit<ChangelistScanConfig, 'id' | 'mode' | 'label'>\n regions: ChangeRegion[]\n changedPixels: number\n changedPercent: number\n }>\n regions: ChangeRegion[]\n}\n\nexport interface ChangelistCommandOptions {\n designImagePath: string\n runtimeImagePath?: string\n runtimeUrl?: string\n selector?: string\n fullPage?: boolean\n cdp?: string\n output?: string\n annotated?: string\n regionsDir?: string\n mode: ChangelistModeOption\n threshold?: number\n group?: number\n minArea?: number\n maxAreaPercent?: number\n}\n\ninterface ImageData {\n data: Buffer\n width: number\n height: number\n}\n\ninterface Component {\n x: number\n y: number\n right: number\n bottom: number\n changedPixels: number\n}\n\ninterface AnnotatedOutput {\n path: string\n mode: ChangelistMode | 'combined'\n regions: number\n}\n\ninterface RegionExportOutput {\n dir: string\n mode: ChangelistMode\n regions: number\n}\n\nconst COMPARISON_GAP = 32\n\nconst DEFAULT_SCANS: ChangelistScanConfig[] = [\n {\n id: 1,\n mode: 'word-sentence',\n label: 'word / sentence',\n hiddenSlider: true,\n threshold: 20,\n group: 12,\n minArea: 114,\n maxAreaPercent: 15,\n },\n {\n id: 2,\n mode: 'graphic-large',\n label: 'graphic / large region',\n hiddenSlider: true,\n threshold: 25,\n group: 25,\n minArea: 761,\n maxAreaPercent: 50,\n },\n]\n\nexport function buildChangelistOptions(raw: Record<string, any>): ChangelistCommandOptions {\n if (!raw.design) throw new Error('--design is required (path to design screenshot)')\n if (raw.runtime && raw.url) throw new Error('Use either --runtime or --url, not both')\n if (!raw.runtime && !raw.url) throw new Error('--runtime or --url is required')\n\n return {\n designImagePath: resolve(raw.design),\n runtimeImagePath: raw.runtime ? resolve(raw.runtime) : undefined,\n runtimeUrl: raw.url,\n selector: raw.selector ? resolveSelector(raw.selector) : undefined,\n fullPage: raw.fullPage ?? false,\n cdp: raw.cdp,\n output: raw.output,\n annotated: raw.annotated,\n regionsDir: raw.regionsDir,\n mode: parseMode(raw.mode ?? 'both'),\n threshold: raw.threshold != null ? parseNumber(raw.threshold, '--threshold') : undefined,\n group: raw.group != null ? parseNumber(raw.group, '--group') : undefined,\n minArea: raw.minArea != null ? parseNumber(raw.minArea, '--min-area') : undefined,\n maxAreaPercent: raw.maxAreaPercent != null\n ? parsePercent(raw.maxAreaPercent, '--max-area-percent')\n : undefined,\n }\n}\n\nexport function resolveScanConfigs(opts: Pick<ChangelistCommandOptions, 'mode' | 'threshold' | 'group' | 'minArea' | 'maxAreaPercent'>): ChangelistScanConfig[] {\n const scans = DEFAULT_SCANS\n .filter(scan => opts.mode === 'both' || scan.mode === opts.mode)\n .map(scan => ({\n ...scan,\n threshold: opts.threshold ?? scan.threshold,\n group: opts.group ?? scan.group,\n minArea: opts.minArea ?? scan.minArea,\n maxAreaPercent: opts.maxAreaPercent ?? scan.maxAreaPercent,\n }))\n\n if (scans.length === 0) throw new Error(`Unsupported mode: ${opts.mode}`)\n return scans\n}\n\nexport async function detectChangelist(\n designImagePath: string,\n runtimeImage: string | Buffer,\n scans: ChangelistScanConfig[] = DEFAULT_SCANS,\n): Promise<ChangelistResult> {\n const design = await loadImage(designImagePath)\n const runtime = await loadImage(runtimeImage)\n\n if (design.width !== runtime.width || design.height !== runtime.height) {\n throw new Error(`Image sizes differ: design ${design.width}x${design.height}, runtime ${runtime.width}x${runtime.height}`)\n }\n\n const scanResults = scans.map(scan => {\n const mask = buildDiffMask(design, runtime, scan.threshold)\n const changedPixels = countMask(mask)\n const components = findComponents(mask, design.width, design.height)\n const grouped = mergeComponents(components, scan.group, maxRegionArea(scan, design.width, design.height))\n const regions = filterRegions(grouped, scan, design.width, design.height)\n\n return {\n id: scan.id,\n mode: scan.mode,\n label: scan.label,\n params: {\n hiddenSlider: scan.hiddenSlider,\n threshold: scan.threshold,\n group: scan.group,\n minArea: scan.minArea,\n maxAreaPercent: scan.maxAreaPercent,\n },\n regions,\n changedPixels,\n changedPercent: roundPercent(changedPixels / (design.width * design.height)),\n }\n })\n\n let nextId = 1\n const regions = scanResults\n .flatMap(scan => scan.regions.map(region => ({ ...region, id: nextId++ })))\n .sort((a, b) => b.area - a.area || a.y - b.y || a.x - b.x)\n .map((region, index) => ({ ...region, id: index + 1 }))\n\n return {\n design: designImagePath,\n runtime: typeof runtimeImage === 'string' ? runtimeImage : '<captured>',\n size: { width: design.width, height: design.height },\n scans: scanResults,\n regions,\n }\n}\n\nexport async function changelist(raw: Record<string, any>): Promise<void> {\n const opts = buildChangelistOptions(raw)\n const scans = resolveScanConfigs(opts)\n const runtime = opts.runtimeImagePath ?? await captureRuntime(opts)\n const result = await detectChangelist(opts.designImagePath, runtime, scans)\n let annotatedOutputs: AnnotatedOutput[] | undefined\n let regionOutputs: RegionExportOutput[] | undefined\n\n if (opts.annotated) {\n annotatedOutputs = await writeAnnotatedImages(opts.annotated, opts.designImagePath, runtime, scans, result)\n }\n\n if (opts.regionsDir) {\n regionOutputs = await writeRegionExports(opts.regionsDir, opts.designImagePath, runtime, scans, result)\n }\n\n if (opts.output) {\n await writeOutputFile(opts.output, Buffer.from(`${JSON.stringify(result, null, 2)}\\n`, 'utf8'))\n console.log(JSON.stringify({\n output: opts.output,\n annotated: annotatedOutputs ?? opts.annotated,\n regionsDir: regionOutputs ?? opts.regionsDir,\n regions: result.regions.length,\n scans: result.scans.map(scan => ({ id: scan.id, mode: scan.mode, regions: scan.regions.length })),\n }))\n return\n }\n\n console.log(JSON.stringify(result, null, 2))\n}\n\nasync function writeAnnotatedImages(\n annotatedPath: string,\n designImagePath: string,\n runtimeImage: string | Buffer,\n scans: ChangelistScanConfig[],\n result: ChangelistResult,\n): Promise<AnnotatedOutput[]> {\n const outputs: AnnotatedOutput[] = []\n\n if (scans.length > 1) {\n const combined = await renderComparisonImage(designImagePath, runtimeImage, scans, result.regions)\n await writeOutputFile(annotatedPath, combined)\n outputs.push({ path: annotatedPath, mode: 'combined', regions: result.regions.length })\n }\n\n for (const scan of scans) {\n const scanResult = result.scans.find(item => item.id === scan.id)\n const outputPath = scans.length === 1 ? annotatedPath : appendModeSuffix(annotatedPath, scan.mode)\n const image = await renderComparisonImage(designImagePath, runtimeImage, [scan], scanResult?.regions ?? [])\n await writeOutputFile(outputPath, image)\n outputs.push({ path: outputPath, mode: scan.mode, regions: scanResult?.regions.length ?? 0 })\n }\n\n return outputs\n}\n\nasync function writeRegionExports(\n outputRoot: string,\n designImagePath: string,\n runtimeImage: string | Buffer,\n scans: ChangelistScanConfig[],\n result: ChangelistResult,\n): Promise<RegionExportOutput[]> {\n const designBuffer = await readFile(designImagePath)\n const runtimeBuffer = typeof runtimeImage === 'string' ? await readFile(runtimeImage) : runtimeImage\n const outputs: RegionExportOutput[] = []\n\n for (const scan of scans) {\n const scanResult = result.scans.find(item => item.id === scan.id)\n const regions = scanResult?.regions ?? []\n const modeDir = join(outputRoot, regionDirName(scan.mode))\n\n for (const region of regions) {\n const regionDir = join(modeDir, String(region.id))\n const designCrop = await cropRegion(designBuffer, region)\n const runtimeCrop = await cropRegion(runtimeBuffer, region)\n const compare = await renderRegionPairImage(designCrop, runtimeCrop, region)\n const regionJson = {\n ...region,\n source: {\n design: designImagePath,\n runtime: typeof runtimeImage === 'string' ? runtimeImage : '<captured>',\n size: result.size,\n },\n scan: {\n id: scan.id,\n mode: scan.mode,\n label: scan.label,\n params: scanResult?.params,\n },\n }\n\n await writeOutputFile(join(regionDir, 'design.png'), designCrop)\n await writeOutputFile(join(regionDir, 'runtime.png'), runtimeCrop)\n await writeOutputFile(join(regionDir, 'compare.png'), compare)\n await writeOutputFile(join(regionDir, 'region.json'), Buffer.from(`${JSON.stringify(regionJson, null, 2)}\\n`, 'utf8'))\n }\n\n outputs.push({ dir: modeDir, mode: scan.mode, regions: regions.length })\n }\n\n return outputs\n}\n\nasync function captureRuntime(opts: ChangelistCommandOptions): Promise<Buffer> {\n if (!opts.runtimeUrl) throw new Error('--url is required when --runtime is not provided')\n\n const engine = await createEngine({ url: opts.runtimeUrl, cdp: opts.cdp })\n try {\n return await engine.screenshot({\n selector: opts.selector,\n fullPage: opts.fullPage,\n })\n } finally {\n await engine.close()\n }\n}\n\nasync function loadImage(input: string | Buffer): Promise<ImageData> {\n const source = typeof input === 'string' ? await readFile(input) : input\n const { data, info } = await sharp(source)\n .ensureAlpha()\n .raw()\n .toBuffer({ resolveWithObject: true })\n\n return {\n data,\n width: info.width,\n height: info.height,\n }\n}\n\nfunction buildDiffMask(design: ImageData, runtime: ImageData, threshold: number): Uint8Array {\n const total = design.width * design.height\n const mask = new Uint8Array(total)\n\n for (let pixel = 0, offset = 0; pixel < total; pixel++, offset += 4) {\n const diff = Math.max(\n Math.abs(design.data[offset] - runtime.data[offset]),\n Math.abs(design.data[offset + 1] - runtime.data[offset + 1]),\n Math.abs(design.data[offset + 2] - runtime.data[offset + 2]),\n Math.abs(design.data[offset + 3] - runtime.data[offset + 3]),\n )\n if (diff >= threshold) mask[pixel] = 1\n }\n\n return mask\n}\n\nfunction buildUnionDiffMask(design: ImageData, runtime: ImageData, scans: ChangelistScanConfig[]): Uint8Array {\n const total = design.width * design.height\n const mask = new Uint8Array(total)\n\n for (const scan of scans) {\n const scanMask = buildDiffMask(design, runtime, scan.threshold)\n for (let i = 0; i < total; i++) {\n if (scanMask[i]) mask[i] = 1\n }\n }\n\n return mask\n}\n\nfunction countMask(mask: Uint8Array): number {\n let count = 0\n for (const value of mask) count += value\n return count\n}\n\nfunction findComponents(mask: Uint8Array, width: number, height: number): Component[] {\n const visited = new Uint8Array(mask.length)\n const components: Component[] = []\n const queue: number[] = []\n\n for (let start = 0; start < mask.length; start++) {\n if (!mask[start] || visited[start]) continue\n\n visited[start] = 1\n queue.length = 0\n queue.push(start)\n\n let head = 0\n let changedPixels = 0\n let minX = width\n let minY = height\n let maxX = 0\n let maxY = 0\n\n while (head < queue.length) {\n const idx = queue[head++]\n const x = idx % width\n const y = Math.floor(idx / width)\n\n changedPixels++\n if (x < minX) minX = x\n if (y < minY) minY = y\n if (x > maxX) maxX = x\n if (y > maxY) maxY = y\n\n for (let dy = -1; dy <= 1; dy++) {\n const ny = y + dy\n if (ny < 0 || ny >= height) continue\n\n for (let dx = -1; dx <= 1; dx++) {\n if (dx === 0 && dy === 0) continue\n const nx = x + dx\n if (nx < 0 || nx >= width) continue\n\n const next = ny * width + nx\n if (!mask[next] || visited[next]) continue\n visited[next] = 1\n queue.push(next)\n }\n }\n }\n\n components.push({\n x: minX,\n y: minY,\n right: maxX + 1,\n bottom: maxY + 1,\n changedPixels,\n })\n }\n\n return components\n}\n\nfunction mergeComponents(components: Component[], group: number, maxArea: number): Component[] {\n const regions = components.map(component => ({ ...component }))\n let changed = true\n\n while (changed) {\n changed = false\n for (let i = 0; i < regions.length; i++) {\n for (let j = i + 1; j < regions.length; j++) {\n if (!shouldMerge(regions[i], regions[j], group)) continue\n const merged = mergeRegion(regions[i], regions[j])\n if (componentArea(merged) > maxArea) continue\n\n regions[i] = merged\n regions.splice(j, 1)\n changed = true\n j--\n }\n }\n }\n\n return regions\n}\n\nfunction maxRegionArea(scan: ChangelistScanConfig, width: number, height: number): number {\n return width * height * (scan.maxAreaPercent / 100)\n}\n\nfunction shouldMerge(a: Component, b: Component, gap: number): boolean {\n return !(\n a.right + gap < b.x ||\n b.right + gap < a.x ||\n a.bottom + gap < b.y ||\n b.bottom + gap < a.y\n )\n}\n\nfunction componentArea(component: Component): number {\n return (component.right - component.x) * (component.bottom - component.y)\n}\n\nfunction mergeRegion(a: Component, b: Component): Component {\n return {\n x: Math.min(a.x, b.x),\n y: Math.min(a.y, b.y),\n right: Math.max(a.right, b.right),\n bottom: Math.max(a.bottom, b.bottom),\n changedPixels: a.changedPixels + b.changedPixels,\n }\n}\n\nfunction filterRegions(\n components: Component[],\n scan: ChangelistScanConfig,\n width: number,\n height: number,\n): ChangeRegion[] {\n const imageArea = width * height\n return components\n .map(componentToRegion(scan, imageArea))\n .filter(region => region.area >= scan.minArea)\n .filter(region => region.changedPercent <= scan.maxAreaPercent)\n .sort((a, b) => b.area - a.area || a.y - b.y || a.x - b.x)\n .map((region, index) => ({ ...region, id: index + 1 }))\n}\n\nfunction componentToRegion(scan: ChangelistScanConfig, imageArea: number) {\n return (component: Component): ChangeRegion => {\n const width = component.right - component.x\n const height = component.bottom - component.y\n const area = width * height\n return {\n id: 0,\n scanId: scan.id,\n mode: scan.mode,\n x: component.x,\n y: component.y,\n width,\n height,\n area,\n changedPixels: component.changedPixels,\n changedPercent: roundPercent(area / imageArea),\n }\n }\n}\n\nasync function cropRegion(image: Buffer, region: ChangeRegion): Promise<Buffer> {\n return sharp(image)\n .extract({\n left: region.x,\n top: region.y,\n width: region.width,\n height: region.height,\n })\n .png()\n .toBuffer()\n}\n\nasync function renderRegionPairImage(designCrop: Buffer, runtimeCrop: Buffer, region: ChangeRegion): Promise<Buffer> {\n const designMeta = await sharp(designCrop).metadata()\n const runtimeMeta = await sharp(runtimeCrop).metadata()\n const width = designMeta.width ?? region.width\n const height = designMeta.height ?? region.height\n\n if (width !== runtimeMeta.width || height !== runtimeMeta.height) {\n throw new Error(`Region crop sizes differ for region ${region.id}: design ${width}x${height}, runtime ${runtimeMeta.width}x${runtimeMeta.height}`)\n }\n\n const runtimeOffsetX = width + COMPARISON_GAP\n const outputWidth = width * 2 + COMPARISON_GAP\n\n return sharp({\n create: {\n width: outputWidth,\n height,\n channels: 4,\n background: { r: 248, g: 250, b: 252, alpha: 1 },\n },\n })\n .composite([\n { input: designCrop, left: 0, top: 0 },\n { input: runtimeCrop, left: runtimeOffsetX, top: 0 },\n { input: Buffer.from(buildDividerSvg(outputWidth, height, runtimeOffsetX)), blend: 'over' },\n ])\n .png()\n .toBuffer()\n}\n\nexport async function renderComparisonImage(\n designImagePath: string,\n runtimeImage: string | Buffer,\n scans: ChangelistScanConfig[],\n regions: ChangeRegion[],\n): Promise<Buffer> {\n const design = await loadImage(designImagePath)\n const runtime = await loadImage(runtimeImage)\n\n if (design.width !== runtime.width || design.height !== runtime.height) {\n throw new Error(`Image sizes differ: design ${design.width}x${design.height}, runtime ${runtime.width}x${runtime.height}`)\n }\n\n const mask = buildUnionDiffMask(design, runtime, scans)\n const highlightedRuntime = Buffer.from(runtime.data)\n\n for (let pixel = 0, offset = 0; pixel < mask.length; pixel++, offset += 4) {\n if (!mask[pixel]) continue\n\n highlightedRuntime[offset] = 255\n highlightedRuntime[offset + 1] = Math.round(highlightedRuntime[offset + 1] * 0.35)\n highlightedRuntime[offset + 2] = Math.round(highlightedRuntime[offset + 2] * 0.35)\n highlightedRuntime[offset + 3] = 255\n }\n\n const runtimeOffsetX = design.width + COMPARISON_GAP\n const outputWidth = design.width * 2 + COMPARISON_GAP\n const designPanel = await imageDataToPng(design)\n const runtimePanel = await imageDataToPng({ ...runtime, data: highlightedRuntime })\n const svg = buildSideBySideRegionSvg(outputWidth, design.height, runtimeOffsetX, regions)\n\n return sharp({\n create: {\n width: outputWidth,\n height: design.height,\n channels: 4,\n background: { r: 248, g: 250, b: 252, alpha: 1 },\n },\n })\n .composite([\n { input: designPanel, left: 0, top: 0 },\n { input: runtimePanel, left: runtimeOffsetX, top: 0 },\n { input: Buffer.from(svg), blend: 'over' },\n ])\n .png()\n .toBuffer()\n}\n\nfunction imageDataToPng(image: ImageData): Promise<Buffer> {\n return sharp(image.data, {\n raw: {\n width: image.width,\n height: image.height,\n channels: 4,\n },\n })\n .png()\n .toBuffer()\n}\n\nfunction buildSideBySideRegionSvg(width: number, height: number, runtimeOffsetX: number, regions: ChangeRegion[]): string {\n const svg = [\n `<svg width=\"${width}\" height=\"${height}\" viewBox=\"0 0 ${width} ${height}\" xmlns=\"http://www.w3.org/2000/svg\">`,\n dividerSvgContent(height, runtimeOffsetX),\n ...regions.flatMap(region => [\n regionToSvg(region, 0),\n regionToSvg(region, runtimeOffsetX),\n ]),\n '</svg>',\n ].join('')\n\n return svg\n}\n\nfunction buildDividerSvg(width: number, height: number, runtimeOffsetX: number): string {\n return [\n `<svg width=\"${width}\" height=\"${height}\" viewBox=\"0 0 ${width} ${height}\" xmlns=\"http://www.w3.org/2000/svg\">`,\n dividerSvgContent(height, runtimeOffsetX),\n '</svg>',\n ].join('')\n}\n\nfunction dividerSvgContent(height: number, runtimeOffsetX: number): string {\n return [\n `<rect x=\"${runtimeOffsetX - COMPARISON_GAP}\" y=\"0\" width=\"${COMPARISON_GAP}\" height=\"${height}\" fill=\"#f8fafc\"/>`,\n `<line x1=\"${runtimeOffsetX - COMPARISON_GAP / 2}\" y1=\"0\" x2=\"${runtimeOffsetX - COMPARISON_GAP / 2}\" y2=\"${height}\" stroke=\"#d9e2ec\" stroke-width=\"1\"/>`,\n ].join('')\n}\n\nfunction regionToSvg(region: ChangeRegion, offsetX: number): string {\n const labelWidth = Math.max(14, String(region.id).length * 8 + 8)\n const labelX = Math.max(offsetX, offsetX + region.x + region.width - labelWidth)\n const labelY = Math.max(0, region.y - 12)\n return [\n `<rect x=\"${offsetX + region.x + 0.5}\" y=\"${region.y + 0.5}\" width=\"${Math.max(1, region.width - 1)}\" height=\"${Math.max(1, region.height - 1)}\" fill=\"none\" stroke=\"#ef3b2d\" stroke-width=\"1\"/>`,\n `<rect x=\"${labelX}\" y=\"${labelY}\" width=\"${labelWidth}\" height=\"14\" fill=\"#ef3b2d\"/>`,\n `<text x=\"${labelX + labelWidth / 2}\" y=\"${labelY + 10}\" text-anchor=\"middle\" font-family=\"Arial, sans-serif\" font-size=\"10\" font-weight=\"700\" fill=\"#fff\">${region.id}</text>`,\n ].join('')\n}\n\nasync function writeOutputFile(filePath: string, data: Buffer): Promise<void> {\n await mkdir(dirname(resolve(filePath)), { recursive: true }).catch(() => {})\n await writeFile(filePath, data)\n}\n\nfunction appendModeSuffix(filePath: string, mode: ChangelistMode): string {\n const ext = extname(filePath) || '.png'\n const name = extname(filePath) ? basename(filePath, extname(filePath)) : basename(filePath)\n return join(dirname(filePath), `${name}-${mode}${ext}`)\n}\n\nfunction regionDirName(mode: ChangelistMode): string {\n return mode === 'word-sentence' ? 'word' : 'graphic'\n}\n\nfunction parseMode(value: string): ChangelistModeOption {\n const normalized = String(value).trim().toLowerCase()\n if (['both', 'all'].includes(normalized)) return 'both'\n if (['word', 'words', 'sentence', 'sentences', 'word-sentence', 'word_sentence', 'text'].includes(normalized)) {\n return 'word-sentence'\n }\n if (['graphic', 'graphics', 'large', 'large-region', 'graphic-large', 'graphic_large'].includes(normalized)) {\n return 'graphic-large'\n }\n throw new Error(`invalid mode: ${value}. Use both, word-sentence, or graphic-large.`)\n}\n\nfunction parseNumber(value: unknown, flag: string): number {\n const n = Number(value)\n if (!Number.isFinite(n) || n < 0) throw new Error(`${flag} must be a non-negative number`)\n return n\n}\n\nfunction parsePercent(value: unknown, flag: string): number {\n const raw = String(value).trim().replace(/%$/, '')\n const n = Number(raw)\n if (!Number.isFinite(n) || n < 0 || n > 100) {\n throw new Error(`${flag} must be a number between 0 and 100`)\n }\n return n\n}\n\nfunction roundPercent(value: number): number {\n return Math.round(value * 10000) / 100\n}\n"],"mappings":"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","names":["printChildren","writeFile","mkdir","dirname","mkdir","dirname","writeFile","sharp","writeFile","mkdir","dirname","resolve","resolve","regions","mkdir","dirname","writeFile"]}
@@ -0,0 +1,118 @@
1
+ interface BBox {
2
+ x: number;
3
+ y: number;
4
+ width: number;
5
+ height: number;
6
+ top: number;
7
+ right: number;
8
+ bottom: number;
9
+ left: number;
10
+ }
11
+ interface ChildElement {
12
+ tag: string;
13
+ className: string;
14
+ bbox: BBox;
15
+ text?: string;
16
+ children?: ChildElement[];
17
+ }
18
+ interface MeasureResult {
19
+ selector: string;
20
+ frameSelector?: string;
21
+ bbox: BBox;
22
+ computedStyle: Record<string, string>;
23
+ children?: ChildElement[];
24
+ }
25
+ interface OverlayParams {
26
+ designImagePath: string;
27
+ targetUrl: string;
28
+ offsetX: number;
29
+ offsetY: number;
30
+ scale: number;
31
+ opacity: number;
32
+ scrollY?: number;
33
+ }
34
+ interface ScreenshotOptions {
35
+ selector?: string;
36
+ fullPage?: boolean;
37
+ output?: string;
38
+ }
39
+ interface RuntimeEngine {
40
+ /** Take a screenshot, optionally of a specific element */
41
+ screenshot(options?: ScreenshotOptions): Promise<Buffer>;
42
+ /** Measure an element's bbox + computed style */
43
+ measure(selector: string, depth?: number, frameSelector?: string): Promise<MeasureResult>;
44
+ /** Execute JavaScript in the page context */
45
+ evaluate<T = unknown>(expression: string): Promise<T>;
46
+ /** Inject a design overlay image onto the page */
47
+ injectOverlay(params: OverlayParams): Promise<void>;
48
+ /** Capture the page with overlay applied */
49
+ captureOverlay(options?: ScreenshotOptions): Promise<Buffer>;
50
+ /** Clean up resources */
51
+ close(): Promise<void>;
52
+ }
53
+
54
+ interface EngineOptions {
55
+ cdp?: string;
56
+ url: string;
57
+ viewport?: {
58
+ width: number;
59
+ height: number;
60
+ };
61
+ headless?: boolean;
62
+ }
63
+ declare function resolveEngineType(options: {
64
+ cdp?: string;
65
+ }): 'cdp' | 'playwright';
66
+ declare function createEngine(options: EngineOptions): Promise<RuntimeEngine>;
67
+
68
+ declare class CdpEngine implements RuntimeEngine {
69
+ private client;
70
+ private pageUrl;
71
+ private constructor();
72
+ static create(host: string, port: number, urlFilter?: string): Promise<CdpEngine>;
73
+ screenshot(options?: ScreenshotOptions): Promise<Buffer>;
74
+ measure(selector: string, depth?: number, frameSelector?: string): Promise<MeasureResult>;
75
+ evaluate<T = unknown>(expression: string): Promise<T>;
76
+ injectOverlay(params: OverlayParams): Promise<void>;
77
+ captureOverlay(options?: ScreenshotOptions): Promise<Buffer>;
78
+ close(): Promise<void>;
79
+ private getViewport;
80
+ }
81
+
82
+ interface PlaywrightEngineOptions {
83
+ headless?: boolean;
84
+ viewport?: {
85
+ width: number;
86
+ height: number;
87
+ };
88
+ deviceScaleFactor?: number;
89
+ waitUntil?: 'load' | 'domcontentloaded' | 'networkidle' | 'commit';
90
+ waitTimeout?: number;
91
+ }
92
+ declare class PlaywrightEngine implements RuntimeEngine {
93
+ private browser;
94
+ private page;
95
+ private constructor();
96
+ static create(url: string, options?: PlaywrightEngineOptions): Promise<PlaywrightEngine>;
97
+ screenshot(options?: ScreenshotOptions): Promise<Buffer>;
98
+ measure(selector: string, depth?: number, frameSelector?: string): Promise<MeasureResult>;
99
+ evaluate<T = unknown>(expression: string): Promise<T>;
100
+ injectOverlay(params: OverlayParams): Promise<void>;
101
+ captureOverlay(options?: ScreenshotOptions): Promise<Buffer>;
102
+ close(): Promise<void>;
103
+ }
104
+
105
+ type TintMode = 'magenta' | 'ghost' | 'difference';
106
+ /**
107
+ * 处理设计稿截图,生成适合叠到运行页上的 PNG 重影。
108
+ *
109
+ * 模式说明:
110
+ * - 'magenta': 把非白色像素染成品红,适合白底或浅色背景的设计稿。
111
+ * - 'ghost': 只统一降低透明度,适合背景不是纯白的截图。
112
+ * - 'difference': 不预处理,由调用方使用 difference 混合模式。
113
+ *
114
+ * 返回带 alpha 通道的 PNG buffer。
115
+ */
116
+ declare function tintDesignImage(imagePath: string, mode?: TintMode): Promise<Buffer>;
117
+
118
+ export { type BBox, CdpEngine, type ChildElement, type EngineOptions, type MeasureResult, type OverlayParams, PlaywrightEngine, type RuntimeEngine, type ScreenshotOptions, createEngine, resolveEngineType, tintDesignImage };
@@ -0,0 +1,37 @@
1
+ import {
2
+ tintDesignImage
3
+ } from "./chunk-ISUUIOO7.js";
4
+ import {
5
+ CdpEngine
6
+ } from "./chunk-DPOWNFOH.js";
7
+ import {
8
+ PlaywrightEngine
9
+ } from "./chunk-7X7PTLZH.js";
10
+ import "./chunk-UVKSRKXR.js";
11
+
12
+ // src/engine/create-engine.ts
13
+ function resolveEngineType(options) {
14
+ return options.cdp ? "cdp" : "playwright";
15
+ }
16
+ async function createEngine(options) {
17
+ const type = resolveEngineType(options);
18
+ if (type === "cdp") {
19
+ const { CdpEngine: CdpEngine2 } = await import("./cdp-engine-SG4K2BCX.js");
20
+ const [host, portStr] = options.cdp.split(":");
21
+ const port = parseInt(portStr, 10);
22
+ return CdpEngine2.create(host, port, options.url);
23
+ }
24
+ const { PlaywrightEngine: PlaywrightEngine2 } = await import("./playwright-engine-YXGDTSZ5.js");
25
+ return PlaywrightEngine2.create(options.url, {
26
+ headless: options.headless ?? true,
27
+ viewport: options.viewport
28
+ });
29
+ }
30
+ export {
31
+ CdpEngine,
32
+ PlaywrightEngine,
33
+ createEngine,
34
+ resolveEngineType,
35
+ tintDesignImage
36
+ };
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/engine/create-engine.ts"],"sourcesContent":["import type { RuntimeEngine } from './types.js'\r\n\r\nexport interface EngineOptions {\r\n cdp?: string // host:port\r\n url: string\r\n viewport?: { width: number; height: number }\r\n headless?: boolean\r\n}\r\n\r\nexport function resolveEngineType(options: { cdp?: string }): 'cdp' | 'playwright' {\r\n return options.cdp ? 'cdp' : 'playwright'\r\n}\r\n\r\nexport async function createEngine(options: EngineOptions): Promise<RuntimeEngine> {\r\n const type = resolveEngineType(options)\r\n\r\n if (type === 'cdp') {\r\n const { CdpEngine } = await import('./cdp/cdp-engine.js')\r\n const [host, portStr] = options.cdp!.split(':')\r\n const port = parseInt(portStr, 10)\r\n return CdpEngine.create(host, port, options.url)\r\n }\r\n\r\n const { PlaywrightEngine } = await import('./playwright/playwright-engine.js')\r\n return PlaywrightEngine.create(options.url, {\r\n headless: options.headless ?? true,\r\n viewport: options.viewport,\r\n })\r\n}\r\n"],"mappings":";;;;;;;;;;;;AASO,SAAS,kBAAkB,SAAiD;AACjF,SAAO,QAAQ,MAAM,QAAQ;AAC/B;AAEA,eAAsB,aAAa,SAAgD;AACjF,QAAM,OAAO,kBAAkB,OAAO;AAEtC,MAAI,SAAS,OAAO;AAClB,UAAM,EAAE,WAAAA,WAAU,IAAI,MAAM,OAAO,0BAAqB;AACxD,UAAM,CAAC,MAAM,OAAO,IAAI,QAAQ,IAAK,MAAM,GAAG;AAC9C,UAAM,OAAO,SAAS,SAAS,EAAE;AACjC,WAAOA,WAAU,OAAO,MAAM,MAAM,QAAQ,GAAG;AAAA,EACjD;AAEA,QAAM,EAAE,kBAAAC,kBAAiB,IAAI,MAAM,OAAO,iCAAmC;AAC7E,SAAOA,kBAAiB,OAAO,QAAQ,KAAK;AAAA,IAC1C,UAAU,QAAQ,YAAY;AAAA,IAC9B,UAAU,QAAQ;AAAA,EACpB,CAAC;AACH;","names":["CdpEngine","PlaywrightEngine"]}
@@ -0,0 +1,186 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {
4
+ MEASURE_RETRY_INTERVAL_MS,
5
+ MEASURE_WAIT_TIMEOUT_MS,
6
+ RELEVANT_PROPS,
7
+ REQUIRED_MEASURE_PROPS
8
+ } from "./chunk-NLYFLQ3C.js";
9
+
10
+ // src/engine/playwright/playwright-engine.ts
11
+ var PlaywrightEngine = class _PlaywrightEngine {
12
+ browser;
13
+ page;
14
+ constructor(browser, page) {
15
+ this.browser = browser;
16
+ this.page = page;
17
+ }
18
+ static async create(url, options = {}) {
19
+ const { chromium } = await import("playwright");
20
+ const browser = await chromium.launch({
21
+ headless: options.headless ?? true
22
+ });
23
+ const context = await browser.newContext({
24
+ viewport: options.viewport ?? { width: 1920, height: 1080 },
25
+ deviceScaleFactor: options.deviceScaleFactor ?? 1
26
+ });
27
+ const page = await context.newPage();
28
+ await page.goto(url, {
29
+ waitUntil: options.waitUntil ?? "networkidle",
30
+ timeout: options.waitTimeout ?? 15e3
31
+ });
32
+ return new _PlaywrightEngine(browser, page);
33
+ }
34
+ async screenshot(options) {
35
+ if (options?.selector) {
36
+ const el = await this.page.waitForSelector(options.selector, {
37
+ timeout: 5e3,
38
+ state: "visible"
39
+ });
40
+ return el.screenshot({ type: "png" });
41
+ }
42
+ return this.page.screenshot({
43
+ type: "png",
44
+ fullPage: options?.fullPage ?? false
45
+ });
46
+ }
47
+ async measure(selector, depth = 1, frameSelector) {
48
+ const maxDepth = Number.isFinite(depth) ? Math.max(0, depth) : 1;
49
+ const handle = await this.page.waitForFunction(
50
+ ({
51
+ sel,
52
+ frameSel,
53
+ props,
54
+ requiredProps,
55
+ maxDepth: maxDepth2
56
+ }) => {
57
+ function toBBox(rect, origin) {
58
+ const originX = origin?.x ?? 0;
59
+ const originY = origin?.y ?? 0;
60
+ const originLeft = origin?.left ?? 0;
61
+ const originTop = origin?.top ?? 0;
62
+ return {
63
+ x: +(rect.x - originX).toFixed(1),
64
+ y: +(rect.y - originY).toFixed(1),
65
+ width: +rect.width.toFixed(1),
66
+ height: +rect.height.toFixed(1),
67
+ top: +(rect.top - originTop).toFixed(1),
68
+ right: +(rect.right - originLeft).toFixed(1),
69
+ bottom: +(rect.bottom - originTop).toFixed(1),
70
+ left: +(rect.left - originLeft).toFixed(1)
71
+ };
72
+ }
73
+ function isValidBBox(bbox2) {
74
+ return Object.values(bbox2).every(Number.isFinite);
75
+ }
76
+ function collectStyle(win2, el2) {
77
+ const cs = win2.getComputedStyle(el2);
78
+ const style2 = {};
79
+ props.forEach((p) => {
80
+ style2[p] = p === "font" ? cs.font : cs.getPropertyValue(p);
81
+ });
82
+ return style2;
83
+ }
84
+ function hasRequiredStyle(style2) {
85
+ return requiredProps.every((p) => typeof style2[p] === "string" && style2[p] !== "");
86
+ }
87
+ function collectChildren(parent, parentRect, currentDepth, maxDep) {
88
+ if (currentDepth >= maxDep) return [];
89
+ const result2 = [];
90
+ for (const child of parent.children) {
91
+ const cr = child.getBoundingClientRect();
92
+ const node = {
93
+ tag: child.tagName.toLowerCase(),
94
+ className: (child.className || "").toString().substring(0, 120),
95
+ bbox: toBBox(cr, parentRect),
96
+ text: (child.textContent || "").substring(0, 80).trim() || void 0
97
+ };
98
+ if (currentDepth + 1 < maxDep && child.children.length > 0) {
99
+ node.children = collectChildren(child, cr, currentDepth + 1, maxDep);
100
+ }
101
+ result2.push(node);
102
+ }
103
+ return result2;
104
+ }
105
+ let doc = document;
106
+ let win = window;
107
+ if (frameSel) {
108
+ const frame = document.querySelector(frameSel);
109
+ if (!frame || !frame.contentDocument || !frame.contentWindow) return null;
110
+ doc = frame.contentDocument;
111
+ win = frame.contentWindow;
112
+ }
113
+ const el = doc.querySelector(sel);
114
+ if (!el) return null;
115
+ const r = el.getBoundingClientRect();
116
+ const bbox = toBBox(r);
117
+ const style = collectStyle(win, el);
118
+ if (!isValidBBox(bbox)) return null;
119
+ if (!hasRequiredStyle(style)) return null;
120
+ if (bbox.width <= 0 || bbox.height <= 0 || style.display === "none" || style.visibility === "hidden") {
121
+ return null;
122
+ }
123
+ return {
124
+ bbox,
125
+ computedStyle: style,
126
+ children: maxDepth2 > 0 ? collectChildren(el, r, 0, maxDepth2) : []
127
+ };
128
+ },
129
+ {
130
+ sel: selector,
131
+ frameSel: frameSelector,
132
+ props: RELEVANT_PROPS,
133
+ requiredProps: REQUIRED_MEASURE_PROPS,
134
+ maxDepth
135
+ },
136
+ {
137
+ timeout: MEASURE_WAIT_TIMEOUT_MS,
138
+ polling: MEASURE_RETRY_INTERVAL_MS
139
+ }
140
+ );
141
+ const result = await handle.jsonValue();
142
+ return frameSelector ? { selector, frameSelector, ...result } : { selector, ...result };
143
+ }
144
+ async evaluate(expression) {
145
+ return this.page.evaluate(expression);
146
+ }
147
+ async injectOverlay(params) {
148
+ const { tintDesignImage } = await import("./tint-YN63MLVN.js");
149
+ const tintedBuf = await tintDesignImage(params.designImagePath);
150
+ const base64 = tintedBuf.toString("base64");
151
+ await this.page.evaluate(
152
+ ({ b64, opacity, offsetX, offsetY, scale, scrollY }) => {
153
+ let overlay = document.getElementById("__design_ruler_overlay__");
154
+ if (!overlay) {
155
+ overlay = document.createElement("img");
156
+ overlay.id = "__design_ruler_overlay__";
157
+ overlay.style.cssText = "position:fixed;top:0;left:0;width:100vw;height:auto;pointer-events:none;z-index:999999;";
158
+ document.body.appendChild(overlay);
159
+ }
160
+ overlay.src = `data:image/png;base64,${b64}`;
161
+ overlay.style.opacity = String(opacity);
162
+ overlay.style.transform = `translate(${offsetX}px, ${offsetY}px) scale(${scale})`;
163
+ overlay.style.transformOrigin = "top left";
164
+ if (scrollY > 0) window.scrollTo(0, scrollY);
165
+ },
166
+ {
167
+ b64: base64,
168
+ opacity: params.opacity,
169
+ offsetX: params.offsetX,
170
+ offsetY: params.offsetY,
171
+ scale: params.scale,
172
+ scrollY: params.scrollY ?? 0
173
+ }
174
+ );
175
+ }
176
+ async captureOverlay(options) {
177
+ return this.screenshot(options);
178
+ }
179
+ async close() {
180
+ await this.browser.close();
181
+ }
182
+ };
183
+ export {
184
+ PlaywrightEngine
185
+ };
186
+ //# sourceMappingURL=playwright-engine-YXBY3KEN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/engine/playwright/playwright-engine.ts"],"sourcesContent":["import type { RuntimeEngine, MeasureResult, ScreenshotOptions, OverlayParams } from '../types.js'\nimport {\n MEASURE_RETRY_INTERVAL_MS,\n MEASURE_WAIT_TIMEOUT_MS,\n RELEVANT_PROPS,\n REQUIRED_MEASURE_PROPS,\n} from '../constants.js'\n\r\nexport interface PlaywrightEngineOptions {\r\n headless?: boolean\r\n viewport?: { width: number; height: number }\r\n deviceScaleFactor?: number\r\n waitUntil?: 'load' | 'domcontentloaded' | 'networkidle' | 'commit'\r\n waitTimeout?: number\r\n}\r\n\r\nexport class PlaywrightEngine implements RuntimeEngine {\r\n private browser: any\r\n private page: any\r\n\r\n private constructor(browser: any, page: any) {\r\n this.browser = browser\r\n this.page = page\r\n }\r\n\r\n static async create(\r\n url: string,\r\n options: PlaywrightEngineOptions = {},\r\n ): Promise<PlaywrightEngine> {\r\n const { chromium } = await import('playwright')\r\n const browser = await chromium.launch({\r\n headless: options.headless ?? true,\r\n })\r\n const context = await browser.newContext({\r\n viewport: options.viewport ?? { width: 1920, height: 1080 },\r\n deviceScaleFactor: options.deviceScaleFactor ?? 1,\r\n })\r\n const page = await context.newPage()\r\n await page.goto(url, {\r\n waitUntil: options.waitUntil ?? 'networkidle',\r\n timeout: options.waitTimeout ?? 15000,\r\n })\r\n return new PlaywrightEngine(browser, page)\r\n }\r\n\r\n async screenshot(options?: ScreenshotOptions): Promise<Buffer> {\r\n if (options?.selector) {\r\n const el = await this.page.waitForSelector(options.selector, {\r\n timeout: 5000,\r\n state: 'visible',\r\n })\r\n return el.screenshot({ type: 'png' })\r\n }\r\n return this.page.screenshot({\r\n type: 'png',\r\n fullPage: options?.fullPage ?? false,\r\n })\r\n }\r\n\r\n async measure(selector: string, depth = 1, frameSelector?: string): Promise<MeasureResult> {\n const maxDepth = Number.isFinite(depth) ? Math.max(0, depth) : 1\n const handle = await this.page.waitForFunction(\n (\n {\n sel,\n frameSel,\n props,\n requiredProps,\n maxDepth,\n }: { sel: string; frameSel?: string; props: string[]; requiredProps: string[]; maxDepth: number },\n ) => {\n function toBBox(rect: DOMRect, origin?: DOMRect) {\n const originX = origin?.x ?? 0\n const originY = origin?.y ?? 0\n const originLeft = origin?.left ?? 0\n const originTop = origin?.top ?? 0\n return {\n x: +(rect.x - originX).toFixed(1),\n y: +(rect.y - originY).toFixed(1),\n width: +rect.width.toFixed(1),\n height: +rect.height.toFixed(1),\n top: +(rect.top - originTop).toFixed(1),\n right: +(rect.right - originLeft).toFixed(1),\n bottom: +(rect.bottom - originTop).toFixed(1),\n left: +(rect.left - originLeft).toFixed(1),\n }\n }\n\n function isValidBBox(bbox: Record<string, number>) {\n return Object.values(bbox).every(Number.isFinite)\n }\n\n function collectStyle(win: Window, el: Element) {\n const cs = win.getComputedStyle(el)\n const style: Record<string, string> = {}\n props.forEach(p => {\n style[p] = p === 'font' ? cs.font : cs.getPropertyValue(p)\n })\n return style\n }\n\n function hasRequiredStyle(style: Record<string, string>) {\n return requiredProps.every(p => typeof style[p] === 'string' && style[p] !== '')\n }\n\n function collectChildren(\n parent: Element,\n parentRect: DOMRect,\n currentDepth: number,\n maxDep: number,\n ): any[] {\n if (currentDepth >= maxDep) return []\n const result: any[] = []\n for (const child of parent.children) {\n const cr = child.getBoundingClientRect()\n const node: any = {\n tag: child.tagName.toLowerCase(),\n className: (child.className || '').toString().substring(0, 120),\n bbox: toBBox(cr, parentRect),\n text: (child.textContent || '').substring(0, 80).trim() || undefined,\n }\n if (currentDepth + 1 < maxDep && child.children.length > 0) {\n node.children = collectChildren(child, cr, currentDepth + 1, maxDep)\r\n }\r\n result.push(node)\r\n }\n return result\n }\n\n let doc: Document = document\n let win: Window = window\n if (frameSel) {\n const frame = document.querySelector(frameSel) as HTMLIFrameElement | null\n if (!frame || !frame.contentDocument || !frame.contentWindow) return null\n doc = frame.contentDocument\n win = frame.contentWindow\n }\n\n const el = doc.querySelector(sel)\n if (!el) return null\n const r = el.getBoundingClientRect()\n const bbox = toBBox(r)\n const style = collectStyle(win, el)\n if (!isValidBBox(bbox)) return null\n if (!hasRequiredStyle(style)) return null\n if (bbox.width <= 0 || bbox.height <= 0 || style.display === 'none' || style.visibility === 'hidden') {\n return null\n }\n\n return {\n bbox,\n computedStyle: style,\n children: maxDepth > 0 ? collectChildren(el, r, 0, maxDepth) : [],\n }\n },\n {\n sel: selector,\n frameSel: frameSelector,\n props: RELEVANT_PROPS,\n requiredProps: REQUIRED_MEASURE_PROPS,\n maxDepth,\n },\n {\n timeout: MEASURE_WAIT_TIMEOUT_MS,\n polling: MEASURE_RETRY_INTERVAL_MS,\n },\n )\n const result = await handle.jsonValue()\n return frameSelector ? { selector, frameSelector, ...result } : { selector, ...result }\n }\n\r\n async evaluate<T = unknown>(expression: string): Promise<T> {\r\n return this.page.evaluate(expression)\r\n }\r\n\r\n async injectOverlay(params: OverlayParams): Promise<void> {\r\n const { tintDesignImage } = await import('../../overlay/tint.js')\r\n const tintedBuf = await tintDesignImage(params.designImagePath)\r\n const base64 = tintedBuf.toString('base64')\r\n await this.page.evaluate(\r\n ({ b64, opacity, offsetX, offsetY, scale, scrollY }: any) => {\r\n let overlay = document.getElementById('__design_ruler_overlay__') as HTMLImageElement\r\n if (!overlay) {\r\n overlay = document.createElement('img')\r\n overlay.id = '__design_ruler_overlay__'\r\n overlay.style.cssText =\r\n 'position:fixed;top:0;left:0;width:100vw;height:auto;pointer-events:none;z-index:999999;'\r\n document.body.appendChild(overlay)\r\n }\r\n overlay.src = `data:image/png;base64,${b64}`\r\n overlay.style.opacity = String(opacity)\r\n overlay.style.transform = `translate(${offsetX}px, ${offsetY}px) scale(${scale})`\r\n overlay.style.transformOrigin = 'top left'\r\n if (scrollY > 0) window.scrollTo(0, scrollY)\r\n },\r\n {\r\n b64: base64,\r\n opacity: params.opacity,\r\n offsetX: params.offsetX,\r\n offsetY: params.offsetY,\r\n scale: params.scale,\r\n scrollY: params.scrollY ?? 0,\r\n },\r\n )\r\n }\r\n\r\n async captureOverlay(options?: import('../types.js').ScreenshotOptions): Promise<Buffer> {\r\n return this.screenshot(options)\r\n }\r\n\r\n async close(): Promise<void> {\r\n await this.browser.close()\r\n }\r\n}\r\n"],"mappings":"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","names":["maxDepth","bbox","win","el","style","result"]}
@@ -0,0 +1,8 @@
1
+ import {
2
+ PlaywrightEngine
3
+ } from "./chunk-7X7PTLZH.js";
4
+ import "./chunk-UVKSRKXR.js";
5
+ export {
6
+ PlaywrightEngine
7
+ };
8
+ //# sourceMappingURL=playwright-engine-YXGDTSZ5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,7 @@
1
+ import {
2
+ tintDesignImage
3
+ } from "./chunk-ISUUIOO7.js";
4
+ export {
5
+ tintDesignImage
6
+ };
7
+ //# sourceMappingURL=tint-UD4CJ7S2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env node
2
+
3
+
4
+ // src/overlay/tint.ts
5
+ import sharp from "sharp";
6
+ async function tintDesignImage(imagePath, mode = "auto") {
7
+ const { data, info } = await sharp(imagePath).ensureAlpha().raw().toBuffer({ resolveWithObject: true });
8
+ const pixels = new Uint8Array(data.buffer);
9
+ const resolvedMode = mode === "auto" ? detectMode(pixels) : mode;
10
+ if (resolvedMode === "magenta") {
11
+ return tintMagenta(pixels, info);
12
+ }
13
+ if (resolvedMode === "difference") {
14
+ return sharp(imagePath).ensureAlpha().png().toBuffer();
15
+ }
16
+ return tintGhost(pixels, info, 0.4);
17
+ }
18
+ function detectMode(pixels) {
19
+ let brightCount = 0;
20
+ const sampleSize = Math.min(pixels.length / 4, 1e3);
21
+ const step = Math.floor(pixels.length / 4 / sampleSize);
22
+ for (let i = 0; i < sampleSize; i++) {
23
+ const idx = i * step * 4;
24
+ const brightness = (pixels[idx] + pixels[idx + 1] + pixels[idx + 2]) / 3;
25
+ if (brightness > 220) brightCount++;
26
+ }
27
+ return brightCount / sampleSize > 0.5 ? "magenta" : "ghost";
28
+ }
29
+ var LIGHT_THRESHOLD = 230;
30
+ var MAGENTA = [220, 40, 160];
31
+ function tintMagenta(pixels, info) {
32
+ for (let i = 0; i < pixels.length; i += 4) {
33
+ const r = pixels[i], g = pixels[i + 1], b = pixels[i + 2];
34
+ const brightness = (r + g + b) / 3;
35
+ if (brightness > LIGHT_THRESHOLD) {
36
+ pixels[i + 3] = 0;
37
+ } else {
38
+ const darkness = 1 - brightness / 255;
39
+ pixels[i] = MAGENTA[0];
40
+ pixels[i + 1] = MAGENTA[1];
41
+ pixels[i + 2] = MAGENTA[2];
42
+ pixels[i + 3] = Math.round(darkness * 200);
43
+ }
44
+ }
45
+ return sharp(Buffer.from(pixels.buffer), {
46
+ raw: { width: info.width, height: info.height, channels: 4 }
47
+ }).png().toBuffer();
48
+ }
49
+ function tintGhost(pixels, info, opacity) {
50
+ for (let i = 0; i < pixels.length; i += 4) {
51
+ pixels[i + 3] = Math.round(pixels[i + 3] * opacity);
52
+ }
53
+ return sharp(Buffer.from(pixels.buffer), {
54
+ raw: { width: info.width, height: info.height, channels: 4 }
55
+ }).png().toBuffer();
56
+ }
57
+ export {
58
+ tintDesignImage
59
+ };
60
+ //# sourceMappingURL=tint-YN63MLVN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/overlay/tint.ts"],"sourcesContent":["import sharp from 'sharp'\r\n\r\nexport type TintMode = 'magenta' | 'ghost' | 'difference'\r\n\r\n/**\n * 处理设计稿截图,生成适合叠到运行页上的 PNG 重影。\n *\n * 模式说明:\n * - 'magenta': 把非白色像素染成品红,适合白底或浅色背景的设计稿。\n * - 'ghost': 只统一降低透明度,适合背景不是纯白的截图。\n * - 'difference': 不预处理,由调用方使用 difference 混合模式。\n *\n * 返回带 alpha 通道的 PNG buffer。\n */\nexport async function tintDesignImage(\n imagePath: string,\r\n mode: TintMode = 'auto' as any,\r\n): Promise<Buffer> {\r\n const { data, info } = await sharp(imagePath)\r\n .ensureAlpha()\r\n .raw()\r\n .toBuffer({ resolveWithObject: true })\r\n\r\n const pixels = new Uint8Array(data.buffer)\r\n\r\n // 自动模式只粗略判断背景亮度:白底走品红染色,深色/复杂背景走 ghost。\n const resolvedMode = mode === ('auto' as any) ? detectMode(pixels) : mode\n\r\n if (resolvedMode === 'magenta') {\r\n return tintMagenta(pixels, info)\r\n }\n\n if (resolvedMode === 'difference') {\n // difference 模式需要保留原图颜色,混合策略交给调用方处理。\n return sharp(imagePath).ensureAlpha().png().toBuffer()\n }\n\n // ghost 模式不改颜色,只统一压低 alpha,避免覆盖运行页细节。\n return tintGhost(pixels, info, 0.4)\n}\n\nfunction detectMode(pixels: Uint8Array): TintMode {\n // 采样前若干像素估算背景亮度;当前目标是快速区分浅底和非浅底,不做精确抠图。\n let brightCount = 0\n const sampleSize = Math.min(pixels.length / 4, 1000)\r\n const step = Math.floor(pixels.length / 4 / sampleSize)\r\n\r\n for (let i = 0; i < sampleSize; i++) {\r\n const idx = i * step * 4\r\n const brightness = (pixels[idx] + pixels[idx + 1] + pixels[idx + 2]) / 3\r\n if (brightness > 220) brightCount++\r\n }\r\n\r\n return (brightCount / sampleSize) > 0.5 ? 'magenta' : 'ghost'\r\n}\r\n\r\nconst LIGHT_THRESHOLD = 230\nconst MAGENTA: [number, number, number] = [220, 40, 160]\n\r\nfunction tintMagenta(\r\n pixels: Uint8Array,\r\n info: { width: number; height: number },\r\n): Promise<Buffer> {\r\n for (let i = 0; i < pixels.length; i += 4) {\n const r = pixels[i], g = pixels[i + 1], b = pixels[i + 2]\n const brightness = (r + g + b) / 3\n\n if (brightness > LIGHT_THRESHOLD) {\n // 浅色背景直接透明化,避免白底盖住运行页。\n pixels[i + 3] = 0\n } else {\n // 像素越暗说明设计内容越明显,叠层 alpha 越高,便于观察 1-2px 偏差。\n const darkness = 1 - brightness / 255\n pixels[i] = MAGENTA[0]\n pixels[i + 1] = MAGENTA[1]\r\n pixels[i + 2] = MAGENTA[2]\r\n pixels[i + 3] = Math.round(darkness * 200)\r\n }\r\n }\r\n\r\n return sharp(Buffer.from(pixels.buffer), {\r\n raw: { width: info.width, height: info.height, channels: 4 },\r\n })\r\n .png()\r\n .toBuffer()\r\n}\r\n\r\nfunction tintGhost(\r\n pixels: Uint8Array,\r\n info: { width: number; height: number },\r\n opacity: number,\r\n): Promise<Buffer> {\n for (let i = 0; i < pixels.length; i += 4) {\n // 仅缩放 alpha,保留原图色相,用于非白底设计稿的低侵入叠加。\n pixels[i + 3] = Math.round(pixels[i + 3] * opacity)\n }\n\r\n return sharp(Buffer.from(pixels.buffer), {\r\n raw: { width: info.width, height: info.height, channels: 4 },\r\n })\r\n .png()\r\n .toBuffer()\r\n}\r\n"],"mappings":";;;;AAAA,OAAO,WAAW;AAclB,eAAsB,gBACpB,WACA,OAAiB,QACA;AACjB,QAAM,EAAE,MAAM,KAAK,IAAI,MAAM,MAAM,SAAS,EACzC,YAAY,EACZ,IAAI,EACJ,SAAS,EAAE,mBAAmB,KAAK,CAAC;AAEvC,QAAM,SAAS,IAAI,WAAW,KAAK,MAAM;AAGzC,QAAM,eAAe,SAAU,SAAiB,WAAW,MAAM,IAAI;AAErE,MAAI,iBAAiB,WAAW;AAC9B,WAAO,YAAY,QAAQ,IAAI;AAAA,EACjC;AAEA,MAAI,iBAAiB,cAAc;AAEjC,WAAO,MAAM,SAAS,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS;AAAA,EACvD;AAGA,SAAO,UAAU,QAAQ,MAAM,GAAG;AACpC;AAEA,SAAS,WAAW,QAA8B;AAEhD,MAAI,cAAc;AAClB,QAAM,aAAa,KAAK,IAAI,OAAO,SAAS,GAAG,GAAI;AACnD,QAAM,OAAO,KAAK,MAAM,OAAO,SAAS,IAAI,UAAU;AAEtD,WAAS,IAAI,GAAG,IAAI,YAAY,KAAK;AACnC,UAAM,MAAM,IAAI,OAAO;AACvB,UAAM,cAAc,OAAO,GAAG,IAAI,OAAO,MAAM,CAAC,IAAI,OAAO,MAAM,CAAC,KAAK;AACvE,QAAI,aAAa,IAAK;AAAA,EACxB;AAEA,SAAQ,cAAc,aAAc,MAAM,YAAY;AACxD;AAEA,IAAM,kBAAkB;AACxB,IAAM,UAAoC,CAAC,KAAK,IAAI,GAAG;AAEvD,SAAS,YACP,QACA,MACiB;AACjB,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK,GAAG;AACzC,UAAM,IAAI,OAAO,CAAC,GAAG,IAAI,OAAO,IAAI,CAAC,GAAG,IAAI,OAAO,IAAI,CAAC;AACxD,UAAM,cAAc,IAAI,IAAI,KAAK;AAEjC,QAAI,aAAa,iBAAiB;AAEhC,aAAO,IAAI,CAAC,IAAI;AAAA,IAClB,OAAO;AAEL,YAAM,WAAW,IAAI,aAAa;AAClC,aAAO,CAAC,IAAI,QAAQ,CAAC;AACrB,aAAO,IAAI,CAAC,IAAI,QAAQ,CAAC;AACzB,aAAO,IAAI,CAAC,IAAI,QAAQ,CAAC;AACzB,aAAO,IAAI,CAAC,IAAI,KAAK,MAAM,WAAW,GAAG;AAAA,IAC3C;AAAA,EACF;AAEA,SAAO,MAAM,OAAO,KAAK,OAAO,MAAM,GAAG;AAAA,IACvC,KAAK,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,QAAQ,UAAU,EAAE;AAAA,EAC7D,CAAC,EACE,IAAI,EACJ,SAAS;AACd;AAEA,SAAS,UACP,QACA,MACA,SACiB;AACjB,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK,GAAG;AAEzC,WAAO,IAAI,CAAC,IAAI,KAAK,MAAM,OAAO,IAAI,CAAC,IAAI,OAAO;AAAA,EACpD;AAEA,SAAO,MAAM,OAAO,KAAK,OAAO,MAAM,GAAG;AAAA,IACvC,KAAK,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,QAAQ,UAAU,EAAE;AAAA,EAC7D,CAAC,EACE,IAAI,EACJ,SAAS;AACd;","names":[]}