packages/core/src/lib/style/diagnostics.ts
This is the source snapshot used to build these API details. View this revision on GitHub.
1 import type { normalizeEdges } from './normalize.js';
2 import type { resolveLength } from './resolve-length.js';
3 import type { Constraints } from '../layout/types.js';
4
5 /**
6 * Component and source context attached to a layout diagnostic.
7 *
8 * @see {@link Constraints}
9 * @see {@link LayoutDiagnosticInput}
10 * @see {@link normalizeEdges}
11 * @see {@link resolveLength}
12 */
13 export interface LayoutDiagnosticContext {
14 /**
15 * Component identity or diagnostic name associated with this value. See
16 * {@link LayoutDiagnosticContext}.
17 */
18 component?: string;
19 /**
20 * Name of the layout algorithm producing this diagnostic or resolution. See
21 * {@link LayoutDiagnosticContext}.
22 */
23 algorithm?: string;
24 /** Sizing limits and available dimensions for this operation. See {@link Constraints}. */
25 constraints?: Readonly<Constraints>;
26 }
27
28 /**
29 * Validation-failure details used to construct a layout diagnostic.
30 *
31 * @see {@link LayoutDiagnosticContext}
32 * @see {@link layoutDiagnostic}
33 */
34 export interface LayoutDiagnosticInput extends LayoutDiagnosticContext {
35 /** Name of the affected input property. See {@link LayoutDiagnosticInput}. */
36 property: string;
37 /** Value associated with this sample, input, or result. See {@link LayoutDiagnosticInput}. */
38 value: unknown;
39 /**
40 * Reason the operation could not produce its ordinary result. See {@link LayoutDiagnosticInput}
41 * .
42 */
43 reason: string;
44 }
45
46 /**
47 * A layout validation error carrying the affected property and component context.
48 *
49 * @see {@link layoutDiagnostic}
50 */
51 export class LayoutDiagnostic extends Error {
52 /**
53 * Component identity or diagnostic name associated with this value. See {@link LayoutDiagnostic}
54 * .
55 */
56 readonly component: string;
57 /** Name of the affected input property. See {@link LayoutDiagnostic}. */
58 readonly property: string;
59 /** The original value that failed validation. See {@link LayoutDiagnostic}. */
60 readonly suppliedValue: unknown;
61 /**
62 * Name of the layout algorithm producing this diagnostic or resolution. See
63 * {@link LayoutDiagnostic}.
64 */
65 readonly algorithm: string;
66 /** Sizing limits and available dimensions for this operation. See {@link Constraints}. */
67 readonly constraints: Readonly<Constraints> | undefined;
68
69 /**
70 * Creates a layout error containing the property, supplied value, and diagnostic context. See
71 * {@link LayoutDiagnostic}.
72 * @param input - Diagnostic code, message, property, and layout context. See
73 * {@link LayoutDiagnosticInput} .
74 */
75 constructor(input: LayoutDiagnosticInput) {
76 const component = input.component ?? 'layout';
77 const algorithm = input.algorithm ?? 'value-resolution';
78 const constraints = input.constraints;
79 super(
80 `${component}: property ${input.property} received ${formatValue(input.value)} ` +
81 `during ${algorithm}; constraints ${formatConstraints(constraints)}; ${input.reason}`,
82 );
83 this.name = 'LayoutDiagnostic';
84 this.component = component;
85 this.property = input.property;
86 this.suppliedValue = input.value;
87 this.algorithm = algorithm;
88 this.constraints = constraints;
89 }
90 }
91
92 /**
93 * Creates a structured layout error from a validation failure and its component context.
94 *
95 * @param input - Diagnostic code, message, property, and layout context. See
96 * {@link LayoutDiagnosticInput} .
97 * @returns A structured layout diagnostic. See {@link LayoutDiagnostic}.
98 *
99 * @see {@link LayoutDiagnosticInput}
100 * @see {@link LayoutDiagnostic}
101 */
102 export function layoutDiagnostic(
103 input: LayoutDiagnosticInput,
104 ): LayoutDiagnostic {
105 return new LayoutDiagnostic(input);
106 }
107
108 function formatValue(value: unknown): string {
109 if (typeof value === 'string') return JSON.stringify(value);
110 if (typeof value === 'number') {
111 if (Number.isNaN(value)) return 'NaN';
112 if (value === Number.POSITIVE_INFINITY) return 'Infinity';
113 if (value === Number.NEGATIVE_INFINITY) return '-Infinity';
114 }
115 try {
116 return JSON.stringify(value) ?? String(value);
117 } catch {
118 return String(value);
119 }
120 }
121
122 function formatConstraints(
123 constraints: Readonly<Constraints> | undefined,
124 ): string {
125 if (!constraints) return 'unspecified';
126 return (
127 `{ minWidth: ${formatValue(constraints.minWidth)}, maxWidth: ${formatValue(constraints.maxWidth)}, ` +
128 `minHeight: ${formatValue(constraints.minHeight)}, maxHeight: ${formatValue(constraints.maxHeight)} }`
129 );
130 }
131
Documentation version
Section titled “Documentation version”Documentation built with @pibbl/core 0.0.2, revision 272a94a. ALPHA — NOT FOR PRODUCTION USE.