@ammduncan/easel 0.2.12 → 0.2.13
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/CHANGELOG.md +5 -0
- package/dist/client/viewer.js +26 -4
- package/dist/mcp.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to easel. This project adheres to [Semantic Versioning](https://semver.org/).
|
|
4
4
|
|
|
5
|
+
## 0.2.13 — 2026-05-23
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **`kind: "mockup"` and `kind: "app"` switch the iframe into app-fidelity mode.** The wrapper skips its presentation defaults (Inter body font, design-token CSS, semantic chips, body bg/color, prose width constraints) and only keeps the box-sizing reset and the html-to-image bridge. Agent paints everything. Makes the existing "App/UI recreations are always locked-mode" rule structural — for a true mockup, opt in via `kind` and the wrapper stops fighting you instead of relying on the agent remembering to override every default. Presentation pushes (explanations, comparisons, status reports) keep the existing wrapper as before.
|
|
9
|
+
|
|
5
10
|
## 0.2.12 — 2026-05-23
|
|
6
11
|
|
|
7
12
|
### Docs
|
package/dist/client/viewer.js
CHANGED
|
@@ -585,7 +585,7 @@
|
|
|
585
585
|
iframe.setAttribute("scrolling", "no");
|
|
586
586
|
iframe.setAttribute("title", push.title || "push " + push.index);
|
|
587
587
|
iframe.dataset.pushId = push.id;
|
|
588
|
-
iframe.srcdoc = wrapPushedHtml(push.html, currentTheme(), push.id);
|
|
588
|
+
iframe.srcdoc = wrapPushedHtml(push.html, currentTheme(), push.id, push.kind);
|
|
589
589
|
iframe.addEventListener("load", () => {
|
|
590
590
|
iframes.add(iframe);
|
|
591
591
|
// Primary path: the iframe self-measures and posts back size via
|
|
@@ -607,7 +607,7 @@
|
|
|
607
607
|
- write plain HTML (<h1>, <h2>, <p>, etc.) — gets styled for free, OR
|
|
608
608
|
- write their own <style> and override anything.
|
|
609
609
|
============================================================ */
|
|
610
|
-
function wrapPushedHtml(html, theme, pushId) {
|
|
610
|
+
function wrapPushedHtml(html, theme, pushId, kind) {
|
|
611
611
|
// Authors sometimes wrap payloads in <![CDATA[ ... ]]> (treating html
|
|
612
612
|
// like CDATA-in-XML). Strip the XML-ism before doing anything else —
|
|
613
613
|
// otherwise the iframe renders the CDATA tags as visible text.
|
|
@@ -620,7 +620,8 @@
|
|
|
620
620
|
if (lower.startsWith("<!doctype") || lower.startsWith("<html")) {
|
|
621
621
|
return injectBridge(cleaned, theme, preset, pushId);
|
|
622
622
|
}
|
|
623
|
-
|
|
623
|
+
const isAppFidelity = kind === "mockup" || kind === "app";
|
|
624
|
+
return buildDefaultWrapper(cleaned, theme, preset, pushId, isAppFidelity);
|
|
624
625
|
}
|
|
625
626
|
|
|
626
627
|
function selfMeasureScript(pushId) {
|
|
@@ -631,8 +632,29 @@
|
|
|
631
632
|
);
|
|
632
633
|
}
|
|
633
634
|
|
|
634
|
-
function buildDefaultWrapper(body, theme, preset, pushId) {
|
|
635
|
+
function buildDefaultWrapper(body, theme, preset, pushId, appFidelity) {
|
|
635
636
|
const density = currentDensity();
|
|
637
|
+
// app-fidelity mode: skip presentation defaults (presets, semantic chips,
|
|
638
|
+
// body font/bg/color, prose constraints). Agent paints everything. Only
|
|
639
|
+
// keeps box-sizing reset + the html-to-image bridge script.
|
|
640
|
+
if (appFidelity) {
|
|
641
|
+
return `<!DOCTYPE html>
|
|
642
|
+
<html data-theme="${theme}" data-preset="${preset}" data-density="${density}" data-app-fidelity="true">
|
|
643
|
+
<head>
|
|
644
|
+
<meta charset="utf-8" />
|
|
645
|
+
<base target="_blank" />
|
|
646
|
+
<script src="https://cdn.jsdelivr.net/npm/html-to-image@1.11.13/dist/html-to-image.js"></script>
|
|
647
|
+
<style>
|
|
648
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
649
|
+
html, body { margin: 0; padding: 0; }
|
|
650
|
+
</style>
|
|
651
|
+
</head>
|
|
652
|
+
<body>
|
|
653
|
+
${body}
|
|
654
|
+
<script>${selfMeasureScript(pushId)}</script>
|
|
655
|
+
</body>
|
|
656
|
+
</html>`;
|
|
657
|
+
}
|
|
636
658
|
return `<!DOCTYPE html>
|
|
637
659
|
<html data-theme="${theme}" data-preset="${preset}" data-density="${density}">
|
|
638
660
|
<head>
|
package/dist/mcp.js
CHANGED
|
@@ -82,7 +82,7 @@ const inputSchema = {
|
|
|
82
82
|
},
|
|
83
83
|
kind: {
|
|
84
84
|
type: "string",
|
|
85
|
-
description: "Freeform tag: mockup, diff, explanation, comparison, diagram, status, progress, etc.",
|
|
85
|
+
description: "Freeform tag: mockup, app, diff, explanation, comparison, diagram, status, progress, etc. SPECIAL: 'mockup' and 'app' switch the iframe into APP-FIDELITY mode — the wrapper skips its presentation defaults (Inter body font, design-token CSS, semantic chips, prose width constraints, body bg/color). Only the box-sizing reset and the html-to-image bridge stay. Use this when the push is a recreation of real UI (app screen, component instance, embedded preview) and you want full control over every pixel without the host theme leaking in. For presentation content (explanations, comparisons, status reports), omit kind or use a non-fidelity value.",
|
|
86
86
|
},
|
|
87
87
|
},
|
|
88
88
|
required: ["html"],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ammduncan/easel",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.13",
|
|
4
4
|
"description": "A live browser tab for every Claude Code (and MCP) session. The push MCP tool appends HTML cards to a scrolling feed you keep open in split-screen.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|