mesurer-solid 0.1.0-beta.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/AGENT_INTEGRATION.md +189 -0
- package/LICENSE +21 -0
- package/README.md +233 -0
- package/THIRD_PARTY_LICENSES.md +29 -0
- package/dist/agent.d.ts +113 -0
- package/dist/context-contract-parity.d.ts +1 -0
- package/dist/context-plugin.d.ts +27 -0
- package/dist/context.d.ts +359 -0
- package/dist/core.d.ts +147 -0
- package/dist/core.js +226 -0
- package/dist/host-layer.d.ts +24 -0
- package/dist/index.d.ts +210 -0
- package/dist/index.js +10195 -0
- package/dist/inject-script.d.ts +1 -0
- package/dist/inject-script.js +1227 -0
- package/dist/inject.d.ts +12 -0
- package/dist/inject.js +9983 -0
- package/package.json +62 -0
- package/scripts/install-skill.mjs +31 -0
- package/skills/mesurer-ui/SKILL.md +111 -0
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mesurer-solid",
|
|
3
|
+
"version": "0.1.0-beta.11",
|
|
4
|
+
"description": "Framework-agnostic UI measurement and inspection tools for browser apps and coding agents.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"bin": {
|
|
11
|
+
"mesurer-skill": "./scripts/install-skill.mjs"
|
|
12
|
+
},
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./core": {
|
|
19
|
+
"types": "./dist/core.d.ts",
|
|
20
|
+
"import": "./dist/core.js"
|
|
21
|
+
},
|
|
22
|
+
"./inject": {
|
|
23
|
+
"types": "./dist/inject.d.ts",
|
|
24
|
+
"import": "./dist/inject.js"
|
|
25
|
+
},
|
|
26
|
+
"./inject-script": "./dist/inject-script.js",
|
|
27
|
+
"./package.json": "./package.json"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"skills",
|
|
32
|
+
"scripts/install-skill.mjs",
|
|
33
|
+
"README.md",
|
|
34
|
+
"AGENT_INTEGRATION.md",
|
|
35
|
+
"LICENSE",
|
|
36
|
+
"THIRD_PARTY_LICENSES.md"
|
|
37
|
+
],
|
|
38
|
+
"keywords": [
|
|
39
|
+
"measurement",
|
|
40
|
+
"devtools",
|
|
41
|
+
"agent",
|
|
42
|
+
"playwright",
|
|
43
|
+
"solid",
|
|
44
|
+
"react",
|
|
45
|
+
"vue",
|
|
46
|
+
"svelte",
|
|
47
|
+
"electron"
|
|
48
|
+
],
|
|
49
|
+
"repository": {
|
|
50
|
+
"type": "git",
|
|
51
|
+
"url": "https://github.com/jhomra21/mesurer-solid.git",
|
|
52
|
+
"directory": "packages/mesurer"
|
|
53
|
+
},
|
|
54
|
+
"bugs": {
|
|
55
|
+
"url": "https://github.com/jhomra21/mesurer-solid/issues"
|
|
56
|
+
},
|
|
57
|
+
"homepage": "https://github.com/jhomra21/mesurer-solid#readme",
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"access": "public",
|
|
60
|
+
"registry": "https://registry.npmjs.org/"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { cpSync, existsSync, mkdirSync, rmSync } from "node:fs";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
|
|
5
|
+
const args = process.argv.slice(2);
|
|
6
|
+
const command = args.find((arg) => !arg.startsWith("-")) ?? "install";
|
|
7
|
+
const force = args.includes("--force");
|
|
8
|
+
|
|
9
|
+
if (command !== "install") {
|
|
10
|
+
console.error("Usage: mesurer-skill install [--force]");
|
|
11
|
+
process.exitCode = 1;
|
|
12
|
+
} else {
|
|
13
|
+
const source = new URL("../skills/mesurer-ui/", import.meta.url);
|
|
14
|
+
const injector = new URL("../dist/inject-script.js", import.meta.url);
|
|
15
|
+
const destination = resolve(process.cwd(), ".agents/skills/mesurer-ui");
|
|
16
|
+
const assets = resolve(destination, "assets");
|
|
17
|
+
if (existsSync(destination) && !force) {
|
|
18
|
+
console.error(`Mesurer skill already exists at ${destination}. Use --force to replace it.`);
|
|
19
|
+
process.exitCode = 1;
|
|
20
|
+
} else if (!existsSync(injector)) {
|
|
21
|
+
console.error("Mesurer inject-script asset is missing. Reinstall @jhomra21/mesurer-solid and retry.");
|
|
22
|
+
process.exitCode = 1;
|
|
23
|
+
} else {
|
|
24
|
+
if (force) rmSync(destination, { recursive: true, force: true });
|
|
25
|
+
mkdirSync(resolve(destination, ".."), { recursive: true });
|
|
26
|
+
cpSync(source, destination, { recursive: true });
|
|
27
|
+
mkdirSync(assets, { recursive: true });
|
|
28
|
+
cpSync(injector, resolve(assets, "inject-script.js"));
|
|
29
|
+
console.log(`Installed Mesurer Agent Skill and injector at ${destination}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mesurer-ui
|
|
3
|
+
description: Use Mesurer when implementing, reviewing, or fixing frontend UI in a browser. Load for visual alignment, spacing, sizing, layout, CSS, responsive work, design/Figma implementation, screenshots, pixel discrepancies, or human Mesurer annotations. Revalidate visual changes with Mesurer before claiming completion when Mesurer is available.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Mesurer UI workflow
|
|
7
|
+
|
|
8
|
+
Mesurer is a shared visual inspection and feedback layer between the person reviewing a UI and the agent editing it.
|
|
9
|
+
|
|
10
|
+
## Discover Mesurer
|
|
11
|
+
|
|
12
|
+
When you have a browser/evaluation channel, wait for an existing Mesurer instance before inspecting its capabilities:
|
|
13
|
+
|
|
14
|
+
```js
|
|
15
|
+
if (window.__MESURER__) {
|
|
16
|
+
await window.__MESURER__.ready()
|
|
17
|
+
window.__MESURER__.capabilities()
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
If Mesurer is absent, use the browser JavaScript-evaluation primitive the harness already owns. Do not add Mesurer to application source, create another browser, or change the app build just to inspect the page.
|
|
22
|
+
|
|
23
|
+
The installed skill is self-contained: `assets/inject-script.js` beside this file is the packaged classic injector. Read that file and evaluate its contents in the page. In the Mesurer repository itself, the equivalent development artifact is `packages/mesurer/dist/inject-script.js`. If `mesurer-solid` is already installed in the project, its `/inject-script` export is the same distribution path.
|
|
24
|
+
|
|
25
|
+
After injection:
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
await window.__MESURER__.ready()
|
|
29
|
+
window.__MESURER__.capabilities()
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Human feedback comes first
|
|
33
|
+
|
|
34
|
+
Before editing UI code, read any Mesurer annotations and the relevant scoped context:
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
await window.__MESURER__.annotations()
|
|
38
|
+
await window.__MESURER__.context({ annotation: annotationId })
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Treat the user's annotation note as intent. Treat selectors, geometry, guides, measurements, distances, typography, and screenshots as evidence that helps implement that intent. Do not override a user's stated intent merely because a numeric measurement exists.
|
|
42
|
+
|
|
43
|
+
For the current unsaved selection, use:
|
|
44
|
+
|
|
45
|
+
```js
|
|
46
|
+
await window.__MESURER__.context({ scope: "selection" })
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
A selection may be one or more elements or a dragged visual region. Region annotations are useful for whitespace, alignment, or other feedback where no single DOM element is the right target.
|
|
50
|
+
|
|
51
|
+
For the whole meaningful workspace, use:
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
await window.__MESURER__.context()
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Implement, render, revalidate
|
|
58
|
+
|
|
59
|
+
For a requested visual change:
|
|
60
|
+
|
|
61
|
+
1. Capture the relevant annotation/selection context before editing.
|
|
62
|
+
2. Make the smallest source change that addresses the visual intent.
|
|
63
|
+
3. Let the normal dev server/HMR update the page.
|
|
64
|
+
4. Wait for the rendered UI to settle with `await window.__MESURER__.stable()`.
|
|
65
|
+
5. Re-read the affected annotation with `await window.__MESURER__.review(annotationId)`.
|
|
66
|
+
6. Inspect measurable before/current changes and any explicit missing evidence. If a gap, alignment, width, height, guide relationship, or expected target is still wrong, iterate.
|
|
67
|
+
7. If the harness supports screenshots, inspect the current visual evidence as well.
|
|
68
|
+
8. For visual tasks, do not declare completion merely because typecheck/tests/build pass when Mesurer is available for browser validation.
|
|
69
|
+
|
|
70
|
+
Annotations keep the original live DOM target while it remains connected. After DOM replacement, Mesurer rebinds only when the stored selector and fingerprint resolve conservatively and uniquely. If Mesurer reports a target as stale, do not silently assume another element is the same target; ask for or re-establish the intended target when necessary.
|
|
71
|
+
|
|
72
|
+
## Screenshot evidence
|
|
73
|
+
|
|
74
|
+
Mesurer distinguishes controls from visual evidence. Capture with Mesurer controls hidden but guides, rulers, selected outlines, annotations, measurements, distances, and pixel labels visible:
|
|
75
|
+
|
|
76
|
+
```js
|
|
77
|
+
const plan = await window.__MESURER__.capturePlan({ annotation: annotationId })
|
|
78
|
+
await window.__MESURER__.prepareCapture()
|
|
79
|
+
try {
|
|
80
|
+
// Use the harness/browser's real screenshot primitive.
|
|
81
|
+
// Capture the current viewport and, when plan contains `focus`, that clip.
|
|
82
|
+
} finally {
|
|
83
|
+
await window.__MESURER__.finishCapture()
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Do not use a DOM-to-canvas approximation when the harness can capture the real rendered browser.
|
|
88
|
+
|
|
89
|
+
Use screenshots together with structured Mesurer evidence, not instead of it. Numeric geometry is better for exact discrepancies; images are better for visual judgment and surrounding design context.
|
|
90
|
+
|
|
91
|
+
## Delivery
|
|
92
|
+
|
|
93
|
+
The universal fallback is `await window.__MESURER__.contextText(...)` or the visible **Copy context** action.
|
|
94
|
+
|
|
95
|
+
For direct standardized agent delivery, use the ACP session already owned by the client/harness. Mesurer context maps to ACP as one text content block plus optional image content blocks. Do not invent an OpenCode-, Pi-, Cursor-, Codex-, or other harness-specific Mesurer protocol.
|
|
96
|
+
|
|
97
|
+
## Useful low-level inspection
|
|
98
|
+
|
|
99
|
+
The existing browser API remains available when more detail is needed:
|
|
100
|
+
|
|
101
|
+
```js
|
|
102
|
+
await window.__MESURER__.ready()
|
|
103
|
+
window.__MESURER__.inspect(".selector")
|
|
104
|
+
window.__MESURER__.inspectAll(".selector")
|
|
105
|
+
window.__MESURER__.distance(".a", ".b")
|
|
106
|
+
window.__MESURER__.viewport()
|
|
107
|
+
await window.__MESURER__.state()
|
|
108
|
+
await window.__MESURER__.stable()
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Use these primitives to answer a concrete visual question; prefer scoped `context()`/`review()` for normal human-in-the-loop UI work.
|