@glissade/scene 0.60.0-pre.0 → 0.60.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/describe.d.ts +10 -2
- package/dist/describe.js +36 -1
- package/dist/diagnostics.d.ts +14 -0
- package/dist/diagnostics.js +27 -17
- package/package.json +2 -2
package/dist/describe.d.ts
CHANGED
|
@@ -153,8 +153,16 @@ interface DescribedHelper {
|
|
|
153
153
|
interface SurfaceEntry {
|
|
154
154
|
/** The export name — also the `window.glissade.<name>` global on the IIFE. */
|
|
155
155
|
name: string;
|
|
156
|
-
/**
|
|
157
|
-
|
|
156
|
+
/**
|
|
157
|
+
* `'value'` = a runtime binding on the bundle (a class / function / object);
|
|
158
|
+
* `'type'` = a TS type-only name that erases at runtime (opaque, referenced by
|
|
159
|
+
* signatures); `'diagnostic'` = a runtime AUTHORING-DIAGNOSTIC function
|
|
160
|
+
* (`critique`/`validateScene`/`resolveAt`/`instanceProps`, 0.60) — a real
|
|
161
|
+
* `window.glissade.<name>` callable that is PERCEPTION/self-check tooling, not
|
|
162
|
+
* scene-building surface. An agent BUILDING a scene filters `kind !== 'diagnostic'`;
|
|
163
|
+
* an agent CRITIQUING a rendered scene filters `kind === 'diagnostic'`.
|
|
164
|
+
*/
|
|
165
|
+
kind: 'value' | 'type' | 'diagnostic';
|
|
158
166
|
/** `true` when it is reachable as `window.glissade.<name>` on the single-file IIFE bundle. */
|
|
159
167
|
iife: boolean;
|
|
160
168
|
/** How to consume it: `'constructor'` needs `new`, `'function'` is a plain call, `'object'` is a value namespace (e.g. `easings`), `'type'` is type-only. */
|
package/dist/describe.js
CHANGED
|
@@ -23,7 +23,7 @@ import { easings, listValueTypes } from "@glissade/core";
|
|
|
23
23
|
* never pulled onto the base embed path — a scene that never calls `describe()`
|
|
24
24
|
* pays zero bytes for it.
|
|
25
25
|
*/
|
|
26
|
-
const RAW_VERSION = "0.60.0
|
|
26
|
+
const RAW_VERSION = "0.60.0";
|
|
27
27
|
const PACKAGE_VERSION = RAW_VERSION.includes("GLISSADE_".concat("VERSION")) ? "0.0.0-dev" : RAW_VERSION;
|
|
28
28
|
/**
|
|
29
29
|
* Parse the documented positional-arg count from a helper `usage` string — the
|
|
@@ -182,6 +182,34 @@ const SURFACE_EXTRA = [
|
|
|
182
182
|
/** Value exports that are runtime OBJECTS (not callable): the easing registry. */
|
|
183
183
|
const SURFACE_VALUE_OBJECTS = ["easings"];
|
|
184
184
|
/**
|
|
185
|
+
* The 0.60 machine-readable AUTHORING-DIAGNOSTIC functions on `window.glissade`
|
|
186
|
+
* (the `@glissade/scene/diagnostics` subpath, IIFE-re-exported off the base embed):
|
|
187
|
+
* `critique` (rendered geometry), `validateScene` (static structure), `resolveAt`
|
|
188
|
+
* (the truthful read primitive), `instanceProps` (instance-bound state). Marked
|
|
189
|
+
* `kind: 'diagnostic'` so a consumer can PARTITION the surface — build-a-scene
|
|
190
|
+
* tooling filters them OUT, render-critique/perception tooling filters them IN —
|
|
191
|
+
* instead of them being invisible (previously exempt-internal, discoverable only by
|
|
192
|
+
* reading the bundle). `arity` = the documented required positional-arg count.
|
|
193
|
+
*/
|
|
194
|
+
const SURFACE_DIAGNOSTICS = [
|
|
195
|
+
{
|
|
196
|
+
name: "critique",
|
|
197
|
+
arity: 2
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
name: "validateScene",
|
|
201
|
+
arity: 2
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
name: "resolveAt",
|
|
205
|
+
arity: 3
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
name: "instanceProps",
|
|
209
|
+
arity: 1
|
|
210
|
+
}
|
|
211
|
+
];
|
|
212
|
+
/**
|
|
185
213
|
* The opaque, type-ONLY names the API surface references (they erase at runtime —
|
|
186
214
|
* `window.glissade.Paint` is `undefined`). `gs types --global` emits a best-effort
|
|
187
215
|
* alias per name; `gs describe --lint` guards they stay type-only (a type surfaced
|
|
@@ -235,6 +263,13 @@ function buildSurface() {
|
|
|
235
263
|
iife: true,
|
|
236
264
|
form: "object"
|
|
237
265
|
});
|
|
266
|
+
for (const d of SURFACE_DIAGNOSTICS) out.push({
|
|
267
|
+
name: d.name,
|
|
268
|
+
kind: "diagnostic",
|
|
269
|
+
iife: true,
|
|
270
|
+
form: "function",
|
|
271
|
+
arity: d.arity
|
|
272
|
+
});
|
|
238
273
|
for (const name of SURFACE_TYPE_ONLY) out.push({
|
|
239
274
|
name,
|
|
240
275
|
kind: "type",
|
package/dist/diagnostics.d.ts
CHANGED
|
@@ -282,6 +282,20 @@ interface CritiqueOptions {
|
|
|
282
282
|
* override for tooling; a fixed INTEGER-frame grid is the determinism contract.
|
|
283
283
|
*/
|
|
284
284
|
fps?: number;
|
|
285
|
+
/**
|
|
286
|
+
* Author-declared INTENTIONALLY off-stage node ids — the OFF_CANVAS opt-out.
|
|
287
|
+
* A node is exempt from OFF_CANVAS iff its id is in this list OR ANY of its
|
|
288
|
+
* ancestors' ids is (SUBTREE match): list the parked GROUP id
|
|
289
|
+
* (`'sd1-drawer'`) and its whole subtree — current children AND any it later
|
|
290
|
+
* gains — is suppressed, while sibling groups stay fully checked. This lets an
|
|
291
|
+
* author silence the true-positive-but-intentional off-stage art (wing-parked
|
|
292
|
+
* drawers, hidden placeholder cards) without muting OFF_CANVAS wholesale. A
|
|
293
|
+
* PURE emission filter — determinism-neutral (it never changes the sampled
|
|
294
|
+
* geometry, only which off-frame nodes are reported). Same param-seam shape as
|
|
295
|
+
* a future `safeAreas`; a per-node `offstage:true` marker is a planned
|
|
296
|
+
* fast-follow, not this mechanism.
|
|
297
|
+
*/
|
|
298
|
+
offstage?: readonly string[];
|
|
285
299
|
}
|
|
286
300
|
interface CritiqueResult {
|
|
287
301
|
schemaVersion: typeof DIAGNOSTIC_SCHEMA_VERSION;
|
package/dist/diagnostics.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { I as isEstimatingMeasurer, J as collapseReplacer, P as estimatingMeasurer, W as createDisplayListBuilder, Y as IDENTITY, et as multiply, r as Group, s as Text } from "./nodes.js";
|
|
1
|
+
import { I as isEstimatingMeasurer, J as collapseReplacer, P as estimatingMeasurer, R as quantize, W as createDisplayListBuilder, Y as IDENTITY, et as multiply, r as Group, s as Text } from "./nodes.js";
|
|
2
2
|
import { a as evaluate, r as bindScene } from "./scene.js";
|
|
3
3
|
import { emitWithIds } from "./identity.js";
|
|
4
4
|
import { buildFontRegistry, compileTimeline, evaluateAt, parseCmap, parseColor, untracked, validateFonts } from "@glissade/core";
|
|
@@ -737,8 +737,10 @@ function critique(scene, timeline, opts = {}) {
|
|
|
737
737
|
}
|
|
738
738
|
}
|
|
739
739
|
const rendered = [];
|
|
740
|
+
const offstageSet = new Set(opts.offstage ?? []);
|
|
741
|
+
const isOffstage = (id) => offstageSet.size > 0 && (offstageSet.has(id) || hasFlaggedAncestor(scene, id, offstageSet));
|
|
740
742
|
const offCanvasIds = /* @__PURE__ */ new Set();
|
|
741
|
-
for (const [id, a] of agg) if (a.onStage > 0 && a.offCanvas === a.onStage) offCanvasIds.add(id);
|
|
743
|
+
for (const [id, a] of agg) if (a.onStage > 0 && a.offCanvas === a.onStage && !isOffstage(id)) offCanvasIds.add(id);
|
|
742
744
|
const reportedOffCanvas = /* @__PURE__ */ new Set();
|
|
743
745
|
for (const id of offCanvasIds) {
|
|
744
746
|
if (hasFlaggedAncestor(scene, id, offCanvasIds)) continue;
|
|
@@ -749,22 +751,29 @@ function critique(scene, timeline, opts = {}) {
|
|
|
749
751
|
for (const [id, a] of agg) {
|
|
750
752
|
if (a.lastTexts.length === 0) continue;
|
|
751
753
|
const node = scene.nodes.get(id);
|
|
752
|
-
if (!node
|
|
754
|
+
if (!(node instanceof Text)) continue;
|
|
753
755
|
const width = numberAt(scene, `${id}/width`, a.lastTextFrameT);
|
|
754
|
-
if (width
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
756
|
+
if (width !== void 0 && width > 0) {
|
|
757
|
+
let widest = 0;
|
|
758
|
+
for (const run of a.lastTexts) {
|
|
759
|
+
let mw = 0;
|
|
760
|
+
try {
|
|
761
|
+
mw = measurer.measureText(run.text, run.font).width;
|
|
762
|
+
} catch {
|
|
763
|
+
mw = 0;
|
|
764
|
+
}
|
|
765
|
+
if (mw > widest) widest = mw;
|
|
762
766
|
}
|
|
763
|
-
|
|
767
|
+
const over = widest - width;
|
|
768
|
+
if (over > .5) rendered.push(textOverflowDiagnostic(id, "width", widest, width, over, estimating));
|
|
769
|
+
}
|
|
770
|
+
const boxH = node.box?.h;
|
|
771
|
+
if (boxH !== void 0 && boxH > 0) {
|
|
772
|
+
const fontSize = a.lastTexts[0].font.size;
|
|
773
|
+
const blockH = quantize(fontSize * node.lineHeight) * a.lastTexts.length;
|
|
774
|
+
const overH = blockH - boxH;
|
|
775
|
+
if (overH > .5) rendered.push(textOverflowDiagnostic(id, "height", blockH, boxH, overH, estimating));
|
|
764
776
|
}
|
|
765
|
-
const over = widest - width;
|
|
766
|
-
if (over <= .5) continue;
|
|
767
|
-
rendered.push(textOverflowDiagnostic(id, widest, width, over, estimating));
|
|
768
777
|
}
|
|
769
778
|
for (const [id, a] of agg) {
|
|
770
779
|
if (a.onStage === 0 || a.occluded !== a.onStage) continue;
|
|
@@ -824,8 +833,8 @@ function offCanvasDiagnostic(scene, id, a, w, h) {
|
|
|
824
833
|
}
|
|
825
834
|
};
|
|
826
835
|
}
|
|
827
|
-
function textOverflowDiagnostic(id, measured, threshold, over, estimating) {
|
|
828
|
-
const base = `text of node '${id}' overflows its box by ${round(over)}px (needs ${round(measured)}px, box width ${round(threshold)}px). Reduce fontSize, widen width, or wrap it with fitText({ maxW: ${round(threshold)} }).`;
|
|
836
|
+
function textOverflowDiagnostic(id, dimension, measured, threshold, over, estimating) {
|
|
837
|
+
const base = dimension === "width" ? `text of node '${id}' overflows its box WIDTH by ${round(over)}px (needs ${round(measured)}px, box width ${round(threshold)}px). Reduce fontSize, widen width, or wrap it with fitText({ maxW: ${round(threshold)} }).` : `text of node '${id}' overflows its box HEIGHT by ${round(over)}px (wrapped block ${round(measured)}px tall, box height ${round(threshold)}px). Reduce fontSize, increase the box height, or shorten the text.`;
|
|
829
838
|
return {
|
|
830
839
|
schemaVersion: 1,
|
|
831
840
|
code: "TEXT_OVERFLOW",
|
|
@@ -834,6 +843,7 @@ function textOverflowDiagnostic(id, measured, threshold, over, estimating) {
|
|
|
834
843
|
node: id,
|
|
835
844
|
message: estimating ? `${base} (metrics ESTIMATED — no real text measurer injected; verify with the real backend measurer.)` : base,
|
|
836
845
|
detail: {
|
|
846
|
+
dimension,
|
|
837
847
|
measured: round(measured),
|
|
838
848
|
threshold: round(threshold),
|
|
839
849
|
overflowPx: round(over),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glissade/scene",
|
|
3
|
-
"version": "0.60.0
|
|
3
|
+
"version": "0.60.0",
|
|
4
4
|
"description": "glissade scene graph: nodes, transforms, DisplayList emission. Renderer-agnostic; zero DOM/Node dependencies.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"engines": {
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
],
|
|
82
82
|
"dependencies": {
|
|
83
83
|
"yoga-layout": "^3.2.1",
|
|
84
|
-
"@glissade/core": "0.60.0
|
|
84
|
+
"@glissade/core": "0.60.0"
|
|
85
85
|
},
|
|
86
86
|
"repository": {
|
|
87
87
|
"type": "git",
|