@phun-ky/speccer 11.2.44 → 11.3.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/README.md +6 -6
- package/dist/speccer.d.ts +445 -37
- package/dist/speccer.esm.js +2 -2
- package/dist/speccer.js +2 -2
- package/package.json +11 -4
package/README.md
CHANGED
|
@@ -54,8 +54,8 @@ webpage. If you need to draw attention to elements, **SPECCER** is your tool!
|
|
|
54
54
|
- [Pin programmatically](#pin-programmatically)
|
|
55
55
|
- [Element typography](#element-typography)
|
|
56
56
|
- [Syntax highlighting for typography](#syntax-highlighting-for-typography)
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
- [Grid spacing](#grid-spacing)
|
|
58
|
+
- [Mark elements](#mark-elements)
|
|
59
59
|
- [A11y notation](#a11y-notation)
|
|
60
60
|
- [Tab stops](#tab-stops)
|
|
61
61
|
- [Landmarks and regions](#landmarks-and-regions)
|
|
@@ -78,7 +78,7 @@ webpage. If you need to draw attention to elements, **SPECCER** is your tool!
|
|
|
78
78
|
npm i --save @phun-ky/speccer
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
[See a live demo](https://codepen.io/phun-ky/
|
|
81
|
+
[See a live demo](https://codepen.io/phun-ky/full/OJejexN).
|
|
82
82
|
|
|
83
83
|
## Usage
|
|
84
84
|
|
|
@@ -679,7 +679,7 @@ Here is an example with these colors and overrides:
|
|
|
679
679
|
|
|
680
680
|

|
|
681
681
|
|
|
682
|
-
|
|
682
|
+
## Grid spacing
|
|
683
683
|
|
|
684
684
|

|
|
685
685
|
|
|
@@ -700,7 +700,7 @@ In your component examples, use the following attribute on your grid container.
|
|
|
700
700
|
|
|
701
701
|

|
|
702
702
|
|
|
703
|
-
|
|
703
|
+
## Mark elements
|
|
704
704
|
|
|
705
705
|

|
|
706
706
|
|
|
@@ -840,7 +840,7 @@ CSS overrides :)
|
|
|
840
840
|
## API
|
|
841
841
|
|
|
842
842
|
Full API documentation is available
|
|
843
|
-
[here](https://github.com/phun-ky/speccer/blob/main/api/
|
|
843
|
+
[here](https://github.com/phun-ky/speccer/blob/main/docs/api/index.md).
|
|
844
844
|
|
|
845
845
|
## Development
|
|
846
846
|
|
package/dist/speccer.d.ts
CHANGED
|
@@ -1,76 +1,301 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extends the global Window interface to add custom properties.
|
|
3
|
+
*/
|
|
4
|
+
declare global {
|
|
5
|
+
interface Window {
|
|
6
|
+
/**
|
|
7
|
+
* Represents the DrawSVGCurlyBracket class for drawing curly brackets.
|
|
8
|
+
*/
|
|
9
|
+
DrawSVGCurlyBracket: any;
|
|
10
|
+
/**
|
|
11
|
+
* Represents the DrawCircle class for drawing circles.
|
|
12
|
+
*/
|
|
13
|
+
DrawCircle: any;
|
|
14
|
+
/**
|
|
15
|
+
* Represents the DrawSVGLine class for drawing lines.
|
|
16
|
+
*/
|
|
17
|
+
DrawSVGLine: any;
|
|
18
|
+
/**
|
|
19
|
+
* Represents the speccer object for additional functionality.
|
|
20
|
+
*/
|
|
21
|
+
speccer: any;
|
|
22
|
+
/**
|
|
23
|
+
* Represents the custom literals to be used.
|
|
24
|
+
* 
|
|
25
|
+
* @example
|
|
26
|
+
* ```js
|
|
27
|
+
* window.SPECCER_LITERALS = [あ,い,う,え,お,か,き,く,け,こ,さ,し,す,せ,そ,た,ち,つ,て,と,な,に,ぬ,ね,の,は,ひ,ふ,へ,ほ,ま,み,む,め,も,や,ゆ,よ,ら,り,る,れ,ろ,わ,を];
|
|
28
|
+
* speccer();
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
SPECCER_LITERALS: string[];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=global.d.ts.map
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Initializes the accessibility elements on the document.
|
|
38
|
+
*
|
|
39
|
+
* This feature will annotate or highlight accessibility areas like landmarks and region. It can also display tab stops/sequence and any keyboard shortcuts assigned
|
|
40
|
+
*
|
|
41
|
+
* 
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
*
|
|
45
|
+
* Use the following code, either for html or js:
|
|
46
|
+
*
|
|
47
|
+
* ```html
|
|
48
|
+
* <div
|
|
49
|
+
* data-speccer="a11y [shortcuts|tabstops|landmark|headings|autocomplete]"
|
|
50
|
+
* class="…"
|
|
51
|
+
* >
|
|
52
|
+
* …
|
|
53
|
+
* </div>
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* ```ts
|
|
57
|
+
* const targetElement = document.getElementById('target');
|
|
58
|
+
* a11y(targetElement);
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
*
|
|
62
|
+
*/
|
|
63
|
+
declare const a11y: () => void;
|
|
64
|
+
|
|
1
65
|
type SpeccerFunctionType = () => void;
|
|
2
66
|
type SpeccerFeatureType = 'pin' | 'grid' | 'mark' | 'typography' | 'measure' | 'spacing';
|
|
3
67
|
type SpeccerPositionType = 'top' | 'left' | 'right' | 'bottom';
|
|
68
|
+
/**
|
|
69
|
+
* Configuration object that tells Speccer **what** to render and **how** to render it.
|
|
70
|
+
*
|
|
71
|
+
* ### Feature flags
|
|
72
|
+
* Only one top-level {@link SpeccerOptionsInterface.type | type} is active at a time
|
|
73
|
+
* (`"pin" | "grid" | "mark" | "typography" | "measure" | "spacing"`). The corresponding
|
|
74
|
+
* nested section (e.g. `pin`, `grid`, `typography`, `measure`, `spacing`) becomes relevant
|
|
75
|
+
* and other sections are typically omitted.
|
|
76
|
+
*
|
|
77
|
+
* @example Basic "pin" annotation
|
|
78
|
+
* ```ts
|
|
79
|
+
* import type { SpeccerOptionsInterface } from "@phun-ky/speccer";
|
|
80
|
+
*
|
|
81
|
+
* const options: SpeccerOptionsInterface = {
|
|
82
|
+
* slug: "pinBracketSubtle",
|
|
83
|
+
* position: "left",
|
|
84
|
+
* type: "pin",
|
|
85
|
+
* pin: {
|
|
86
|
+
* bracket: true,
|
|
87
|
+
* enclose: false,
|
|
88
|
+
* subtle: true,
|
|
89
|
+
* parent: false,
|
|
90
|
+
* text: false,
|
|
91
|
+
* useSVGLine: true,
|
|
92
|
+
* useCurlyBrackets: false
|
|
93
|
+
* }
|
|
94
|
+
* };
|
|
95
|
+
* ```
|
|
96
|
+
*
|
|
97
|
+
* @example Measure width, slim style
|
|
98
|
+
* ```ts
|
|
99
|
+
* const options: SpeccerOptionsInterface = {
|
|
100
|
+
* slug: "measureWidthSlim",
|
|
101
|
+
* position: "bottom",
|
|
102
|
+
* type: "measure",
|
|
103
|
+
* measure: {
|
|
104
|
+
* slim: true,
|
|
105
|
+
* height: false,
|
|
106
|
+
* width: true
|
|
107
|
+
* }
|
|
108
|
+
* };
|
|
109
|
+
* ```
|
|
110
|
+
*
|
|
111
|
+
* @example Typography with syntax highlighting
|
|
112
|
+
* ```ts
|
|
113
|
+
* const options: SpeccerOptionsInterface = {
|
|
114
|
+
* slug: "codeSample",
|
|
115
|
+
* position: "right",
|
|
116
|
+
* type: "typography",
|
|
117
|
+
* typography: {
|
|
118
|
+
* useSyntaxHighlighting: true
|
|
119
|
+
* }
|
|
120
|
+
* };
|
|
121
|
+
* ```
|
|
122
|
+
*
|
|
123
|
+
* @example Spacing overlays (margin vs. padding vs. both)
|
|
124
|
+
* ```ts
|
|
125
|
+
* const marginOnly: SpeccerOptionsInterface = {
|
|
126
|
+
* slug: "spacingMargin",
|
|
127
|
+
* position: "top",
|
|
128
|
+
* type: "spacing",
|
|
129
|
+
* spacing: {
|
|
130
|
+
* margin: true,
|
|
131
|
+
* padding: false,
|
|
132
|
+
* both: false,
|
|
133
|
+
* bound: false
|
|
134
|
+
* }
|
|
135
|
+
* };
|
|
136
|
+
*
|
|
137
|
+
* const bothWithBounds: SpeccerOptionsInterface = {
|
|
138
|
+
* slug: "spacingBothBound",
|
|
139
|
+
* position: "top",
|
|
140
|
+
* type: "spacing",
|
|
141
|
+
* spacing: {
|
|
142
|
+
* margin: false,
|
|
143
|
+
* padding: false,
|
|
144
|
+
* both: true,
|
|
145
|
+
* bound: true
|
|
146
|
+
* }
|
|
147
|
+
* };
|
|
148
|
+
* ```
|
|
149
|
+
*
|
|
150
|
+
* @example Grid overlays (rows, columns, or both)
|
|
151
|
+
* ```ts
|
|
152
|
+
* const gridBoth: SpeccerOptionsInterface = {
|
|
153
|
+
* slug: "gridBoth",
|
|
154
|
+
* position: "bottom",
|
|
155
|
+
* type: "grid",
|
|
156
|
+
* grid: {
|
|
157
|
+
* toggle: "both", // allowed: "rows" | "columns" | "both"
|
|
158
|
+
* both: true,
|
|
159
|
+
* rows: false,
|
|
160
|
+
* columns: false
|
|
161
|
+
* }
|
|
162
|
+
* };
|
|
163
|
+
*
|
|
164
|
+
* const gridRows: SpeccerOptionsInterface = {
|
|
165
|
+
* slug: "gridRows",
|
|
166
|
+
* position: "bottom",
|
|
167
|
+
* type: "grid",
|
|
168
|
+
* grid: {
|
|
169
|
+
* toggle: "rows",
|
|
170
|
+
* both: false,
|
|
171
|
+
* rows: true,
|
|
172
|
+
* columns: false
|
|
173
|
+
* }
|
|
174
|
+
* };
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
4
177
|
interface SpeccerOptionsInterface {
|
|
178
|
+
/**
|
|
179
|
+
* Machine-readable identifier for this option set.
|
|
180
|
+
*
|
|
181
|
+
* @remarks
|
|
182
|
+
* When produced by {@link getOptions}, this is derived from the input `areaString`
|
|
183
|
+
* using a camel-casing strategy (e.g., `"pin bracket subtle"` → `"pinBracketSubtle"`).
|
|
184
|
+
*/
|
|
5
185
|
slug: string;
|
|
186
|
+
/**
|
|
187
|
+
* Preferred anchor side for rendering or label placement.
|
|
188
|
+
*
|
|
189
|
+
* @remarks
|
|
190
|
+
* Use to hint where visual affordances (e.g., labels, callouts) should appear
|
|
191
|
+
* relative to the annotated element.
|
|
192
|
+
*/
|
|
6
193
|
position: SpeccerPositionType;
|
|
194
|
+
/**
|
|
195
|
+
* Which Speccer feature this option set activates.
|
|
196
|
+
*
|
|
197
|
+
* @remarks
|
|
198
|
+
* This field determines which nested section is relevant (`pin`, `grid`, `mark`,
|
|
199
|
+
* `typography`, `measure`, or `spacing`). Only one feature is active at a time.
|
|
200
|
+
*/
|
|
7
201
|
type: SpeccerFeatureType;
|
|
202
|
+
/**
|
|
203
|
+
* Options for the `"pin"` feature.
|
|
204
|
+
*
|
|
205
|
+
* @remarks
|
|
206
|
+
* Present only when {@link SpeccerOptionsInterface.type | type} is `"pin"`.
|
|
207
|
+
* Each flag toggles a specific pin decoration or behavior.
|
|
208
|
+
*/
|
|
8
209
|
pin?: {
|
|
210
|
+
/** Draw bracket-style markers around the pin. */
|
|
9
211
|
bracket: boolean;
|
|
212
|
+
/** Enclose the pin target (e.g., a boxed/outlined emphasis). */
|
|
10
213
|
enclose: boolean;
|
|
214
|
+
/** Reduce visual weight for a subtler presentation. */
|
|
11
215
|
subtle: boolean;
|
|
216
|
+
/** Indicate that the pin references a parent container/element. */
|
|
12
217
|
parent: boolean;
|
|
218
|
+
/** Render an inline text label along with the pin. */
|
|
13
219
|
text: boolean;
|
|
220
|
+
/** Use an SVG line primitive instead of a DOM line. */
|
|
14
221
|
useSVGLine: boolean;
|
|
222
|
+
/** Use curly brackets for bracketed pins instead of straight brackets. */
|
|
15
223
|
useCurlyBrackets: boolean;
|
|
16
224
|
};
|
|
225
|
+
/**
|
|
226
|
+
* Options for the `"measure"` feature.
|
|
227
|
+
*
|
|
228
|
+
* @remarks
|
|
229
|
+
* Present only when {@link SpeccerOptionsInterface.type | type} is `"measure"`.
|
|
230
|
+
* Use `height` and/or `width` to select the axis to measure; `slim` switches to
|
|
231
|
+
* a compact rendering style for tight layouts.
|
|
232
|
+
*/
|
|
17
233
|
measure?: {
|
|
234
|
+
/** Use a compact (thinner) measurement style. */
|
|
18
235
|
slim: boolean;
|
|
236
|
+
/** Show a vertical measurement (element height). */
|
|
19
237
|
height: boolean;
|
|
238
|
+
/** Show a horizontal measurement (element width). */
|
|
20
239
|
width: boolean;
|
|
21
240
|
};
|
|
241
|
+
/**
|
|
242
|
+
* Options for the `"typography"` feature.
|
|
243
|
+
*
|
|
244
|
+
* @remarks
|
|
245
|
+
* Present only when {@link SpeccerOptionsInterface.type | type} is `"typography"`.
|
|
246
|
+
* Enables code-like styling or syntax coloring when appropriate.
|
|
247
|
+
*/
|
|
22
248
|
typography?: {
|
|
249
|
+
/** Enable syntax highlighting for textual samples. */
|
|
23
250
|
useSyntaxHighlighting: boolean;
|
|
24
251
|
};
|
|
252
|
+
/**
|
|
253
|
+
* Options for the `"spacing"` feature.
|
|
254
|
+
*
|
|
255
|
+
* @remarks
|
|
256
|
+
* Present only when {@link SpeccerOptionsInterface.type | type} is `"spacing"`.
|
|
257
|
+
* Exactly one of `margin`, `padding`, or `both` is typically `true`.
|
|
258
|
+
* `bound` can be used to visualize the outer bound in addition to spacing.
|
|
259
|
+
*/
|
|
25
260
|
spacing?: {
|
|
261
|
+
/** Visualize the element's margins. */
|
|
26
262
|
margin?: boolean;
|
|
263
|
+
/** Visualize the element's padding. */
|
|
27
264
|
padding?: boolean;
|
|
265
|
+
/**
|
|
266
|
+
* Visualize both margin and padding in a combined overlay.
|
|
267
|
+
* @remarks Mutually exclusive with `margin` and `padding` where applicable.
|
|
268
|
+
*/
|
|
28
269
|
both?: boolean;
|
|
270
|
+
/**
|
|
271
|
+
* Emphasize the bounding outline of the target in addition to spacing.
|
|
272
|
+
* @remarks Often used to show the element's overall occupied box.
|
|
273
|
+
*/
|
|
29
274
|
bound?: boolean;
|
|
30
275
|
};
|
|
276
|
+
/**
|
|
277
|
+
* Options for the `"grid"` feature.
|
|
278
|
+
*
|
|
279
|
+
* @remarks
|
|
280
|
+
* Present only when {@link SpeccerOptionsInterface.type | type} is `"grid"`.
|
|
281
|
+
* `toggle` indicates the primary axis selection and should be `"rows" | "columns" | "both"`.
|
|
282
|
+
* The convenience flags (`both`, `rows`, `columns`) mirror the current state for easy checks.
|
|
283
|
+
*/
|
|
31
284
|
grid?: {
|
|
285
|
+
/**
|
|
286
|
+
* Controls which grid axes are active.
|
|
287
|
+
* @remarks Allowed values: `"rows" | "columns" | "both"`.
|
|
288
|
+
*/
|
|
32
289
|
toggle: string;
|
|
290
|
+
/** Convenience flag set when both rows and columns are active. */
|
|
33
291
|
both?: boolean;
|
|
292
|
+
/** Convenience flag set when only rows are active. */
|
|
34
293
|
rows?: boolean;
|
|
294
|
+
/** Convenience flag set when only columns are active. */
|
|
35
295
|
columns?: boolean;
|
|
36
296
|
};
|
|
37
297
|
}
|
|
38
298
|
|
|
39
|
-
/**
|
|
40
|
-
* Extends the global Window interface to add custom properties.
|
|
41
|
-
*/
|
|
42
|
-
declare global {
|
|
43
|
-
interface Window {
|
|
44
|
-
/**
|
|
45
|
-
* Represents the DrawSVGCurlyBracket class for drawing curly brackets.
|
|
46
|
-
*/
|
|
47
|
-
DrawSVGCurlyBracket: any;
|
|
48
|
-
/**
|
|
49
|
-
* Represents the DrawCircle class for drawing circles.
|
|
50
|
-
*/
|
|
51
|
-
DrawCircle: any;
|
|
52
|
-
/**
|
|
53
|
-
* Represents the DrawSVGLine class for drawing lines.
|
|
54
|
-
*/
|
|
55
|
-
DrawSVGLine: any;
|
|
56
|
-
/**
|
|
57
|
-
* Represents the speccer object for additional functionality.
|
|
58
|
-
*/
|
|
59
|
-
speccer: any;
|
|
60
|
-
/**
|
|
61
|
-
* Represents the custom literals to be used.
|
|
62
|
-
* 
|
|
63
|
-
* @example
|
|
64
|
-
* ```js
|
|
65
|
-
* window.SPECCER_LITERALS = [あ,い,う,え,お,か,き,く,け,こ,さ,し,す,せ,そ,た,ち,つ,て,と,な,に,ぬ,ね,の,は,ひ,ふ,へ,ほ,ま,み,む,め,も,や,ゆ,よ,ら,り,る,れ,ろ,わ,を];
|
|
66
|
-
* speccer();
|
|
67
|
-
* ```
|
|
68
|
-
*/
|
|
69
|
-
SPECCER_LITERALS: string[];
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
//# sourceMappingURL=global.d.ts.map
|
|
73
|
-
|
|
74
299
|
/**
|
|
75
300
|
* Remove a speccer element by removing associated elements and SVG paths.
|
|
76
301
|
*
|
|
@@ -90,37 +315,220 @@ declare global {
|
|
|
90
315
|
*/
|
|
91
316
|
declare const removeSpeccerElement: (el: HTMLElement) => void;
|
|
92
317
|
|
|
318
|
+
/**
|
|
319
|
+
* This feature will highlight the grid spacing in a `display: grid;` element.
|
|
320
|
+
*
|
|
321
|
+
* 
|
|
322
|
+
*
|
|
323
|
+
* @example
|
|
324
|
+
*
|
|
325
|
+
* Use the following code, either for html or js:
|
|
326
|
+
*
|
|
327
|
+
* ```html
|
|
328
|
+
* <div
|
|
329
|
+
* data-speccer="grid [columns|rows]"
|
|
330
|
+
* class="…"
|
|
331
|
+
* >
|
|
332
|
+
* …
|
|
333
|
+
* </div>
|
|
334
|
+
* ```
|
|
335
|
+
*
|
|
336
|
+
* ```ts
|
|
337
|
+
* const targetElement = document.getElementById('target');
|
|
338
|
+
* const options = {
|
|
339
|
+
* type: 'grid',
|
|
340
|
+
* grid: {
|
|
341
|
+
* toggle: 'both'
|
|
342
|
+
* }
|
|
343
|
+
* };
|
|
344
|
+
*
|
|
345
|
+
* grid(targetElement, options);
|
|
346
|
+
* ```
|
|
347
|
+
*
|
|
348
|
+
*/
|
|
93
349
|
declare const grid: {
|
|
94
350
|
create: (targetElement: HTMLElement, styles: Partial<CSSStyleDeclaration>, options: SpeccerOptionsInterface) => Promise<void>;
|
|
95
351
|
element: (targetElement: HTMLElement, options?: SpeccerOptionsInterface | undefined) => Promise<void>;
|
|
96
352
|
};
|
|
353
|
+
/**
|
|
354
|
+
* This feature highlights the spacing of an element.
|
|
355
|
+
*
|
|
356
|
+
* 
|
|
357
|
+
* *
|
|
358
|
+
* @example
|
|
359
|
+
*
|
|
360
|
+
* Use the following code, either for html or js:
|
|
361
|
+
*
|
|
362
|
+
* ```html
|
|
363
|
+
* <div
|
|
364
|
+
* data-speccer="spacing [padding|margin][bound]"
|
|
365
|
+
* class="…"
|
|
366
|
+
* >
|
|
367
|
+
* …
|
|
368
|
+
* </div>
|
|
369
|
+
* ```
|
|
370
|
+
* ```ts
|
|
371
|
+
* const targetElement = document.getElementById('target');
|
|
372
|
+
* element(targetElement);
|
|
373
|
+
* ```
|
|
374
|
+
*/
|
|
97
375
|
declare const spacing: {
|
|
98
376
|
create: (text?: string | number, tag?: string) => HTMLElement;
|
|
99
377
|
element: (targetElement: HTMLElement, options?: SpeccerOptionsInterface | undefined) => Promise<void>;
|
|
100
378
|
};
|
|
379
|
+
/**
|
|
380
|
+
* This feature annotate or highlight the anatomy of an element.
|
|
381
|
+
*
|
|
382
|
+
* 
|
|
383
|
+
*
|
|
384
|
+
* In your component examples, use the following attribute. Remember to use the `data-speccer="pin-area"`-attribute on a parent element to scope the marking.
|
|
385
|
+
*
|
|
386
|
+
* @example
|
|
387
|
+
* ```html
|
|
388
|
+
* <div data-speccer="pin-area">
|
|
389
|
+
* <div
|
|
390
|
+
* data-speccer="pin [bracket [curly] |enclose] [left|right|top|bottom]"
|
|
391
|
+
* class="..."
|
|
392
|
+
* ></div>
|
|
393
|
+
* </div>
|
|
394
|
+
* ```
|
|
395
|
+
*
|
|
396
|
+
*/
|
|
101
397
|
declare const pin: {
|
|
102
398
|
createPinElement: (content: string | undefined, options: SpeccerOptionsInterface, id?: string, n?: string) => HTMLElement;
|
|
103
|
-
pinElement: (targetElement: HTMLElement, parentElement: HTMLElement, content: string, options: SpeccerOptionsInterface) => Promise<string |
|
|
399
|
+
pinElement: (targetElement: HTMLElement, parentElement: HTMLElement, content: string, options: SpeccerOptionsInterface) => Promise<string | undefined>;
|
|
104
400
|
pinElements: (sectionElement: HTMLElement, options?: SpeccerOptionsInterface | undefined) => Promise<void>;
|
|
105
401
|
};
|
|
402
|
+
/**
|
|
403
|
+
* This feature measures given element
|
|
404
|
+
*
|
|
405
|
+
* 
|
|
406
|
+
*
|
|
407
|
+
* @example
|
|
408
|
+
*
|
|
409
|
+
* Use the following code, either for html or js:
|
|
410
|
+
*
|
|
411
|
+
* ```html
|
|
412
|
+
* <div
|
|
413
|
+
* data-speccer="measure [height left|right] | [width top|bottom]"
|
|
414
|
+
* class="..."
|
|
415
|
+
* >
|
|
416
|
+
* …
|
|
417
|
+
* </div>
|
|
418
|
+
* ```
|
|
419
|
+
*
|
|
420
|
+
* ```ts
|
|
421
|
+
* const targetElement = document.getElementById('target');
|
|
422
|
+
* const options = {
|
|
423
|
+
* position: 'right',
|
|
424
|
+
* measure: {
|
|
425
|
+
* height: true
|
|
426
|
+
* }
|
|
427
|
+
* };
|
|
428
|
+
*
|
|
429
|
+
* measure(targetElement, options);
|
|
430
|
+
* ```
|
|
431
|
+
*
|
|
432
|
+
*/
|
|
106
433
|
declare const measure: {
|
|
107
434
|
create: (text: string | number | undefined, options: SpeccerOptionsInterface, id: string, tag?: string) => HTMLElement;
|
|
108
435
|
element: (targetElement: HTMLElement, options?: SpeccerOptionsInterface | undefined) => Promise<void>;
|
|
109
436
|
};
|
|
437
|
+
/**
|
|
438
|
+
* This feature marks given element
|
|
439
|
+
*
|
|
440
|
+
* 
|
|
441
|
+
*
|
|
442
|
+
* @example
|
|
443
|
+
*
|
|
444
|
+
* Use the following code, either for html or js:
|
|
445
|
+
*
|
|
446
|
+
* ```html
|
|
447
|
+
* <div
|
|
448
|
+
* data-speccer="mark"
|
|
449
|
+
* class="..."
|
|
450
|
+
* >
|
|
451
|
+
* …
|
|
452
|
+
* </div>
|
|
453
|
+
* ```
|
|
454
|
+
*
|
|
455
|
+
* ```ts
|
|
456
|
+
* const targetElement = document.getElementById('target');
|
|
457
|
+
* const options = {
|
|
458
|
+
* type: 'mark'
|
|
459
|
+
* };
|
|
460
|
+
*
|
|
461
|
+
* mark(targetElement, options);
|
|
462
|
+
* ```
|
|
463
|
+
*
|
|
464
|
+
*/
|
|
110
465
|
declare const mark: {
|
|
111
466
|
create: (id: string, n?: string) => HTMLElement;
|
|
112
467
|
element: (targetElement: HTMLElement) => Promise<void>;
|
|
113
468
|
};
|
|
469
|
+
/**
|
|
470
|
+
* This feature presents typography
|
|
471
|
+
*
|
|
472
|
+
* 
|
|
473
|
+
*
|
|
474
|
+
* @example
|
|
475
|
+
*
|
|
476
|
+
* Use the following code, either for html or js:
|
|
477
|
+
*
|
|
478
|
+
* ```html
|
|
479
|
+
* <div
|
|
480
|
+
* data-speccer="typography [top|right|bottom|left] [syntax]"
|
|
481
|
+
* class="..."
|
|
482
|
+
* >
|
|
483
|
+
* …
|
|
484
|
+
* </div>
|
|
485
|
+
* ```
|
|
486
|
+
*
|
|
487
|
+
* ```ts
|
|
488
|
+
* const targetElement = document.getElementById('target');
|
|
489
|
+
* const options = {
|
|
490
|
+
* position: 'right',
|
|
491
|
+
* type: 'typography',
|
|
492
|
+
* typography: {
|
|
493
|
+
* useSyntaxHighlighting: false
|
|
494
|
+
* }
|
|
495
|
+
* };
|
|
496
|
+
*
|
|
497
|
+
* typography(targetElement, options);
|
|
498
|
+
* ```
|
|
499
|
+
*
|
|
500
|
+
*/
|
|
114
501
|
declare const typography: {
|
|
115
502
|
create: (html: string, options: SpeccerOptionsInterface, id: string) => HTMLElement;
|
|
116
503
|
element: (targetElement: HTMLElement, options?: SpeccerOptionsInterface | undefined) => Promise<void>;
|
|
117
504
|
};
|
|
505
|
+
/**
|
|
506
|
+
* The available modes to run SPECCER with
|
|
507
|
+
*
|
|
508
|
+
*/
|
|
118
509
|
declare const modes: {
|
|
119
510
|
dom: (speccer: SpeccerFunctionType) => void;
|
|
120
511
|
lazy: () => void;
|
|
121
512
|
manual: (speccer: SpeccerFunctionType) => void;
|
|
122
513
|
activate: (speccer: SpeccerFunctionType) => void;
|
|
123
514
|
};
|
|
515
|
+
/**
|
|
516
|
+
*
|
|
517
|
+
* @example
|
|
518
|
+
* ```typescript
|
|
519
|
+
* import '@phun-ky/speccer/dist/speccer.min.css';
|
|
520
|
+
* import speccer from '@phun-ky/speccer';
|
|
521
|
+
*
|
|
522
|
+
* // do stuff
|
|
523
|
+
* speccer();
|
|
524
|
+
* ```
|
|
525
|
+
* @example
|
|
526
|
+
* ```html
|
|
527
|
+
* <link rel="stylesheet" href="../path/to/speccer.min.css" />
|
|
528
|
+
* <script src="../path/to/speccer.js"></script>
|
|
529
|
+
* ```
|
|
530
|
+
*/
|
|
124
531
|
declare const speccer: () => void;
|
|
125
532
|
|
|
126
|
-
export { speccer as default, grid, mark, measure, modes, pin, removeSpeccerElement, spacing, typography };
|
|
533
|
+
export { a11y, speccer as default, grid, mark, measure, modes, pin, removeSpeccerElement, spacing, typography };
|
|
534
|
+
export type { SpeccerFunctionType, SpeccerOptionsInterface };
|
package/dist/speccer.esm.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @phun-ky/speccer
|
|
3
3
|
* A script to annotate, show spacing specs and to display typography information in documentation/website on HTML elements
|
|
4
4
|
* @author Alexander Vassbotn Røyne-Helgesen <alexander@phun-ky.net>
|
|
5
|
-
* @version 11.
|
|
5
|
+
* @version 11.3.0
|
|
6
6
|
* @license
|
|
7
7
|
* Copyright (c) 2018-2025 Alexander Vassbotn Røyne-Helgesen
|
|
8
8
|
*
|
|
@@ -24,4 +24,4 @@
|
|
|
24
24
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
25
|
* SOFTWARE.
|
|
26
26
|
*/
|
|
27
|
-
const t=t=>"string"==typeof t,e=e=>!t(e),n=t=>"number"==typeof t,o=t=>!n(t),i=t=>void 0===t,r=(t,e,n="noop")=>{if(!t)return;if(!e||e&&!e.length)return;const o=e.trim().split(" ").filter((t=>t!==n)).filter((t=>""!==t)).map((t=>t.trim()));t.classList.add(...o)},s=(t,n)=>t?!n&&e(t)?Object.keys(t).filter((e=>t[e])).join(" ").trim():`${t.trim()} ${n?Object.keys(n).filter((t=>n[t])).join(" "):""}`.trim():"",a=[..."ABCDEFGHIJKLMNOPQRSTUVWXYZ"],c="data-speccer",p="spacing",l="measure",d="typography",h="mark",u="grid",f="pin-area";var g,m,y,w,b,x,$;!function(t){t.Empty="",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top"}(g||(g={})),function(t){t.Pin="pin",t.Parent="parent",t.Text="text",t.Enclose="enclose",t.Subtle="subtle",t.Bracket="bracket",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top",t.SVG="svg",t.Curly="curly"}(m||(m={})),function(t){t.Measure="measure",t.Slim="slim",t.Width="width",t.Height="height",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top"}(y||(y={})),function(t){t.Typography="typography",t.Syntax="syntax",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top"}(w||(w={})),function(t){t.Spacing="spacing"}(b||(b={})),function(t){t.Mark="mark"}(x||(x={})),function(t){t.Grid="grid"}($||($={}));const E=t=>t.split(" "),A=t=>{if(null===t)return!1;return E(t).includes(m.Bracket)},S=t=>{if(null===t)return!1;return E(t).includes(m.Enclose)},C=t=>{if(null===t)return!1;return E(t).includes(m.Subtle)},k=t=>{if(null===t)return!1;return E(t).includes(m.Parent)},v=t=>{if(null===t)return!1;return E(t).includes(m.Text)},P=t=>{if(null===t)return!1;return E(t).includes(y.Height)},L=t=>{if(null===t)return!1;return E(t).includes(y.Slim)},B=t=>{if(null===t)return!1;return E(t).includes(y.Width)},R=t=>{if(null===t)return!1;const e=E(t);return(k(t)&&!S(t)&&!A(t)||v(t)||e.includes(m.SVG))&&!T(t)},T=t=>{if(null===t)return!1;const e=E(t);return e.includes(m.Curly)&&e.includes(m.Bracket)},N=t=>!!t&&t.split(" ").includes(w.Syntax),q=(e,n)=>(t=>null!==t&&t.split(" ").includes(m.Pin))(e)?"pin":((e,n)=>null!==e&&e.split(" ").includes($.Grid)&&t(n.display)&&("grid"===n.display||(n.display||"").includes("grid")))(e,n)?"grid":(t=>null!==t&&t.split(" ").includes(x.Mark))(e)?"mark":(t=>null!==t&&t.split(" ").includes(y.Measure))(e)?"measure":(t=>null!==t&&t.split(" ").includes(b.Spacing))(e)?"spacing":(t=>null!==t&&t.split(" ").includes(w.Typography))(e)?"typography":"pin",H=t=>(t=>null!==t&&E(t).includes(m.Left))(t)?"left":(t=>null!==t&&E(t).includes(m.Right))(t)?"right":(t=>null!==t&&E(t).includes(m.Bottom))(t)?"bottom":"top",I=(t,e,n)=>{const o=q(t,e),i={slug:(r=t,r.normalize("NFKD").replace(/[\u0300-\u036f]/g,"").trim().toLowerCase().replace(/[^a-z0-9 -]/g,"").replace(/\s+/g," ").replace(/(?:^\w|[A-Z]|\b\w)/g,((t,e)=>0===e?t.toLowerCase():t.toUpperCase())).replace(/\s+/g,"")),position:H(t),type:o};var r;if("pin"===o&&(i.pin={bracket:A(t),enclose:S(t),subtle:C(t),parent:k(t),text:v(t),useSVGLine:R(t),useCurlyBrackets:T(t)}),"measure"===o&&(i.measure={slim:L(t),height:P(t),width:B(t)}),"typography"===o&&(i.typography={useSyntaxHighlighting:N(t)}),"grid"===o){const e=(t=>t?.includes("columns")?"columns":t?.includes("rows")?"rows":"both")(t);i.grid={toggle:e,both:"both"===e,rows:"rows"===e,columns:"columns"===e}}if("spacing"===o){const e=(t=>t?.includes("margin")?"margin":t?.includes("padding")?"padding":"both")(t);i.spacing={both:"both"===e,margin:"margin"===e,padding:"padding"===e,bound:t.includes("bound")}}return{...i,...n}},M=()=>"_"+Math.random().toString(36).substring(2,11),O=t=>!t.checkVisibility({opacityProperty:!0,checkVisibilityCSS:!0}),V=()=>new Promise(requestAnimationFrame),z=async(t,e,n)=>{await V();return getComputedStyle(t)[e]===n},G=async(t,e,n)=>{if(!t.parentElement)return null;return await z(t.parentElement,e,n)?t.parentElement:await G(t.parentElement,e,n)},j=(t,e,n)=>t-e.width/2+n.width/2,W=(t,e,n)=>t-e.height/2+n.height/2,D=async t=>{await V();let e=t.getBoundingClientRect(),n=e.top+window.scrollY;const o=e.left+window.scrollX,i=await(async t=>await G(t,"position","sticky"))(t);if(await(async t=>await z(t,"position","sticky"))(t)){const o=t.style.position;await V(),t.style.position="relative",await V(),e=t.getBoundingClientRect(),n=e.top,await V(),t.style.position=o}else if(i){const o=i.style.position;await V(),i.style.position="relative",await V(),e=t.getBoundingClientRect(),n=e.top,await V(),i.style.position=o}return{height:e.height,width:e.width,top:n,left:o}},F=async(t,e)=>{await V();const n=t.getBoundingClientRect(),o=await D(e),i=await(async(t,e)=>{await V();const n=t.getBoundingClientRect();await V();const o=e.getBoundingClientRect(),i=o.top+window.scrollY,r=o.left+window.scrollX;return{height:o.height,width:o.width,top:W(i,n,o),left:j(r,n,o)}})(t,e),r=o.height,s=o.width,a=n.height,c=n.width;return{absolute:()=>({top:o.top,left:o.left,height:r,width:s}),toTop:({center:t=!1,sourceHeight:e=a,modifier:n=0}={})=>({top:o.top+e+n,left:t?i.left:o.left,height:r,width:s}),fromTop:({center:t=!1,sourceHeight:e=a,modifier:n=0}={})=>({top:o.top-e-n,left:t?i.left:o.left,height:r,width:s}),toBottom:({center:t=!1,sourceHeight:e=a,targetHeight:n=r,modifier:c=0}={})=>({top:o.top+n-(e+c),left:t?i.left:o.left,height:r,width:s}),fromBottom:({center:t=!1,targetHeight:e=r,modifier:n=0}={})=>({top:o.top+e+n,left:t?i.left:o.left,height:r,width:s}),toLeft:({center:t=!1,sourceWidth:e=c,modifier:n=0}={})=>({top:t?i.top:o.top,left:o.left+e+n,height:r,width:s}),fromLeft:({center:t=!1,sourceWidth:e=c,modifier:n=0}={})=>({top:t?i.top:o.top,left:o.left-e-n,height:r,width:s}),toRight:({center:t=!1,sourceWidth:e=c,targetWidth:n=s,modifier:a=0}={})=>({top:t?i.top:o.top,left:o.left+n-(e+a),height:r,width:s}),fromRight:({center:t=!1,targetWidth:e=s,modifier:n=0}={})=>({top:t?i.top:o.top,left:o.left+e+n,height:r,width:s})}},_=async(e,o)=>{var i;!e||!o||t(o)||n(o)||(i=o,"boolean"==typeof i)||Array.isArray(o)&&!o.length||!Object.keys(o).length&&o.constructor===Object||(await V(),Array.isArray(o)&&(o=o.reduce(((t,e)=>(t[e.key]=e.value,t)),{})),Object.assign(e.style,o))},X=async t=>(await V(),getComputedStyle(t,null)),Y=async(t,e,n)=>{await V();const{grid:o}=n;if(!o)return;const{toggle:i}=o,{height:s,width:a}=t.getBoundingClientRect(),{top:c,left:p}=await D(t),{gridTemplateColumns:l,gridTemplateRows:d,padding:h}=e,u=`speccer-${n.slug}-${t.getAttribute("id")||M()}`;if(t.setAttribute("data-speccer-element-id",u),"columns"===i||"both"===i){const t=parseInt(e.columnGap||"0"),n=document.createElement("div");document.documentElement.style.setProperty("--ph-speccer-grid-gap-original",`${t}px`),document.documentElement.style.setProperty("--ph-speccer-grid-gap",`${t<24?24:t}px`),t<24&&n.classList.add("speccer-small-grid"),n.setAttribute("data-speccer-id",u),r(n,"ph-speccer speccer speccer-grid-container"),_(n,{height:`${s+64}px`,width:`${a}px`,left:`${p}px`,top:c-32+"px",padding:h,gridTemplateColumns:l});const o=l?.split(" ").length||0;for(let t=0;t<o;t++){const t=document.createElement("div");r(t,"ph-speccer speccer speccer-grid-item"),n.appendChild(t)}document.body.appendChild(n)}if("rows"===i||"both"===i){const t=parseInt(e.rowGap||"0"),n=document.createElement("div");document.documentElement.style.setProperty("--ph-speccer-grid-row-gap-original",`${t}px`),document.documentElement.style.setProperty("--ph-speccer-grid-row-gap",`${t<24?24:t}px`),t<24&&n.classList.add("speccer-small-grid"),n.setAttribute("data-speccer-id",u),n.classList.add("ph-speccer"),n.classList.add("speccer"),n.classList.add("speccer-grid-row-container"),r(n,"ph-speccer speccer speccer-grid-row-container"),_(n,{width:`${a+64}px`,height:`${s}px`,top:`${c}px`,left:p-32+"px",padding:h,gridTemplateRows:d});const o=d?.split(" ").length||0;for(let t=0;t<o;t++){const t=document.createElement("div");r(t,"ph-speccer speccer speccer-grid-row-item"),n.appendChild(t)}document.body.appendChild(n)}},K=async(t,e)=>{if(!t)return;if(O(t))return;const n=t.getAttribute(c)||"",o=await X(t),i=I(n,o,e);"grid"===i.type&&i.grid&&(await V(),await Y(t,o,i))},U=(t,e="span")=>{const n=document.createElement(e);return n.setAttribute("id",t),r(n,"ph-speccer speccer mark"),n},Z=async t=>{if(!t)return;if(O(t))return;const e=t.getAttribute(c)||"";await V();const n=I(e,getComputedStyle(t));if("mark"!==n.type)return;const o=`speccer-${n.slug}-${t.getAttribute("id")||M()}`;t.setAttribute("data-speccer-element-id",o);const i=U(o);i.setAttribute("data-speccer-id",o),document.body.appendChild(i);const r=await F(i,t),{left:s,top:a,height:p,width:l}=r.absolute(),d={left:`${s}px`,top:`${a}px`,height:`${p}px`,width:`${l}px`};await _(i,d)},J=(t="",e,n,o="span")=>{const i=document.createElement(o);i.setAttribute("title",`${t}px`),i.setAttribute("id",n),i.setAttribute("data-speccer-id",n),i.setAttribute("data-measure",`${parseInt(String(t),10)}px`);const{measure:a,position:c}=e,p=s("ph-speccer speccer measure",{height:a?.height||!1,width:a?.width||!1,slim:a?.slim||!1,[c]:!0});return r(i,p),i},Q=async(t,e)=>{if(!t)return;if(O(t))return;const n=t.getAttribute("data-speccer")||"";await V();const o=I(n,getComputedStyle(t),e);if("measure"!==o.type||!o.measure)return;const{measure:i,position:r}=o;await V();const s=t.getBoundingClientRect(),a=i.slim?0:48,c=i.slim?0:96,p=`speccer-${o.slug}-${t.getAttribute("id")||M()}`;if(t.setAttribute("data-speccer-element-id",p),i.width)if(r===y.Bottom){const e=J(s.width,o,p);document.body.appendChild(e);const n=await F(e,t);if(i.slim){const{left:t,top:o,width:i}=n.fromBottom({center:!1});await _(e,{left:`${t}px`,top:`${o}px`,width:`${i}px`})}else{const{left:t,top:o,width:i,height:r}=n.absolute({center:!1});await _(e,{left:`${t}px`,top:`${o}px`,width:`${i}px`,height:`${r+a}px`})}}else{const e=J(s.width,o,p);document.body.appendChild(e);const n=await F(e,t);if(i.slim){const{left:t,top:o,width:i}=n.fromTop({center:!1});await _(e,{left:`${t}px`,top:`${o}px`,width:`${i}px`})}else{const{left:t,top:o,width:i,height:r}=n.absolute({center:!1});await _(e,{left:`${t}px`,top:o-a+"px",width:`${i}px`,height:`${r+a}px`})}}else if(i.height)if(r===y.Right){const e=J(s.height,o,p);document.body.appendChild(e);const n=await F(e,t);if(i.slim){const{left:t,top:o,height:i}=n.fromRight({center:!1});await _(e,{left:`${t}px`,top:`${o}px`,height:`${i}px`})}else{const{left:t,top:o,height:i,width:r}=n.absolute({center:!1});await _(e,{left:`${t}px`,top:`${o}px`,height:`${i}px`,width:`${r+c}px`})}}else{const e=J(s.height,o,p);document.body.appendChild(e);const n=await F(e,t);if(i.slim){const{left:t,top:o,height:i}=n.fromLeft({center:!1});await _(e,{left:`${t}px`,top:`${o}px`,height:`${i}px`})}else{const{left:t,top:o,height:i,width:r}=n.absolute({center:!1});await _(e,{left:t-c+"px",top:`${o}px`,height:`${i}px`,width:`${r+c}px`})}}},tt=(t="",e,n="",o="span")=>{const i=document.createElement(o),a={},{position:c,pin:p={}}=e,{useSVGLine:l,useCurlyBrackets:d,text:h,parent:u,bracket:f,enclose:g,subtle:m}=p;a.text=h,a.parent=u,a.bracket=f,a.enclose=g,a.subtle=m,a.svg=l,a.curly=d,a[c]=!0,!u||f||d||m||(a.svg=!0),!f&&!g||f&&d?i.innerHTML=t:(f||g)&&i.setAttribute("data-pin-counter",t);const y=s("ph-speccer speccer pin",a);return r(i,y),i.setAttribute("id",n),i.setAttribute("data-speccer-id",n),i},et=()=>{const{body:t,documentElement:e}=document;return Math.max(t.scrollHeight,t.offsetHeight,e.clientHeight,e.scrollHeight,e.offsetHeight)},nt=t=>t.top,ot=t=>t.left+t.width,it=t=>t.top+t.height,rt=t=>t.left,st=t=>t.left+t.width/2,at=t=>t.top+t.height/2,ct={center:t=>({x:st(t),y:at(t)}),top:t=>({x:st(t),y:nt(t)}),right:t=>({x:ot(t),y:at(t)}),bottom:t=>({x:st(t),y:it(t)}),left:t=>({x:rt(t),y:at(t)}),"right-top":t=>({x:ot(t),y:nt(t)}),"right-bottom":t=>({x:ot(t),y:it(t)}),"left-top":t=>({x:rt(t),y:nt(t)}),"left-bottom":t=>({x:rt(t),y:it(t)}),"top-left":t=>({x:rt(t),y:nt(t)}),"top-right":t=>({x:ot(t),y:nt(t)}),"bottom-left":t=>({x:rt(t),y:it(t)}),"bottom-right":t=>({x:ot(t),y:it(t)}),"top-center":t=>({x:st(t),y:nt(t)}),"right-center":t=>({x:ot(t),y:at(t)}),"bottom-center":t=>({x:st(t),y:it(t)}),"left-center":t=>({x:rt(t),y:at(t)})},pt=async(t,n="center")=>{if(!n)throw Error("No position given");if(e(n))throw Error("The position given is not the required type: pos: "+typeof n);const o=["center","left","right","top","bottom","right-top","right-bottom","left-top","left-bottom","top-left","top-right","bottom-left","bottom-right","top-center","right-center","bottom-center","left-center"];if(!o.includes(n))throw Error(`The position given does not match allowed positions to use! Valid positions are: ${o.join(", ")}`);await V();const i=t.getBoundingClientRect();return ct[n](i)};class lt{#t;el;circle;radius;options;constructor(t,e,n){this.#e(t,e,n)}#e(t,e,n){if(!t||!e||!n)throw Error("Missing inputs el or radius or options");if(!document.body.contains(t))throw Error("el is not in the DOM");if(this.el=t,this.radius=e,this.options=n,this.#t=document.getElementById("ph-speccer-svg"),!this.#t)throw Error("Missing required SVG element to draw circles. Please see the documentation");const o=et();_(this.#t,{height:`${o}px`}),this.draw()}async draw(){const t=`ph_draw-circle-${M()}`;this.circle=document.createElementNS("http://www.w3.org/2000/svg","circle");const e=this.el.getAttribute("id")||M();if(this.el.setAttribute("id",e),this.circle.setAttribute("id",t),this.circle.setAttribute("data-el",e),this.circle.classList.add("ph-speccer"),this.circle.classList.add("speccer"),this.circle.classList.add("circle"),!this.#t)throw Error("No parentNode found for circle");this.#t.appendChild(this.circle);const{x:n,y:o}=await pt(this.el,this.options.position);this.circle.setAttribute("r",this.radius+""),this.circle.setAttribute("cx",Math.round(n)+""),this.circle.setAttribute("cy",Math.round(o+document.documentElement.scrollTop)+""),this.circle.setAttribute("fill","currentColor")}}window.DrawCircle=lt;const dt=async(t,e,n="center",o="center")=>{if(!t||!e)throw Error("No element given");const{x:i,y:r}=await pt(t,n),{x:s,y:a}=await pt(e,o);return{x1:i,y1:r,x2:s,y2:a}},ht=(t,e)=>{const{x1:n,x2:o,y1:i,y2:r}=t,{direct:s=!1,firstSet:a=!1,direction:c}=e,p={x:n,y:i},l={x:o,y:r};return s?a?"west"===c?{firstPoint:p,firstControl:{x:n-32,y:i-8},lastPoint:l,lastControl:{x:o+32,y:r}}:"south"===c?{firstPoint:p,firstControl:{x:n-8,y:i+32},lastPoint:l,lastControl:{x:o,y:r-32}}:"east"===c?{firstPoint:p,firstControl:{x:n+32,y:i-8},lastPoint:l,lastControl:{x:o-32,y:r}}:{firstPoint:p,firstControl:{x:n-8,y:i-32},lastPoint:l,lastControl:{x:o,y:r+32}}:"west"===c?{firstPoint:p,firstControl:{x:n-32,y:i+8},lastPoint:l,lastControl:{x:o+32,y:r}}:"south"===c?{firstPoint:p,firstControl:{x:n+8,y:i+32},lastPoint:l,lastControl:{x:o,y:r-32}}:"east"===c?{firstPoint:p,firstControl:{x:n+32,y:i+8},lastPoint:l,lastControl:{x:o-32,y:r}}:{firstPoint:p,firstControl:{x:n+8,y:i-32},lastPoint:l,lastControl:{x:o,y:r+32}}:{firstPoint:p,firstControl:{x:n+(o-n)/2,y:i},lastPoint:l,lastControl:{x:n+(o-n)/2,y:r}}},ut=async(t,e,n)=>{const{pos1:o,pos2:i,firstSet:r=!1,direction:s}=n,{x1:a,y1:c,x2:p,y2:l}=await dt(t,e,o,i);let d=0,h=0;"north"===s?h=8:"west"===s?d=8:"east"===s?d=-8:"south"===s&&(h=-8);const{firstPoint:u,firstControl:f,lastControl:g,lastPoint:m}=ht({x1:a+0,x2:p+d,y1:c+0+document.documentElement.scrollTop,y2:l+h+document.documentElement.scrollTop},{direct:!0,firstSet:r,direction:s});return`M ${u.x} ${u.y}C ${f.x} ${f.y}, ${g.x} ${g.y}, ${m.x} ${m.y}`},ft=async({start:t,stop:e,crude:n=!1})=>{const{x1:r,y1:s,x2:a,y2:c}=await dt(t,e),p=((t,e,n,r,s=!0)=>{if(i(t)||i(e)||i(n)||i(r))throw new SyntaxError("Missing input for `angle`");if(o(t)||o(e)||o(n)||o(r))throw TypeError(`Parameters for \`angle\` do not have the required type. Requires number! Got: ${typeof t} ${typeof e} ${typeof n} ${typeof r}`);const a=r-e,c=n-t;let p=Math.atan2(a,c);return p*=180/Math.PI,s&&p<0&&(p+=360),p})(r,s,a,c);return n?(t=>{if(t>360)throw new RangeError("Parameter cannot exceed 360");if(t<0)throw new RangeError("Parameter cannot be lower than 0");return t>=45&&t<=135?"south":t>135&&t<=225?"west":t>225&&t<=315?"north":"east"})(p):(t=>{if(t>360)throw new RangeError("Parameter cannot exceed 360");if(t<0)throw new RangeError("Parameter cannot be lower than 0");return t>=0&&t<=22.5?"east":t>=22.5&&t<=67.5?"south-east":t>=67.5&&t<=112.5?"south":t>=112.5&&t<=157.5?"south-west":t>=157.5&&t<=202.5?"west":t>=202.5&&t<=247.5?"north-west":t>=247.5&&t<=292.5?"north":t>=292.5&&t<=337.5?"north-east":"east"})(p)};class gt{#t;#n;startElement;stopElement;firstPathElement;secondPathElement;constructor(t,e){this.#e(t,e)}#e(t,e){if(!t||!e)throw Error("Missing inputs startElement and stopElement");if(!document.body.contains(e))throw Error("stopElement is not in the DOM");if(!document.body.contains(t))throw Error("startElement is not in the DOM");if(this.startElement=t,this.stopElement=e,this.#t=document.getElementById("ph-speccer-svg"),this.#n=document.getElementById("ph-speccer-path"),!this.#n||!this.#t)throw Error("Missing required SVG element to draw lines. Please see the documentation");const n=et();_(this.#t,{height:`${n}px`}),this.connect()}connect(){this.draw(this.#n)}#o(t){if(!t)throw Error("No path given to #getPathElement!");const e=`ph_draw_path-path-${M()}`,n=t.cloneNode(!1),o=this.startElement.getAttribute("id")||M();return this.startElement.setAttribute("id",o),n.setAttribute("data-start-el",o),n.setAttribute("id",e),n.classList.remove("original"),n.classList.add("speccer"),n}async draw(t){if(!t)throw Error("No path given to draw!");const e=this.#o(t),n=this.#o(t);if(!t.parentNode)throw Error("No parentNode found for path");this.firstPathElement=t.parentNode.insertBefore(e,t.nextSibling),this.secondPathElement=t.parentNode.insertBefore(n,t.nextSibling);const o=await ft({stop:this.stopElement,start:this.startElement,crude:!0}),{path1pos1:i,path1pos2:r,path2pos1:s,path2pos2:a}=(t=>{let e,n,o,i;switch(t){case"east":e="right-top",n="left-center",o="right-bottom",i="left-center";break;case"south":e="bottom-left",n="top-center",o="bottom-right",i="top-center";break;case"west":e="left-top",n="right-center",o="left-bottom",i="right-center";break;default:e="top-left",n="bottom-center",o="top-right",i="bottom-center"}return{path1pos1:e,path1pos2:n,path2pos1:o,path2pos2:i}})(o),c=await ut(this.startElement,this.stopElement,{pos1:i,pos2:r,firstSet:!0,direction:o}),p=await ut(this.startElement,this.stopElement,{pos1:s,pos2:a,direction:o});this.firstPathElement.setAttribute("data-direction",o),this.firstPathElement.setAttribute("data-pos1",i),this.firstPathElement.setAttribute("data-pos2",r),this.firstPathElement.setAttribute("d",c),this.secondPathElement.setAttribute("data-direction",o),this.secondPathElement.setAttribute("data-pos1",s),this.secondPathElement.setAttribute("data-pos2",a),this.secondPathElement.setAttribute("d",p)}}window.DrawSVGCurlyBracket=gt;class mt{#t;#n;startElement;stopElement;options;line;constructor(t,e,n={}){this.#e(t,e,n)}#e(t,e,n={}){if(!t||!e)throw Error("Missing inputs startElement and stopElement");if(!document.body.contains(e))throw Error("stopElement is not in the DOM");if(!document.body.contains(t))throw Error("startElement is not in the DOM");if(this.startElement=t,this.stopElement=e,this.options=n,this.#t=document.getElementById("ph-speccer-svg"),this.#n=document.getElementById("ph-speccer-path"),!this.#n||!this.#t)throw Error("Missing required SVG element to draw lines. Please see the documentation");const o=et();_(this.#t,{height:`${o}px`}),this.connect()}connect(){this.draw(this.#n)}async draw(t){if(!t)throw Error("No path given to draw!");const e=`ph_draw_path-path-${M()}`,n=t.cloneNode(!1),o=this.startElement.getAttribute("id")||M();this.startElement.setAttribute("id",o),n.setAttribute("id",e),n.setAttribute("data-start-el",o),n.classList.remove("original"),n.classList.add("speccer");const{pin:i}=this.options;if(i?.text&&n.classList.add("text"),!t.parentNode)throw Error("No parentNode found for path");this.line=t.parentNode.insertBefore(n,t.nextSibling);const r=await ft({start:this.startElement,stop:this.stopElement,crude:!0}),{pos1:s,pos2:a}=(t=>{let e,n;switch(t){case"east":e="right",n="left";break;case"south":e="bottom",n="top";break;case"west":e="left",n="right";break;default:e="top",n="bottom"}return{pos1:e,pos2:n}})(r),c=await(async(t,e,n)=>{const{pos1:o,pos2:i}=n,{x1:r,y1:s,x2:a,y2:c}=await dt(t,e,o,i),{firstPoint:p,firstControl:l,lastControl:d,lastPoint:h}=ht({x1:r,x2:a,y1:s+document.documentElement.scrollTop,y2:c+document.documentElement.scrollTop},{direction:""});return`M ${p.x} ${p.y}C ${l.x} ${l.y}, ${d.x} ${d.y}, ${h.x} ${h.y}`})(this.startElement,this.stopElement,{pos1:s,pos2:a});this.line.setAttribute("data-direction",r),this.line.setAttribute("data-pos1",s),this.line.setAttribute("data-pos2",a),this.line.setAttribute("d",c)}}window.DrawSVGLine=mt;const yt=t=>parseInt(t,10),wt=t=>yt(getComputedStyle(t).getPropertyValue("--ph-speccer-pin-space"))||48,bt=async(t,e,n,o)=>{await V();const{pin:i={},position:r}=o,{useCurlyBrackets:s,subtle:a,bracket:c,text:p,parent:l,enclose:d}=i,h=wt(e),u=yt(getComputedStyle(e).getPropertyValue("--ph-speccer-measure-size"))||8;const f=await F(e,t);if(d){const{left:t,top:e,height:n,width:o}=f.absolute();return{left:`${t}px`,top:`${e}px`,height:`${n}px`,width:`${o}px`}}if((l||p)&&!c&&!s&&!a){if(r===m.Right){const{top:t}=f.fromRight({center:!0});await V();const{left:e,width:o}=n.getBoundingClientRect();return{left:`${e+o+h}px`,top:`${t}px`}}if(r===m.Bottom){const{left:t}=f.toBottom({center:!0});await V();const{top:e,height:o}=n.getBoundingClientRect();return{left:`${t}px`,top:`${e+o+h}px`}}if(r===m.Left){const{top:t}=f.fromLeft({center:!0});await V();const{left:e}=n.getBoundingClientRect();return{left:e-1.5*h-(p?170:0)+"px",top:`${t}px`}}const{left:t}=f.fromTop({center:!0});await V();const{top:e}=n.getBoundingClientRect();return{left:`${t}px`,top:e-1.5*h+"px"}}if(r===m.Left){if(c&&!s){const{left:t,top:e,height:n}=f.fromLeft({sourceWidth:u});return{left:`${t}px`,top:`${e}px`,height:`${n}px`}}const{left:t,top:e}=f.fromLeft({center:!0,modifier:s?h/1.5:h});return{left:`${t}px`,top:`${e}px`}}if(r===m.Right){if(c&&!s){const{left:t,top:e,height:n}=f.fromRight({center:!1});return{left:`${t}px`,top:`${e}px`,height:`${n}px`}}const{left:t,top:e}=f.fromRight({center:!0,modifier:s?h/1.5:h});return{left:`${t}px`,top:`${e}px`}}if(r===m.Bottom){if(c&&!s){const{left:t,top:e,width:n}=f.fromBottom({center:!1});return{left:`${t}px`,top:`${e}px`,width:`${n}px`}}const{left:t,top:e}=f.fromBottom({center:!0,modifier:s?h/1.5:h});return{left:`${t}px`,top:`${e}px`}}if(c&&!s){const{left:t,top:e,width:n}=f.fromTop({center:!1});return{left:`${t}px`,top:`${e}px`,width:`${n}px`}}const{left:g,top:y}=f.fromTop({center:!0,modifier:s?h/1.5:h});return{left:`${g}px`,top:`${y}px`}},xt=async(t,e,n,o)=>{if(!t)return;if("pin"!==o.type||!o.pin)return;const i=`speccer-${o.slug}-${t.getAttribute("id")||M()}`,r=tt(n,o,i);t.setAttribute("data-speccer-element-id",i),document.body.appendChild(r);const s=await bt(t,r,e,o);await _(r,s);const a=o.pin.text&&null!==t.getAttribute("data-speccer-title"),c=o.pin.parent&&!o.pin.enclose&&!o.pin.bracket&&!a;return o.pin.useSVGLine?(new mt(t,r,o),c&&new lt(t,5,o)):o.pin.useCurlyBrackets&&new gt(t,r),i};let $t=0;const Et=async(t,e)=>{if(!t)return;const n=t.querySelectorAll('[data-speccer^="pin"]');if(!n||0===n.length)return;const o=t.getAttribute("data-speccer-literals")||window.SPECCER_LITERALS||a;[...n].filter((async t=>!O(t))).forEach((async(n,i)=>{const r=((t,e)=>{let n=e[t];return 0===t&&($t=0),n||(n=`${e[$t]}${e[$t].toLowerCase()}`,$t++),n})(i,o),s=n.getAttribute("data-speccer")||"";await V();const a=getComputedStyle(n),c=I(s,a,e),p=((t,e,n)=>{const{pin:o}=n;if(!o)return t;const{text:i}=o;if(!i||null===e.getAttribute("data-speccer-title"))return t;const r=e.getAttribute("data-speccer-title"),s=e.getAttribute("data-speccer-description"),a=0===e.nodeName.indexOf("H")?`<span class="ph-speccer heading">${e.nodeName}</span>`:"";return!s&&r?`${a}<span class="ph-speccer title">${r}</span>`:s&&r?`${a}<span class="ph-speccer title">${r}</span><span class="ph-speccer description">${s.replaceAll("\\n","<br/>")}</span>`:t})(r,n,c);await xt(n,t,p,c)}))},At=(t="",e="span")=>{const n=document.createElement(e),o=document.createTextNode(`${t}px`);return n.appendChild(o),n.setAttribute("title",`${t}px`),r(n,"ph-speccer speccer spacing"),n},St=async(t,e)=>{if(!t)return;if(O(t))return;const n=t.getAttribute("data-speccer")||"",o=await X(t),i=I(n,o,e);if("spacing"!==i.type||!i.spacing)return;const a=((t,e)=>{const{marginTop:n,marginBottom:o,marginLeft:i,marginRight:r,paddingTop:s,paddingBottom:a,paddingLeft:c,paddingRight:p}=t;return e?.spacing?.padding?{paddingTop:s,paddingBottom:a,paddingLeft:c,paddingRight:p}:e?.spacing?.margin?{marginTop:n,marginBottom:o,marginLeft:i,marginRight:r}:{marginTop:n,marginBottom:o,marginLeft:i,marginRight:r,paddingTop:s,paddingBottom:a,paddingLeft:c,paddingRight:p}})(o,i),c=Object.keys(a).filter((t=>"0px"!==a[t]));if(!c.length)return;t.classList.add("is-specced");const p=`speccer-spacing-${t.getAttribute("id")||M()}`;t.setAttribute("data-speccer-element-id",p),c.forEach((async e=>{const n=yt(a[e]),o=At(n);o.setAttribute("data-speccer-id",p);const c=(t=>t.includes("Top")?t.replace("Top"," top"):t.includes("Right")?t.replace("Right"," right"):t.includes("Bottom")?t.replace("Bottom"," bottom"):t.includes("Left")?t.replace("Left"," left"):"")(e);r(o,s(c,{bound:!!i?.spacing?.bound})),document.body.appendChild(o);const l=await(async(t,e,n,o)=>{await V();const i=n.getBoundingClientRect(),r=await D(n),s=o?.spacing?.bound?0:96,a=o?.spacing?.bound?0:48;return"marginTop"===t?{height:`${e}px`,width:i.width+s+"px",left:r.left-s+"px",top:r.top-e+"px"}:"marginRight"===t?{height:i.height+a+"px",width:`${e}px`,left:r.left+parseInt(i.width+"",10)+"px",top:r.top+"px"}:"marginBottom"===t?{height:`${e}px`,width:i.width+s+"px",left:r.left-s+"px",top:r.top+parseInt(i.height+"",10)+"px"}:"marginLeft"===t?{height:i.height+a+"px",width:`${e}px`,left:r.left-e+"px",top:r.top+"px"}:"paddingTop"===t?{height:`${e}px`,width:i.width+s+"px",left:r.left-s+"px",top:r.top+"px"}:"paddingBottom"===t?{height:`${e}px`,width:i.width+s+"px",left:r.left-s+"px",top:r.top+(parseInt(i.height+"",10)-e)+"px"}:"paddingRight"===t?{height:i.height+a+"px",width:`${e}px`,left:r.left+(parseInt(i.width+"",10)-e)+"px",top:r.top+"px"}:"paddingLeft"===t?{height:i.height+a+"px",width:`${e}px`,left:r.left+"px",top:r.top+"px"}:void 0})(e,n,t,i);await _(o,l)}))},Ct=(t,e=3)=>parseFloat(String(t)).toFixed(e),kt=(t,e,n)=>{const o=document.createElement("div"),{typography:i,position:a}=e,c=s("ph-speccer speccer typography",{syntax:i?.useSyntaxHighlighting||!1,[a]:!0});return o.setAttribute("id",n),o.setAttribute("data-speccer-id",n),o.innerHTML=t,r(o,c),o},vt=async(t,e)=>{if(!t)return;if(O(t))return;const n=t.getAttribute("data-speccer")||"";await V();const o=I(n,getComputedStyle(t),e);if("typography"!==o.type||!o.typography)return;t.classList.add("is-specced");const i=await(async(t,e=!1)=>{const n=(t=>{const{lineHeight:e,letterSpacing:n,fontFamily:o,fontSize:i,fontStyle:r,fontVariationSettings:s,fontWeight:a}=t;return{lineHeight:e,letterSpacing:n,fontFamily:o,fontSize:i,fontStyle:r,fontVariationSettings:s,fontWeight:a}})(await X(t));if(e){const t=(n.fontFamily||"").split(",").map((t=>t.includes('"\'"')?`<span class="token string">${t}</span>`:t)).join('<span class="token punctuation">, </span>'),e=`<span class="token number">${parseInt(n.fontSize||"NaN",10)}</span><span class="token unit">px</span> <span class="token operator">/</span> <span class="token number">${parseInt(n.fontSize||"NaN",10)/16}</span><span class="token unit">rem</span>`,o=n.letterSpacing?n.letterSpacing.includes("px")?`<span class="token number">${parseInt(n.letterSpacing,10)}</span><span class="token unit">px</span>`:n.letterSpacing:"",i=n.lineHeight?"normal"!==n.lineHeight?`<span class="token number">${parseInt(n.lineHeight,10)}</span><span class="token unit">px</span> <span class="token operator">/</span> <span class="token number">${parseInt(n.lineHeight,10)/16}</span><span class="token unit">rem</span>`:"normal":"";return`\n<pre class="language-css" tabindex="-1"><code class="language-css"><span class="token selector"><span class="token class">.typography</span></span> <span class="token punctuation">{</span>\n <span class="token property">font-family</span><span class="token punctuation">:</span> ${t}<span class="token punctuation">;</span>\n <span class="token property">font-size</span><span class="token punctuation">:</span> ${e}<span class="token punctuation">;</span>\n <span class="token property">font-weight</span><span class="token punctuation">:</span> <span class="token number">${n.fontWeight}</span><span class="token punctuation">;</span>\n <span class="token property">font-variation-settings</span><span class="token punctuation">:</span> ${n.fontVariationSettings}<span class="token punctuation">;</span>\n <span class="token property">line-height</span><span class="token punctuation">:</span> ${i}<span class="token punctuation">;</span>\n <span class="token property">letter-spacing</span><span class="token punctuation">:</span> ${o}<span class="token punctuation">;</span>\n <span class="token property">font-style</span><span class="token punctuation">:</span> ${n.fontStyle}<span class="token punctuation">;</span>\n<span class="token punctuation">}</span></code></pre>`}return`\ntypography: {<ul class="speccer-styles"> <li><span class="property">font-family:</span> ${n.fontFamily};</li> <li><span class="property">font-size:</span> ${n.fontSize} / ${parseInt(n.fontSize||"NaN",10)/16}rem;</li> <li><span class="property">font-weight:</span> ${n.fontWeight};</li> <li><span class="property">font-variation-settings:</span> ${n.fontVariationSettings};</li> <li><span class="property">line-height:</span> ${"normal"!==n.lineHeight?`${parseInt(n.lineHeight||"NaN",10)}px / ${parseInt(n.lineHeight||"NaN",10)/16}rem`:"normal"};</li> <li><span class="property">letter-spacing:</span> ${n.letterSpacing};</li> <li><span class="property">font-style:</span> ${n.fontStyle};</li></ul>}`})(t,o.typography.useSyntaxHighlighting),r=`speccer-${o.slug}-${t.getAttribute("id")||M()}`;t.setAttribute("data-speccer-element-id",r);const s=kt(i,o,r);document.body.appendChild(s);const a=await(async(t,e,n)=>{const o=e.getBoundingClientRect(),i=wt(n),r=n.getBoundingClientRect(),s=await D(e),{typography:a,position:c}=t;if(a&&c===w.Right)return{left:s.left+o.width+i+"px",top:Ct(W(s.top,r,o))+"px"};if(a&&c===w.Top)return{left:Ct(j(s.left,r,o))+"px",top:s.top-r.height-i+"px"};if(a&&c===w.Bottom)return{left:Ct(j(s.left,r,o))+"px",top:s.top+o.height+i+"px"};return{left:s.left-r.width-i+"px",top:Ct(W(s.top,r,o))+"px"}})(o,t,s);_(s,a)},Pt=t=>{const e=()=>((t,e,n=!1)=>{let o;return function(i,...r){const s=n&&!o;o&&clearTimeout(o),o=setTimeout((function(){o=null,n||t.apply(i,r)}),e),s&&t.apply(i,r)}})((()=>{t()}),300);window.removeEventListener("resize",e),window.addEventListener("resize",e)},Lt=t=>{"loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>{t()})):t()},Bt=()=>{const t=new IntersectionObserver(((t,e)=>{for(const n of t)n.intersectionRatio>0&&(St(n.target),e.unobserve(n.target))}));for(const e of document.querySelectorAll(`[${c}^="${p}"],[${c}^="${p}"] *:not(td):not(tr):not(th):not(tfoot):not(thead):not(tbody)`))t.observe(e);const e=new IntersectionObserver(((t,e)=>{for(const n of t)n.intersectionRatio>0&&(Q(n.target),e.unobserve(n.target))}));for(const t of document.querySelectorAll(`[${c}^="${l}"]`))e.observe(t);const n=new IntersectionObserver(((t,e)=>{for(const n of t)n.intersectionRatio>0&&(Z(n.target),e.unobserve(n.target))}));for(const t of document.querySelectorAll(`[${c}^="${h}"]`))n.observe(t);const o=new IntersectionObserver(((t,e)=>{for(const n of t)n.intersectionRatio>0&&(vt(n.target),e.unobserve(n.target))}));for(const t of document.querySelectorAll(`[${c}^="${d}"]`))o.observe(t);const i=new IntersectionObserver(((t,e)=>{for(const n of t)n.intersectionRatio>0&&(K(n.target),e.unobserve(n.target))}));for(const t of document.querySelectorAll(`[${c}^="${u}"]`))i.observe(t);const r=new IntersectionObserver((async(t,e)=>{for(const n of t)n.intersectionRatio>0&&(await Et(n.target),e.unobserve(n.target))}));for(const t of document.querySelectorAll(`[${c}="${f}"]`))r.observe(t)},Rt=t=>{window.speccer=t},Tt=t=>{const e=document.currentScript;if(e){const n=e.getAttribute("src");n?.includes("speccer.js")&&(e.hasAttribute("data-manual")?Rt(t):e.hasAttribute("data-instant")?t():e.hasAttribute("data-dom")?Lt(t):e.hasAttribute("data-lazy")?Bt():Lt(t),e.hasAttribute("data-manual")||e.hasAttribute("data-lazy")||Pt(t))}},Nt=["alt","altgraph","capslock","control","fn","fnlock","hyper","meta","numlock","os","scrolllock","shift","super","symbol","command","ctrl","altgr","symbollock"],qt=["escape","esc","enter","return","⏎","␛"],Ht=async(t,e,n)=>{await V();const o=wt(n),i=await F(n,e);if("tabstops"===t){let{left:t,top:e}=i.fromTop();return t-=32,e+=32,t<=0&&(t=32),e<=0&&(e=32),{left:`${t}px`,top:`${e}px`}}if("landmark"===t||"autocomplete"===t||"headings"===t){let{left:t,top:e}=i.fromLeft();return t-=o,t<=0&&(t=o),e<=0&&(e=o),{left:`${t}px`,top:`${e}px`}}if("region"===t){const{left:t,top:e,height:n,width:o}=i.fromTop();return{height:`${n}px`,width:`${o}px`,left:`${t}px`,top:`${e}px`}}if("shortcut"===t){const{left:t,top:e}=i.fromBottom();return{left:`${t}px`,top:`${e}px`}}const{left:r,top:s}=i.fromTop({center:!0,modifier:o});return{left:r-32+"px",top:s-32+"px"}},It=async(t,e,n)=>{if(!t||!t.checkVisibility())return;const o=((t="tabstops",e,n="span")=>{const o=document.createElement(n),i=s("ph-speccer speccer a11y",{tabstops:"tabstops"===t,landmark:"landmark"===t,autocomplete:"autocomplete"===t,headings:"headings"===t,region:"region"===t});if("landmark"===t&&e){const t=document.createTextNode(String(e));o.appendChild(t)}return r(o,i),o})(n,e);if("landmark"===n){const e=(t=>{if(!t)return"";if(t.role&&""!==t.role)return t.role;const e=t.nodeName.toLowerCase();return["header","footer","section","form","main","nav","aside"].includes(e)?e:"N/A"})(t),n=t.nodeName.toLowerCase();o.innerHTML=`<${n} role="${e}">`}if("autocomplete"===n){const e=t.getAttribute("autocomplete")||"";o.innerHTML=`autocomplete="${e}"`}"headings"===n&&(o.innerHTML=t.nodeName,o.classList.add(t.nodeName.toLowerCase())),"tabstops"===n&&o.setAttribute("data-speccer-a11y-tabstops",e);const i=`speccer-a11y-${t.getAttribute("id")||M()}`;o.setAttribute("data-speccer-id",i),document.body.appendChild(o);const a=await Ht(n,t,o);await _(o,a)},Mt=async(t,e)=>{const n=e.split(/\s\+\s/).map((t=>t.trim())),o=document.createElement("div"),i=s("ph-speccer speccer a11y shortcut-holder");r(o,i);for(const t of n){const e=document.createElement("kbd"),n=document.createTextNode(t),i=s("ph-speccer speccer a11y shortcut",{modifier:Nt.includes(t.toLowerCase()),physical:qt.includes(t.toLowerCase())});r(e,i),e.appendChild(n);const a=`speccer-a11y-shortcut-${M()}`;o.setAttribute("data-speccer-id",a),o.appendChild(e)}document.body.appendChild(o);const a=await Ht("shortcut",t,o);await _(o,a)},Ot=t=>{const e=t.getAttribute("data-speccer-element-id");if(!e)return;const n=document.getElementById(e)||document.querySelectorAll(`[data-speccer-id="${e}"]`);if(n)if(Object.prototype.isPrototypeOf.call(NodeList.prototype,n))[...n].forEach((t=>t.remove()));else if(n.classList.contains("curly")||n.classList.contains("svg")){const e=t.getAttribute("id");document.querySelectorAll(`#ph-speccer-svg path[data-start-el="${e}"]`).forEach((t=>t.remove()))}},Vt={create:Y,element:K},zt={create:At,element:St},Gt={createPinElement:tt,pinElement:xt,pinElements:Et},jt={create:J,element:Q},Wt={create:U,element:Z},Dt={create:kt,element:vt},Ft={dom:Lt,lazy:Bt,manual:Rt,activate:Tt},_t=()=>{((t,e=document)=>{[].forEach.call(e.querySelectorAll(t),(function(t){t.remove()}))})(".ph-speccer.speccer");const t=document.querySelectorAll(`[${c}^="${p}"]`),e=document.querySelectorAll(`[${c}^="${l}"]`),n=document.querySelectorAll(`[${c}^="${d}"]`),o=document.querySelectorAll(`[${c}="${f}"]`),i=document.querySelectorAll(`[${c}^="${h}"]`),r=document.querySelectorAll(`[${c}^="${u}"]`);for(const t of i)Z(t);for(const t of r)K(t);for(const e of t)if(St(e),e.hasChildNodes()){const t=e.querySelectorAll("*:not(td):not(tr):not(th):not(tfoot):not(thead):not(tbody):not([data-speccer])"),n=e.getAttribute("data-speccer")||"";if(t?.length)for(const e of t)e.setAttribute("data-speccer",n),St(e)}for(const t of e)Q(t);for(const t of n)vt(t);for(const t of o)Et(t);(()=>{const t=document.querySelectorAll('[data-speccer*="a11y tabstops"]'),e=document.querySelectorAll('[data-speccer*="a11y landmark"]'),n=document.querySelectorAll('[data-speccer*="a11y shortcut"]'),o=document.querySelectorAll('[data-speccer*="a11y autocomplete"]'),i=document.querySelectorAll('[data-speccer*="a11y headings"]');if(n.length)for(const t of n){const e=t.getAttribute("data-speccer-a11y-shortcut");e&&""!==e&&!O(t)&&Mt(t,e)}if(t.length)for(const e of t){const t=e.querySelectorAll("\n a[href], area[href], input:not([disabled]):not([tabindex='-1']),\n button:not([disabled]):not([tabindex='-1']),select:not([disabled]):not([tabindex='-1']),\n textarea:not([disabled]):not([tabindex='-1']),\n iframe, object, embed, *[tabindex]:not([tabindex='-1']), *[contenteditable=true]\n");for(const[e,n]of t.entries()){if(!O(n)){It(n,e+1,"tabstops");continue}const t=n.getAttribute("id");if(!t)continue;const o=document.querySelector(`[for="${t}"]`);o&&!O(o)&&It(o,e+1,"tabstops")}}if(o.length)for(const t of o){const e=t.querySelectorAll("[autocomplete]");for(const t of e)O(t)||It(t,null,"autocomplete")}if(i.length)for(const t of i){const e=t.querySelectorAll('h1,h2,h3,h4,h5,h6, [role="heading"]');for(const t of e)O(t)||It(t,null,"headings")}if(e.length)for(const t of e){const e=t.querySelectorAll('\nheader, footer, section, form, main, nav, aside, [role="section"], [role="banner"],\n[role="complementary"], [role="contentinfo"], [role="form"], [role="main"],\n[role="navigation"], [role="region"], [role="search"]\n');for(const[t,n]of e.entries())O(n)||(It(n,t+1,"landmark"),It(n,null,"region"))}})()};Tt(_t);export{_t as default,Vt as grid,Wt as mark,jt as measure,Ft as modes,Gt as pin,Ot as removeSpeccerElement,zt as spacing,Dt as typography};
|
|
27
|
+
const t=t=>"string"==typeof t,e=e=>!t(e),n=t=>"number"==typeof t,o=t=>!n(t),i=t=>void 0===t,r=(t,e,n="noop")=>{if(!t)return;if(!e||e&&!e.length)return;const o=e.trim().split(" ").filter((t=>t!==n)).filter((t=>""!==t)).map((t=>t.trim()));t.classList.add(...o)},s=(t,n)=>t?!n&&e(t)?Object.keys(t).filter((e=>t[e])).join(" ").trim():`${t.trim()} ${n?Object.keys(n).filter((t=>n[t])).join(" "):""}`.trim():"",a=[..."ABCDEFGHIJKLMNOPQRSTUVWXYZ"],c="data-speccer",p="spacing",l="measure",d="typography",h="mark",u="grid",f="pin-area";var g,m,y,w,b,x,$;!function(t){t.Empty="",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top"}(g||(g={})),function(t){t.Pin="pin",t.Parent="parent",t.Text="text",t.Enclose="enclose",t.Subtle="subtle",t.Bracket="bracket",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top",t.SVG="svg",t.Curly="curly"}(m||(m={})),function(t){t.Measure="measure",t.Slim="slim",t.Width="width",t.Height="height",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top"}(y||(y={})),function(t){t.Typography="typography",t.Syntax="syntax",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top"}(w||(w={})),function(t){t.Spacing="spacing"}(b||(b={})),function(t){t.Mark="mark"}(x||(x={})),function(t){t.Grid="grid"}($||($={}));const E=t=>t.split(" "),A=t=>{if(null===t)return!1;return E(t).includes(m.Bracket)},S=t=>{if(null===t)return!1;return E(t).includes(m.Enclose)},C=t=>{if(null===t)return!1;return E(t).includes(m.Subtle)},k=t=>{if(null===t)return!1;return E(t).includes(m.Parent)},v=t=>{if(null===t)return!1;return E(t).includes(m.Text)},P=t=>{if(null===t)return!1;return E(t).includes(y.Height)},L=t=>{if(null===t)return!1;return E(t).includes(y.Slim)},B=t=>{if(null===t)return!1;return E(t).includes(y.Width)},R=t=>{if(null===t)return!1;const e=E(t);return(k(t)&&!S(t)&&!A(t)||v(t)||e.includes(m.SVG))&&!T(t)},T=t=>{if(null===t)return!1;const e=E(t);return e.includes(m.Curly)&&e.includes(m.Bracket)},N=t=>!!t&&t.split(" ").includes(w.Syntax),q=(e,n)=>(t=>null!==t&&t.split(" ").includes(m.Pin))(e)?"pin":((e,n)=>null!==e&&e.split(" ").includes($.Grid)&&t(n.display)&&("grid"===n.display||(n.display||"").includes("grid")))(e,n)?"grid":(t=>null!==t&&t.split(" ").includes(x.Mark))(e)?"mark":(t=>null!==t&&t.split(" ").includes(y.Measure))(e)?"measure":(t=>null!==t&&t.split(" ").includes(b.Spacing))(e)?"spacing":(t=>null!==t&&t.split(" ").includes(w.Typography))(e)?"typography":"pin",H=t=>(t=>null!==t&&E(t).includes(m.Left))(t)?"left":(t=>null!==t&&E(t).includes(m.Right))(t)?"right":(t=>null!==t&&E(t).includes(m.Bottom))(t)?"bottom":"top",I=(t,e,n)=>{const o=q(t,e),i={slug:(r=t,r.normalize("NFKD").replace(/[\u0300-\u036f]/g,"").trim().toLowerCase().replace(/[^a-z0-9 -]/g,"").replace(/\s+/g," ").replace(/(?:^\w|[A-Z]|\b\w)/g,((t,e)=>0===e?t.toLowerCase():t.toUpperCase())).replace(/\s+/g,"")),position:H(t),type:o};var r;if("pin"===o&&(i.pin={bracket:A(t),enclose:S(t),subtle:C(t),parent:k(t),text:v(t),useSVGLine:R(t),useCurlyBrackets:T(t)}),"measure"===o&&(i.measure={slim:L(t),height:P(t),width:B(t)}),"typography"===o&&(i.typography={useSyntaxHighlighting:N(t)}),"grid"===o){const e=(t=>t?.includes("columns")?"columns":t?.includes("rows")?"rows":"both")(t);i.grid={toggle:e,both:"both"===e,rows:"rows"===e,columns:"columns"===e}}if("spacing"===o){const e=(t=>t?.includes("margin")?"margin":t?.includes("padding")?"padding":"both")(t);i.spacing={both:"both"===e,margin:"margin"===e,padding:"padding"===e,bound:t.includes("bound")}}return{...i,...n}},M=()=>"_"+Math.random().toString(36).substring(2,11),O=t=>!t.checkVisibility({opacityProperty:!0,checkVisibilityCSS:!0}),V=()=>new Promise(requestAnimationFrame),z=async(t,e,n)=>{await V();return getComputedStyle(t)[e]===n},G=async(t,e,n)=>{if(!t.parentElement)return null;return await z(t.parentElement,e,n)?t.parentElement:await G(t.parentElement,e,n)},j=(t,e,n)=>t-e.width/2+n.width/2,W=(t,e,n)=>t-e.height/2+n.height/2,D=async t=>{await V();let e=t.getBoundingClientRect(),n=e.top+window.scrollY;const o=e.left+window.scrollX,i=await(async t=>await G(t,"position","sticky"))(t);if(await(async t=>await z(t,"position","sticky"))(t)){const o=t.style.position;await V(),t.style.position="relative",await V(),e=t.getBoundingClientRect(),n=e.top,await V(),t.style.position=o}else if(i){const o=i.style.position;await V(),i.style.position="relative",await V(),e=t.getBoundingClientRect(),n=e.top,await V(),i.style.position=o}return{height:e.height,width:e.width,top:n,left:o}},F=async(t,e)=>{await V();const n=t.getBoundingClientRect(),o=await D(e),i=await(async(t,e)=>{await V();const n=t.getBoundingClientRect();await V();const o=e.getBoundingClientRect(),i=o.top+window.scrollY,r=o.left+window.scrollX;return{height:o.height,width:o.width,top:W(i,n,o),left:j(r,n,o)}})(t,e),r=o.height,s=o.width,a=n.height,c=n.width;return{absolute:()=>({top:o.top,left:o.left,height:r,width:s}),toTop:({center:t=!1,sourceHeight:e=a,modifier:n=0}={})=>({top:o.top+e+n,left:t?i.left:o.left,height:r,width:s}),fromTop:({center:t=!1,sourceHeight:e=a,modifier:n=0}={})=>({top:o.top-e-n,left:t?i.left:o.left,height:r,width:s}),toBottom:({center:t=!1,sourceHeight:e=a,targetHeight:n=r,modifier:c=0}={})=>({top:o.top+n-(e+c),left:t?i.left:o.left,height:r,width:s}),fromBottom:({center:t=!1,targetHeight:e=r,modifier:n=0}={})=>({top:o.top+e+n,left:t?i.left:o.left,height:r,width:s}),toLeft:({center:t=!1,sourceWidth:e=c,modifier:n=0}={})=>({top:t?i.top:o.top,left:o.left+e+n,height:r,width:s}),fromLeft:({center:t=!1,sourceWidth:e=c,modifier:n=0}={})=>({top:t?i.top:o.top,left:o.left-e-n,height:r,width:s}),toRight:({center:t=!1,sourceWidth:e=c,targetWidth:n=s,modifier:a=0}={})=>({top:t?i.top:o.top,left:o.left+n-(e+a),height:r,width:s}),fromRight:({center:t=!1,targetWidth:e=s,modifier:n=0}={})=>({top:t?i.top:o.top,left:o.left+e+n,height:r,width:s})}},_=async(e,o)=>{var i;!e||!o||t(o)||n(o)||(i=o,"boolean"==typeof i)||Array.isArray(o)&&!o.length||!Object.keys(o).length&&o.constructor===Object||(await V(),Array.isArray(o)&&(o=o.reduce(((t,e)=>(t[e.key]=e.value,t)),{})),Object.assign(e.style,o))},X=async t=>(await V(),getComputedStyle(t,null)),Y=async(t,e,n)=>{await V();const{grid:o}=n;if(!o)return;const{toggle:i}=o,{height:s,width:a}=t.getBoundingClientRect(),{top:c,left:p}=await D(t),{gridTemplateColumns:l,gridTemplateRows:d,padding:h}=e,u=`speccer-${n.slug}-${t.getAttribute("id")||M()}`;if(t.setAttribute("data-speccer-element-id",u),"columns"===i||"both"===i){const t=parseInt(e.columnGap||"0"),n=document.createElement("div");document.documentElement.style.setProperty("--ph-speccer-grid-gap-original",`${t}px`),document.documentElement.style.setProperty("--ph-speccer-grid-gap",`${t<24?24:t}px`),t<24&&n.classList.add("speccer-small-grid"),n.setAttribute("data-speccer-id",u),r(n,"ph-speccer speccer speccer-grid-container"),_(n,{height:`${s+64}px`,width:`${a}px`,left:`${p}px`,top:c-32+"px",padding:h,gridTemplateColumns:l});const o=l?.split(" ").length||0;for(let t=0;t<o;t++){const t=document.createElement("div");r(t,"ph-speccer speccer speccer-grid-item"),n.appendChild(t)}document.body.appendChild(n)}if("rows"===i||"both"===i){const t=parseInt(e.rowGap||"0"),n=document.createElement("div");document.documentElement.style.setProperty("--ph-speccer-grid-row-gap-original",`${t}px`),document.documentElement.style.setProperty("--ph-speccer-grid-row-gap",`${t<24?24:t}px`),t<24&&n.classList.add("speccer-small-grid"),n.setAttribute("data-speccer-id",u),n.classList.add("ph-speccer"),n.classList.add("speccer"),n.classList.add("speccer-grid-row-container"),r(n,"ph-speccer speccer speccer-grid-row-container"),_(n,{width:`${a+64}px`,height:`${s}px`,top:`${c}px`,left:p-32+"px",padding:h,gridTemplateRows:d});const o=d?.split(" ").length||0;for(let t=0;t<o;t++){const t=document.createElement("div");r(t,"ph-speccer speccer speccer-grid-row-item"),n.appendChild(t)}document.body.appendChild(n)}},K=async(t,e)=>{if(!t)return;if(O(t))return;const n=t.getAttribute(c)||"",o=await X(t),i=I(n,o,e);"grid"===i.type&&i.grid&&(await V(),await Y(t,o,i))},U=(t,e="span")=>{const n=document.createElement(e);return n.setAttribute("id",t),r(n,"ph-speccer speccer mark"),n},Z=async t=>{if(!t)return;if(O(t))return;const e=t.getAttribute(c)||"";await V();const n=I(e,getComputedStyle(t));if("mark"!==n.type)return;const o=`speccer-${n.slug}-${t.getAttribute("id")||M()}`;t.setAttribute("data-speccer-element-id",o);const i=U(o);i.setAttribute("data-speccer-id",o),document.body.appendChild(i);const r=await F(i,t),{left:s,top:a,height:p,width:l}=r.absolute(),d={left:`${s}px`,top:`${a}px`,height:`${p}px`,width:`${l}px`};await _(i,d)},J=(t="",e,n,o="span")=>{const i=document.createElement(o);i.setAttribute("title",`${t}px`),i.setAttribute("id",n),i.setAttribute("data-speccer-id",n),i.setAttribute("data-measure",`${parseInt(String(t),10)}px`);const{measure:a,position:c}=e,p=s("ph-speccer speccer measure",{height:a?.height||!1,width:a?.width||!1,slim:a?.slim||!1,[c]:!0});return r(i,p),i},Q=async(t,e)=>{if(!t)return;if(O(t))return;const n=t.getAttribute("data-speccer")||"";await V();const o=I(n,getComputedStyle(t),e);if("measure"!==o.type||!o.measure)return;const{measure:i,position:r}=o;await V();const s=t.getBoundingClientRect(),a=i.slim?0:48,c=i.slim?0:96,p=`speccer-${o.slug}-${t.getAttribute("id")||M()}`;if(t.setAttribute("data-speccer-element-id",p),i.width)if(r===y.Bottom){const e=J(s.width,o,p);document.body.appendChild(e);const n=await F(e,t);if(i.slim){const{left:t,top:o,width:i}=n.fromBottom({center:!1});await _(e,{left:`${t}px`,top:`${o}px`,width:`${i}px`})}else{const{left:t,top:o,width:i,height:r}=n.absolute({center:!1});await _(e,{left:`${t}px`,top:`${o}px`,width:`${i}px`,height:`${r+a}px`})}}else{const e=J(s.width,o,p);document.body.appendChild(e);const n=await F(e,t);if(i.slim){const{left:t,top:o,width:i}=n.fromTop({center:!1});await _(e,{left:`${t}px`,top:`${o}px`,width:`${i}px`})}else{const{left:t,top:o,width:i,height:r}=n.absolute({center:!1});await _(e,{left:`${t}px`,top:o-a+"px",width:`${i}px`,height:`${r+a}px`})}}else if(i.height)if(r===y.Right){const e=J(s.height,o,p);document.body.appendChild(e);const n=await F(e,t);if(i.slim){const{left:t,top:o,height:i}=n.fromRight({center:!1});await _(e,{left:`${t}px`,top:`${o}px`,height:`${i}px`})}else{const{left:t,top:o,height:i,width:r}=n.absolute({center:!1});await _(e,{left:`${t}px`,top:`${o}px`,height:`${i}px`,width:`${r+c}px`})}}else{const e=J(s.height,o,p);document.body.appendChild(e);const n=await F(e,t);if(i.slim){const{left:t,top:o,height:i}=n.fromLeft({center:!1});await _(e,{left:`${t}px`,top:`${o}px`,height:`${i}px`})}else{const{left:t,top:o,height:i,width:r}=n.absolute({center:!1});await _(e,{left:t-c+"px",top:`${o}px`,height:`${i}px`,width:`${r+c}px`})}}},tt=(t="",e,n="",o="span")=>{const i=document.createElement(o),a={},{position:c,pin:p={}}=e,{useSVGLine:l,useCurlyBrackets:d,text:h,parent:u,bracket:f,enclose:g,subtle:m}=p;a.text=h,a.parent=u,a.bracket=f,a.enclose=g,a.subtle=m,a.svg=l,a.curly=d,a[c]=!0,!u||f||d||m||(a.svg=!0),!f&&!g||f&&d?i.innerHTML=t:(f||g)&&i.setAttribute("data-pin-counter",t);const y=s("ph-speccer speccer pin",a);return r(i,y),i.setAttribute("id",n),i.setAttribute("data-speccer-id",n),i},et=()=>{const{body:t,documentElement:e}=document;return Math.max(t.scrollHeight,t.offsetHeight,e.clientHeight,e.scrollHeight,e.offsetHeight)},nt=t=>t.top,ot=t=>t.left+t.width,it=t=>t.top+t.height,rt=t=>t.left,st=t=>t.left+t.width/2,at=t=>t.top+t.height/2,ct={center:t=>({x:st(t),y:at(t)}),top:t=>({x:st(t),y:nt(t)}),right:t=>({x:ot(t),y:at(t)}),bottom:t=>({x:st(t),y:it(t)}),left:t=>({x:rt(t),y:at(t)}),"right-top":t=>({x:ot(t),y:nt(t)}),"right-bottom":t=>({x:ot(t),y:it(t)}),"left-top":t=>({x:rt(t),y:nt(t)}),"left-bottom":t=>({x:rt(t),y:it(t)}),"top-left":t=>({x:rt(t),y:nt(t)}),"top-right":t=>({x:ot(t),y:nt(t)}),"bottom-left":t=>({x:rt(t),y:it(t)}),"bottom-right":t=>({x:ot(t),y:it(t)}),"top-center":t=>({x:st(t),y:nt(t)}),"right-center":t=>({x:ot(t),y:at(t)}),"bottom-center":t=>({x:st(t),y:it(t)}),"left-center":t=>({x:rt(t),y:at(t)})},pt=async(t,n="center")=>{if(!n)throw Error("No position given");if(e(n))throw Error("The position given is not the required type: pos: "+typeof n);const o=["center","left","right","top","bottom","right-top","right-bottom","left-top","left-bottom","top-left","top-right","bottom-left","bottom-right","top-center","right-center","bottom-center","left-center"];if(!o.includes(n))throw Error(`The position given does not match allowed positions to use! Valid positions are: ${o.join(", ")}`);await V();const i=t.getBoundingClientRect();return ct[n](i)};class lt{#t;el;circle;radius;options;constructor(t,e,n){this.#e(t,e,n)}#e(t,e,n){if(!t||!e||!n)throw Error("Missing inputs el or radius or options");if(!document.body.contains(t))throw Error("el is not in the DOM");if(this.el=t,this.radius=e,this.options=n,this.#t=document.getElementById("ph-speccer-svg"),!this.#t)throw Error("Missing required SVG element to draw circles. Please see the documentation");const o=et();_(this.#t,{height:`${o}px`}),this.draw()}async draw(){const t=`ph_draw-circle-${M()}`;this.circle=document.createElementNS("http://www.w3.org/2000/svg","circle");const e=this.el.getAttribute("id")||M();if(this.el.setAttribute("id",e),this.circle.setAttribute("id",t),this.circle.setAttribute("data-el",e),this.circle.classList.add("ph-speccer"),this.circle.classList.add("speccer"),this.circle.classList.add("circle"),!this.#t)throw Error("No parentNode found for circle");this.#t.appendChild(this.circle);const{x:n,y:o}=await pt(this.el,this.options.position);this.circle.setAttribute("r",this.radius+""),this.circle.setAttribute("cx",Math.round(n)+""),this.circle.setAttribute("cy",Math.round(o+document.documentElement.scrollTop)+""),this.circle.setAttribute("fill","currentColor")}}window.DrawCircle=lt;const dt=async(t,e,n="center",o="center")=>{if(!t||!e)throw Error("No element given");const{x:i,y:r}=await pt(t,n),{x:s,y:a}=await pt(e,o);return{x1:i,y1:r,x2:s,y2:a}},ht=(t,e)=>{const{x1:n,x2:o,y1:i,y2:r}=t,{direct:s=!1,firstSet:a=!1,direction:c}=e,p={x:n,y:i},l={x:o,y:r};return s?a?"west"===c?{firstPoint:p,firstControl:{x:n-32,y:i-8},lastPoint:l,lastControl:{x:o+32,y:r}}:"south"===c?{firstPoint:p,firstControl:{x:n-8,y:i+32},lastPoint:l,lastControl:{x:o,y:r-32}}:"east"===c?{firstPoint:p,firstControl:{x:n+32,y:i-8},lastPoint:l,lastControl:{x:o-32,y:r}}:{firstPoint:p,firstControl:{x:n-8,y:i-32},lastPoint:l,lastControl:{x:o,y:r+32}}:"west"===c?{firstPoint:p,firstControl:{x:n-32,y:i+8},lastPoint:l,lastControl:{x:o+32,y:r}}:"south"===c?{firstPoint:p,firstControl:{x:n+8,y:i+32},lastPoint:l,lastControl:{x:o,y:r-32}}:"east"===c?{firstPoint:p,firstControl:{x:n+32,y:i+8},lastPoint:l,lastControl:{x:o-32,y:r}}:{firstPoint:p,firstControl:{x:n+8,y:i-32},lastPoint:l,lastControl:{x:o,y:r+32}}:{firstPoint:p,firstControl:{x:n+(o-n)/2,y:i},lastPoint:l,lastControl:{x:n+(o-n)/2,y:r}}},ut=async(t,e,n)=>{const{pos1:o,pos2:i,firstSet:r=!1,direction:s}=n,{x1:a,y1:c,x2:p,y2:l}=await dt(t,e,o,i);let d=0,h=0;"north"===s?h=8:"west"===s?d=8:"east"===s?d=-8:"south"===s&&(h=-8);const{firstPoint:u,firstControl:f,lastControl:g,lastPoint:m}=ht({x1:a+0,x2:p+d,y1:c+0+document.documentElement.scrollTop,y2:l+h+document.documentElement.scrollTop},{direct:!0,firstSet:r,direction:s});return`M ${u.x} ${u.y}C ${f.x} ${f.y}, ${g.x} ${g.y}, ${m.x} ${m.y}`},ft=async({start:t,stop:e,crude:n=!1})=>{const{x1:r,y1:s,x2:a,y2:c}=await dt(t,e),p=((t,e,n,r,s=!0)=>{if(i(t)||i(e)||i(n)||i(r))throw new SyntaxError("Missing input for `angle`");if(o(t)||o(e)||o(n)||o(r))throw TypeError(`Parameters for \`angle\` do not have the required type. Requires number! Got: ${typeof t} ${typeof e} ${typeof n} ${typeof r}`);const a=r-e,c=n-t;let p=Math.atan2(a,c);return p*=180/Math.PI,s&&p<0&&(p+=360),p})(r,s,a,c);return n?(t=>{if(t>360)throw new RangeError("Parameter cannot exceed 360");if(t<0)throw new RangeError("Parameter cannot be lower than 0");return t>=45&&t<=135?"south":t>135&&t<=225?"west":t>225&&t<=315?"north":"east"})(p):(t=>{if(t>360)throw new RangeError("Parameter cannot exceed 360");if(t<0)throw new RangeError("Parameter cannot be lower than 0");return t>=0&&t<=22.5?"east":t>=22.5&&t<=67.5?"south-east":t>=67.5&&t<=112.5?"south":t>=112.5&&t<=157.5?"south-west":t>=157.5&&t<=202.5?"west":t>=202.5&&t<=247.5?"north-west":t>=247.5&&t<=292.5?"north":t>=292.5&&t<=337.5?"north-east":"east"})(p)};class gt{#t;#n;startElement;stopElement;firstPathElement;secondPathElement;constructor(t,e){this.#e(t,e)}#e(t,e){if(!t||!e)throw Error("Missing inputs startElement and stopElement");if(!document.body.contains(e))throw Error("stopElement is not in the DOM");if(!document.body.contains(t))throw Error("startElement is not in the DOM");if(this.startElement=t,this.stopElement=e,this.#t=document.getElementById("ph-speccer-svg"),this.#n=document.getElementById("ph-speccer-path"),!this.#n||!this.#t)throw Error("Missing required SVG element to draw lines. Please see the documentation");const n=et();_(this.#t,{height:`${n}px`}),this.connect()}connect(){this.draw(this.#n)}#o(t){if(!t)throw Error("No path given to #getPathElement!");const e=`ph_draw_path-path-${M()}`,n=t.cloneNode(!1),o=this.startElement.getAttribute("id")||M();return this.startElement.setAttribute("id",o),n.setAttribute("data-start-el",o),n.setAttribute("id",e),n.classList.remove("original"),n.classList.add("speccer"),n}async draw(t){if(!t)throw Error("No path given to draw!");const e=this.#o(t),n=this.#o(t);if(!t.parentNode)throw Error("No parentNode found for path");this.firstPathElement=t.parentNode.insertBefore(e,t.nextSibling),this.secondPathElement=t.parentNode.insertBefore(n,t.nextSibling);const o=await ft({stop:this.stopElement,start:this.startElement,crude:!0}),{path1pos1:i,path1pos2:r,path2pos1:s,path2pos2:a}=(t=>{let e,n,o,i;switch(t){case"east":e="right-top",n="left-center",o="right-bottom",i="left-center";break;case"south":e="bottom-left",n="top-center",o="bottom-right",i="top-center";break;case"west":e="left-top",n="right-center",o="left-bottom",i="right-center";break;default:e="top-left",n="bottom-center",o="top-right",i="bottom-center"}return{path1pos1:e,path1pos2:n,path2pos1:o,path2pos2:i}})(o),c=await ut(this.startElement,this.stopElement,{pos1:i,pos2:r,firstSet:!0,direction:o}),p=await ut(this.startElement,this.stopElement,{pos1:s,pos2:a,direction:o});this.firstPathElement.setAttribute("data-direction",o),this.firstPathElement.setAttribute("data-pos1",i),this.firstPathElement.setAttribute("data-pos2",r),this.firstPathElement.setAttribute("d",c),this.secondPathElement.setAttribute("data-direction",o),this.secondPathElement.setAttribute("data-pos1",s),this.secondPathElement.setAttribute("data-pos2",a),this.secondPathElement.setAttribute("d",p)}}window.DrawSVGCurlyBracket=gt;class mt{#t;#n;startElement;stopElement;options;line;constructor(t,e,n={}){this.#e(t,e,n)}#e(t,e,n={}){if(!t||!e)throw Error("Missing inputs startElement and stopElement");if(!document.body.contains(e))throw Error("stopElement is not in the DOM");if(!document.body.contains(t))throw Error("startElement is not in the DOM");if(this.startElement=t,this.stopElement=e,this.options=n,this.#t=document.getElementById("ph-speccer-svg"),this.#n=document.getElementById("ph-speccer-path"),!this.#n||!this.#t)throw Error("Missing required SVG element to draw lines. Please see the documentation");const o=et();_(this.#t,{height:`${o}px`}),this.connect()}connect(){this.draw(this.#n)}async draw(t){if(!t)throw Error("No path given to draw!");const e=`ph_draw_path-path-${M()}`,n=t.cloneNode(!1),o=this.startElement.getAttribute("id")||M();this.startElement.setAttribute("id",o),n.setAttribute("id",e),n.setAttribute("data-start-el",o),n.classList.remove("original"),n.classList.add("speccer");const{pin:i}=this.options;if(i?.text&&n.classList.add("text"),!t.parentNode)throw Error("No parentNode found for path");this.line=t.parentNode.insertBefore(n,t.nextSibling);const r=await ft({start:this.startElement,stop:this.stopElement,crude:!0}),{pos1:s,pos2:a}=(t=>{let e,n;switch(t){case"east":e="right",n="left";break;case"south":e="bottom",n="top";break;case"west":e="left",n="right";break;default:e="top",n="bottom"}return{pos1:e,pos2:n}})(r),c=await(async(t,e,n)=>{const{pos1:o,pos2:i}=n,{x1:r,y1:s,x2:a,y2:c}=await dt(t,e,o,i),{firstPoint:p,firstControl:l,lastControl:d,lastPoint:h}=ht({x1:r,x2:a,y1:s+document.documentElement.scrollTop,y2:c+document.documentElement.scrollTop},{direction:""});return`M ${p.x} ${p.y}C ${l.x} ${l.y}, ${d.x} ${d.y}, ${h.x} ${h.y}`})(this.startElement,this.stopElement,{pos1:s,pos2:a});this.line.setAttribute("data-direction",r),this.line.setAttribute("data-pos1",s),this.line.setAttribute("data-pos2",a),this.line.setAttribute("d",c)}}window.DrawSVGLine=mt;const yt=t=>parseInt(t,10),wt=t=>yt(getComputedStyle(t).getPropertyValue("--ph-speccer-pin-space"))||48,bt=async(t,e,n,o)=>{await V();const{pin:i={},position:r}=o,{useCurlyBrackets:s,subtle:a,bracket:c,text:p,parent:l,enclose:d}=i,h=wt(e),u=yt(getComputedStyle(e).getPropertyValue("--ph-speccer-measure-size"))||8;const f=await F(e,t);if(d){const{left:t,top:e,height:n,width:o}=f.absolute();return{left:`${t}px`,top:`${e}px`,height:`${n}px`,width:`${o}px`}}if((l||p)&&!c&&!s&&!a){if(r===m.Right){const{top:t}=f.fromRight({center:!0});await V();const{left:e,width:o}=n.getBoundingClientRect();return{left:`${e+o+h}px`,top:`${t}px`}}if(r===m.Bottom){const{left:t}=f.toBottom({center:!0});await V();const{top:e,height:o}=n.getBoundingClientRect();return{left:`${t}px`,top:`${e+o+h}px`}}if(r===m.Left){const{top:t}=f.fromLeft({center:!0});await V();const{left:e}=n.getBoundingClientRect();return{left:e-1.5*h-(p?170:0)+"px",top:`${t}px`}}const{left:t}=f.fromTop({center:!0});await V();const{top:e}=n.getBoundingClientRect();return{left:`${t}px`,top:e-1.5*h+"px"}}if(r===m.Left){if(c&&!s){const{left:t,top:e,height:n}=f.fromLeft({sourceWidth:u});return{left:`${t}px`,top:`${e}px`,height:`${n}px`}}const{left:t,top:e}=f.fromLeft({center:!0,modifier:s?h/1.5:h});return{left:`${t}px`,top:`${e}px`}}if(r===m.Right){if(c&&!s){const{left:t,top:e,height:n}=f.fromRight({center:!1});return{left:`${t}px`,top:`${e}px`,height:`${n}px`}}const{left:t,top:e}=f.fromRight({center:!0,modifier:s?h/1.5:h});return{left:`${t}px`,top:`${e}px`}}if(r===m.Bottom){if(c&&!s){const{left:t,top:e,width:n}=f.fromBottom({center:!1});return{left:`${t}px`,top:`${e}px`,width:`${n}px`}}const{left:t,top:e}=f.fromBottom({center:!0,modifier:s?h/1.5:h});return{left:`${t}px`,top:`${e}px`}}if(c&&!s){const{left:t,top:e,width:n}=f.fromTop({center:!1});return{left:`${t}px`,top:`${e}px`,width:`${n}px`}}const{left:g,top:y}=f.fromTop({center:!0,modifier:s?h/1.5:h});return{left:`${g}px`,top:`${y}px`}},xt=async(t,e,n,o)=>{if("pin"!==o.type||!o.pin)return;const i=`speccer-${o.slug}-${t.getAttribute("id")||M()}`,r=tt(n,o,i);t.setAttribute("data-speccer-element-id",i),document.body.appendChild(r);const s=await bt(t,r,e,o);await _(r,s);const a=o.pin.text&&null!==t.getAttribute("data-speccer-title"),c=o.pin.parent&&!o.pin.enclose&&!o.pin.bracket&&!a;return o.pin.useSVGLine?(new mt(t,r,o),c&&new lt(t,5,o)):o.pin.useCurlyBrackets&&new gt(t,r),i};let $t=0;const Et=async(t,e)=>{if(!t)return;const n=t.querySelectorAll('[data-speccer^="pin"]');if(!n||0===n.length)return;const o=t.getAttribute("data-speccer-literals")||window.SPECCER_LITERALS||a;[...n].filter((async t=>!O(t))).forEach((async(n,i)=>{const r=((t,e)=>{let n=e[t];return 0===t&&($t=0),n||(n=`${e[$t]}${e[$t].toLowerCase()}`,$t++),n})(i,o),s=n.getAttribute("data-speccer")||"";await V();const a=getComputedStyle(n),c=I(s,a,e),p=((t,e,n)=>{const{pin:o}=n;if(!o)return t;const{text:i}=o;if(!i||null===e.getAttribute("data-speccer-title"))return t;const r=e.getAttribute("data-speccer-title"),s=e.getAttribute("data-speccer-description"),a=0===e.nodeName.indexOf("H")?`<span class="ph-speccer heading">${e.nodeName}</span>`:"";return!s&&r?`${a}<span class="ph-speccer title">${r}</span>`:s&&r?`${a}<span class="ph-speccer title">${r}</span><span class="ph-speccer description">${s.replaceAll("\\n","<br/>")}</span>`:t})(r,n,c);await xt(n,t,p,c)}))},At=(t="",e="span")=>{const n=document.createElement(e),o=document.createTextNode(`${t}px`);return n.appendChild(o),n.setAttribute("title",`${t}px`),r(n,"ph-speccer speccer spacing"),n},St=async(t,e)=>{if(!t)return;if(O(t))return;const n=t.getAttribute("data-speccer")||"",o=await X(t),i=I(n,o,e);if("spacing"!==i.type||!i.spacing)return;const a=((t,e)=>{const{marginTop:n,marginBottom:o,marginLeft:i,marginRight:r,paddingTop:s,paddingBottom:a,paddingLeft:c,paddingRight:p}=t;return e?.spacing?.padding?{paddingTop:s,paddingBottom:a,paddingLeft:c,paddingRight:p}:e?.spacing?.margin?{marginTop:n,marginBottom:o,marginLeft:i,marginRight:r}:{marginTop:n,marginBottom:o,marginLeft:i,marginRight:r,paddingTop:s,paddingBottom:a,paddingLeft:c,paddingRight:p}})(o,i),c=Object.keys(a).filter((t=>"0px"!==a[t]));if(!c.length)return;t.classList.add("is-specced");const p=`speccer-spacing-${t.getAttribute("id")||M()}`;t.setAttribute("data-speccer-element-id",p),c.forEach((async e=>{const n=yt(a[e]),o=At(n);o.setAttribute("data-speccer-id",p);const c=(t=>t.includes("Top")?t.replace("Top"," top"):t.includes("Right")?t.replace("Right"," right"):t.includes("Bottom")?t.replace("Bottom"," bottom"):t.includes("Left")?t.replace("Left"," left"):"")(e);r(o,s(c,{bound:!!i?.spacing?.bound})),document.body.appendChild(o);const l=await(async(t,e,n,o)=>{await V();const i=n.getBoundingClientRect(),r=await D(n),s=o?.spacing?.bound?0:96,a=o?.spacing?.bound?0:48;return"marginTop"===t?{height:`${e}px`,width:i.width+s+"px",left:r.left-s+"px",top:r.top-e+"px"}:"marginRight"===t?{height:i.height+a+"px",width:`${e}px`,left:r.left+parseInt(i.width+"",10)+"px",top:r.top+"px"}:"marginBottom"===t?{height:`${e}px`,width:i.width+s+"px",left:r.left-s+"px",top:r.top+parseInt(i.height+"",10)+"px"}:"marginLeft"===t?{height:i.height+a+"px",width:`${e}px`,left:r.left-e+"px",top:r.top+"px"}:"paddingTop"===t?{height:`${e}px`,width:i.width+s+"px",left:r.left-s+"px",top:r.top+"px"}:"paddingBottom"===t?{height:`${e}px`,width:i.width+s+"px",left:r.left-s+"px",top:r.top+(parseInt(i.height+"",10)-e)+"px"}:"paddingRight"===t?{height:i.height+a+"px",width:`${e}px`,left:r.left+(parseInt(i.width+"",10)-e)+"px",top:r.top+"px"}:"paddingLeft"===t?{height:i.height+a+"px",width:`${e}px`,left:r.left+"px",top:r.top+"px"}:void 0})(e,n,t,i);await _(o,l)}))},Ct=(t,e=3)=>parseFloat(String(t)).toFixed(e),kt=(t,e,n)=>{const o=document.createElement("div"),{typography:i,position:a}=e,c=s("ph-speccer speccer typography",{syntax:i?.useSyntaxHighlighting||!1,[a]:!0});return o.setAttribute("id",n),o.setAttribute("data-speccer-id",n),o.innerHTML=t,r(o,c),o},vt=async(t,e)=>{if(!t)return;if(O(t))return;const n=t.getAttribute("data-speccer")||"";await V();const o=I(n,getComputedStyle(t),e);if("typography"!==o.type||!o.typography)return;t.classList.add("is-specced");const i=await(async(t,e=!1)=>{const n=(t=>{const{lineHeight:e,letterSpacing:n,fontFamily:o,fontSize:i,fontStyle:r,fontVariationSettings:s,fontWeight:a}=t;return{lineHeight:e,letterSpacing:n,fontFamily:o,fontSize:i,fontStyle:r,fontVariationSettings:s,fontWeight:a}})(await X(t));if(e){const t=(n.fontFamily||"").split(",").map((t=>t.includes('"\'"')?`<span class="token string">${t}</span>`:t)).join('<span class="token punctuation">, </span>'),e=`<span class="token number">${parseInt(n.fontSize||"NaN",10)}</span><span class="token unit">px</span> <span class="token operator">/</span> <span class="token number">${parseInt(n.fontSize||"NaN",10)/16}</span><span class="token unit">rem</span>`,o=n.letterSpacing?n.letterSpacing.includes("px")?`<span class="token number">${parseInt(n.letterSpacing,10)}</span><span class="token unit">px</span>`:n.letterSpacing:"",i=n.lineHeight?"normal"!==n.lineHeight?`<span class="token number">${parseInt(n.lineHeight,10)}</span><span class="token unit">px</span> <span class="token operator">/</span> <span class="token number">${parseInt(n.lineHeight,10)/16}</span><span class="token unit">rem</span>`:"normal":"";return`\n<pre class="language-css" tabindex="-1"><code class="language-css"><span class="token selector"><span class="token class">.typography</span></span> <span class="token punctuation">{</span>\n <span class="token property">font-family</span><span class="token punctuation">:</span> ${t}<span class="token punctuation">;</span>\n <span class="token property">font-size</span><span class="token punctuation">:</span> ${e}<span class="token punctuation">;</span>\n <span class="token property">font-weight</span><span class="token punctuation">:</span> <span class="token number">${n.fontWeight}</span><span class="token punctuation">;</span>\n <span class="token property">font-variation-settings</span><span class="token punctuation">:</span> ${n.fontVariationSettings}<span class="token punctuation">;</span>\n <span class="token property">line-height</span><span class="token punctuation">:</span> ${i}<span class="token punctuation">;</span>\n <span class="token property">letter-spacing</span><span class="token punctuation">:</span> ${o}<span class="token punctuation">;</span>\n <span class="token property">font-style</span><span class="token punctuation">:</span> ${n.fontStyle}<span class="token punctuation">;</span>\n<span class="token punctuation">}</span></code></pre>`}return`\ntypography: {<ul class="speccer-styles"> <li><span class="property">font-family:</span> ${n.fontFamily};</li> <li><span class="property">font-size:</span> ${n.fontSize} / ${parseInt(n.fontSize||"NaN",10)/16}rem;</li> <li><span class="property">font-weight:</span> ${n.fontWeight};</li> <li><span class="property">font-variation-settings:</span> ${n.fontVariationSettings};</li> <li><span class="property">line-height:</span> ${"normal"!==n.lineHeight?`${parseInt(n.lineHeight||"NaN",10)}px / ${parseInt(n.lineHeight||"NaN",10)/16}rem`:"normal"};</li> <li><span class="property">letter-spacing:</span> ${n.letterSpacing};</li> <li><span class="property">font-style:</span> ${n.fontStyle};</li></ul>}`})(t,o.typography.useSyntaxHighlighting),r=`speccer-${o.slug}-${t.getAttribute("id")||M()}`;t.setAttribute("data-speccer-element-id",r);const s=kt(i,o,r);document.body.appendChild(s);const a=await(async(t,e,n)=>{const o=e.getBoundingClientRect(),i=wt(n),r=n.getBoundingClientRect(),s=await D(e),{typography:a,position:c}=t;if(a&&c===w.Right)return{left:s.left+o.width+i+"px",top:Ct(W(s.top,r,o))+"px"};if(a&&c===w.Top)return{left:Ct(j(s.left,r,o))+"px",top:s.top-r.height-i+"px"};if(a&&c===w.Bottom)return{left:Ct(j(s.left,r,o))+"px",top:s.top+o.height+i+"px"};return{left:s.left-r.width-i+"px",top:Ct(W(s.top,r,o))+"px"}})(o,t,s);_(s,a)},Pt=t=>{const e=()=>((t,e,n=!1)=>{let o;return function(i,...r){const s=n&&!o;o&&clearTimeout(o),o=setTimeout((function(){o=null,n||t.apply(i,r)}),e),s&&t.apply(i,r)}})((()=>{t()}),300);window.removeEventListener("resize",e),window.addEventListener("resize",e)},Lt=t=>{"loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>{t()})):t()},Bt=()=>{const t=new IntersectionObserver(((t,e)=>{for(const n of t)n.intersectionRatio>0&&(St(n.target),e.unobserve(n.target))}));for(const e of document.querySelectorAll(`[${c}^="${p}"],[${c}^="${p}"] *:not(td):not(tr):not(th):not(tfoot):not(thead):not(tbody)`))t.observe(e);const e=new IntersectionObserver(((t,e)=>{for(const n of t)n.intersectionRatio>0&&(Q(n.target),e.unobserve(n.target))}));for(const t of document.querySelectorAll(`[${c}^="${l}"]`))e.observe(t);const n=new IntersectionObserver(((t,e)=>{for(const n of t)n.intersectionRatio>0&&(Z(n.target),e.unobserve(n.target))}));for(const t of document.querySelectorAll(`[${c}^="${h}"]`))n.observe(t);const o=new IntersectionObserver(((t,e)=>{for(const n of t)n.intersectionRatio>0&&(vt(n.target),e.unobserve(n.target))}));for(const t of document.querySelectorAll(`[${c}^="${d}"]`))o.observe(t);const i=new IntersectionObserver(((t,e)=>{for(const n of t)n.intersectionRatio>0&&(K(n.target),e.unobserve(n.target))}));for(const t of document.querySelectorAll(`[${c}^="${u}"]`))i.observe(t);const r=new IntersectionObserver((async(t,e)=>{for(const n of t)n.intersectionRatio>0&&(await Et(n.target),e.unobserve(n.target))}));for(const t of document.querySelectorAll(`[${c}="${f}"]`))r.observe(t)},Rt=t=>{window.speccer=t},Tt=t=>{const e=document.currentScript;if(e){const n=e.getAttribute("src");n?.includes("speccer.js")&&(e.hasAttribute("data-manual")?Rt(t):e.hasAttribute("data-instant")?t():e.hasAttribute("data-dom")?Lt(t):e.hasAttribute("data-lazy")?Bt():Lt(t),e.hasAttribute("data-manual")||e.hasAttribute("data-lazy")||Pt(t))}},Nt=["alt","altgraph","capslock","control","fn","fnlock","hyper","meta","numlock","os","scrolllock","shift","super","symbol","command","ctrl","altgr","symbollock"],qt=["escape","esc","enter","return","⏎","␛"],Ht=async(t,e,n)=>{await V();const o=wt(n),i=await F(n,e);if("tabstops"===t){let{left:t,top:e}=i.fromTop();return t-=32,e+=32,t<=0&&(t=32),e<=0&&(e=32),{left:`${t}px`,top:`${e}px`}}if("landmark"===t||"autocomplete"===t||"headings"===t){let{left:t,top:e}=i.fromLeft();return t-=o,t<=0&&(t=o),e<=0&&(e=o),{left:`${t}px`,top:`${e}px`}}if("region"===t){const{left:t,top:e,height:n,width:o}=i.fromTop();return{height:`${n}px`,width:`${o}px`,left:`${t}px`,top:`${e}px`}}if("shortcut"===t){const{left:t,top:e}=i.fromBottom();return{left:`${t}px`,top:`${e}px`}}const{left:r,top:s}=i.fromTop({center:!0,modifier:o});return{left:r-32+"px",top:s-32+"px"}},It=async(t,e,n)=>{if(!t||!t.checkVisibility())return;const o=((t="tabstops",e,n="span")=>{const o=document.createElement(n),i=s("ph-speccer speccer a11y",{tabstops:"tabstops"===t,landmark:"landmark"===t,autocomplete:"autocomplete"===t,headings:"headings"===t,region:"region"===t});if("landmark"===t&&e){const t=document.createTextNode(String(e));o.appendChild(t)}return r(o,i),o})(n,e);if("landmark"===n){const e=(t=>{if(!t)return"";if(t.role&&""!==t.role)return t.role;const e=t.nodeName.toLowerCase();return["header","footer","section","form","main","nav","aside"].includes(e)?e:"N/A"})(t),n=t.nodeName.toLowerCase();o.innerHTML=`<${n} role="${e}">`}if("autocomplete"===n){const e=t.getAttribute("autocomplete")||"";o.innerHTML=`autocomplete="${e}"`}"headings"===n&&(o.innerHTML=t.nodeName,o.classList.add(t.nodeName.toLowerCase())),"tabstops"===n&&o.setAttribute("data-speccer-a11y-tabstops",e);const i=`speccer-a11y-${t.getAttribute("id")||M()}`;o.setAttribute("data-speccer-id",i),document.body.appendChild(o);const a=await Ht(n,t,o);await _(o,a)},Mt=async(t,e)=>{const n=e.split(/\s\+\s/).map((t=>t.trim())),o=document.createElement("div"),i=s("ph-speccer speccer a11y shortcut-holder");r(o,i);for(const t of n){const e=document.createElement("kbd"),n=document.createTextNode(t),i=s("ph-speccer speccer a11y shortcut",{modifier:Nt.includes(t.toLowerCase()),physical:qt.includes(t.toLowerCase())});r(e,i),e.appendChild(n);const a=`speccer-a11y-shortcut-${M()}`;o.setAttribute("data-speccer-id",a),o.appendChild(e)}document.body.appendChild(o);const a=await Ht("shortcut",t,o);await _(o,a)},Ot=()=>{const t=document.querySelectorAll('[data-speccer*="a11y tabstops"]'),e=document.querySelectorAll('[data-speccer*="a11y landmark"]'),n=document.querySelectorAll('[data-speccer*="a11y shortcut"]'),o=document.querySelectorAll('[data-speccer*="a11y autocomplete"]'),i=document.querySelectorAll('[data-speccer*="a11y headings"]');if(n.length)for(const t of n){const e=t.getAttribute("data-speccer-a11y-shortcut");e&&""!==e&&!O(t)&&Mt(t,e)}if(t.length)for(const e of t){const t=e.querySelectorAll("\n a[href], area[href], input:not([disabled]):not([tabindex='-1']),\n button:not([disabled]):not([tabindex='-1']),select:not([disabled]):not([tabindex='-1']),\n textarea:not([disabled]):not([tabindex='-1']),\n iframe, object, embed, *[tabindex]:not([tabindex='-1']), *[contenteditable=true]\n");for(const[e,n]of t.entries()){if(!O(n)){It(n,e+1,"tabstops");continue}const t=n.getAttribute("id");if(!t)continue;const o=document.querySelector(`[for="${t}"]`);o&&!O(o)&&It(o,e+1,"tabstops")}}if(o.length)for(const t of o){const e=t.querySelectorAll("[autocomplete]");for(const t of e)O(t)||It(t,null,"autocomplete")}if(i.length)for(const t of i){const e=t.querySelectorAll('h1,h2,h3,h4,h5,h6, [role="heading"]');for(const t of e)O(t)||It(t,null,"headings")}if(e.length)for(const t of e){const e=t.querySelectorAll('\nheader, footer, section, form, main, nav, aside, [role="section"], [role="banner"],\n[role="complementary"], [role="contentinfo"], [role="form"], [role="main"],\n[role="navigation"], [role="region"], [role="search"]\n');for(const[t,n]of e.entries())O(n)||(It(n,t+1,"landmark"),It(n,null,"region"))}},Vt=t=>{const e=t.getAttribute("data-speccer-element-id");if(!e)return;const n=document.getElementById(e)||document.querySelectorAll(`[data-speccer-id="${e}"]`);if(n)if(Object.prototype.isPrototypeOf.call(NodeList.prototype,n))[...n].forEach((t=>t.remove()));else if(n.classList.contains("curly")||n.classList.contains("svg")){const e=t.getAttribute("id");document.querySelectorAll(`#ph-speccer-svg path[data-start-el="${e}"]`).forEach((t=>t.remove()))}},zt={create:Y,element:K},Gt={create:At,element:St},jt={createPinElement:tt,pinElement:xt,pinElements:Et},Wt={create:J,element:Q},Dt={create:U,element:Z},Ft={create:kt,element:vt},_t={dom:Lt,lazy:Bt,manual:Rt,activate:Tt},Xt=()=>{((t,e=document)=>{[].forEach.call(e.querySelectorAll(t),(function(t){t.remove()}))})(".ph-speccer.speccer");const t=document.querySelectorAll(`[${c}^="${p}"]`),e=document.querySelectorAll(`[${c}^="${l}"]`),n=document.querySelectorAll(`[${c}^="${d}"]`),o=document.querySelectorAll(`[${c}="${f}"]`),i=document.querySelectorAll(`[${c}^="${h}"]`),r=document.querySelectorAll(`[${c}^="${u}"]`);for(const t of i)Z(t);for(const t of r)K(t);for(const e of t)if(St(e),e.hasChildNodes()){const t=e.querySelectorAll("*:not(td):not(tr):not(th):not(tfoot):not(thead):not(tbody):not([data-speccer])"),n=e.getAttribute("data-speccer")||"";if(t?.length)for(const e of t)e.setAttribute("data-speccer",n),St(e)}for(const t of e)Q(t);for(const t of n)vt(t);for(const t of o)Et(t);Ot()};Tt(Xt);export{Ot as a11y,Xt as default,zt as grid,Dt as mark,Wt as measure,_t as modes,jt as pin,Vt as removeSpeccerElement,Gt as spacing,Ft as typography};
|
package/dist/speccer.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @phun-ky/speccer
|
|
3
3
|
* A script to annotate, show spacing specs and to display typography information in documentation/website on HTML elements
|
|
4
4
|
* @author Alexander Vassbotn Røyne-Helgesen <alexander@phun-ky.net>
|
|
5
|
-
* @version 11.
|
|
5
|
+
* @version 11.3.0
|
|
6
6
|
* @license
|
|
7
7
|
* Copyright (c) 2018-2025 Alexander Vassbotn Røyne-Helgesen
|
|
8
8
|
*
|
|
@@ -24,4 +24,4 @@
|
|
|
24
24
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
25
|
* SOFTWARE.
|
|
26
26
|
*/
|
|
27
|
-
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).speccer={})}(this,(function(t){"use strict";const e=t=>"string"==typeof t,n=t=>!e(t),o=t=>"number"==typeof t,i=t=>!o(t),r=t=>void 0===t,s=(t,e,n="noop")=>{if(!t)return;if(!e||e&&!e.length)return;const o=e.trim().split(" ").filter((t=>t!==n)).filter((t=>""!==t)).map((t=>t.trim()));t.classList.add(...o)},a=(t,e)=>t?!e&&n(t)?Object.keys(t).filter((e=>t[e])).join(" ").trim():`${t.trim()} ${e?Object.keys(e).filter((t=>e[t])).join(" "):""}`.trim():"",c=[..."ABCDEFGHIJKLMNOPQRSTUVWXYZ"],p="data-speccer",l="spacing",d="measure",h="typography",u="mark",f="grid",g="pin-area";var m,y,w,b,x,$,E;!function(t){t.Empty="",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top"}(m||(m={})),function(t){t.Pin="pin",t.Parent="parent",t.Text="text",t.Enclose="enclose",t.Subtle="subtle",t.Bracket="bracket",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top",t.SVG="svg",t.Curly="curly"}(y||(y={})),function(t){t.Measure="measure",t.Slim="slim",t.Width="width",t.Height="height",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top"}(w||(w={})),function(t){t.Typography="typography",t.Syntax="syntax",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top"}(b||(b={})),function(t){t.Spacing="spacing"}(x||(x={})),function(t){t.Mark="mark"}($||($={})),function(t){t.Grid="grid"}(E||(E={}));const A=t=>t.split(" "),S=t=>{if(null===t)return!1;return A(t).includes(y.Bracket)},C=t=>{if(null===t)return!1;return A(t).includes(y.Enclose)},k=t=>{if(null===t)return!1;return A(t).includes(y.Subtle)},v=t=>{if(null===t)return!1;return A(t).includes(y.Parent)},P=t=>{if(null===t)return!1;return A(t).includes(y.Text)},L=t=>{if(null===t)return!1;return A(t).includes(w.Height)},B=t=>{if(null===t)return!1;return A(t).includes(w.Slim)},R=t=>{if(null===t)return!1;return A(t).includes(w.Width)},T=t=>{if(null===t)return!1;const e=A(t);return(v(t)&&!C(t)&&!S(t)||P(t)||e.includes(y.SVG))&&!N(t)},N=t=>{if(null===t)return!1;const e=A(t);return e.includes(y.Curly)&&e.includes(y.Bracket)},q=t=>!!t&&t.split(" ").includes(b.Syntax),M=(t,n)=>(t=>null!==t&&t.split(" ").includes(y.Pin))(t)?"pin":((t,n)=>null!==t&&t.split(" ").includes(E.Grid)&&e(n.display)&&("grid"===n.display||(n.display||"").includes("grid")))(t,n)?"grid":(t=>null!==t&&t.split(" ").includes($.Mark))(t)?"mark":(t=>null!==t&&t.split(" ").includes(w.Measure))(t)?"measure":(t=>null!==t&&t.split(" ").includes(x.Spacing))(t)?"spacing":(t=>null!==t&&t.split(" ").includes(b.Typography))(t)?"typography":"pin",H=t=>(t=>null!==t&&A(t).includes(y.Left))(t)?"left":(t=>null!==t&&A(t).includes(y.Right))(t)?"right":(t=>null!==t&&A(t).includes(y.Bottom))(t)?"bottom":"top",I=(t,e,n)=>{const o=M(t,e),i={slug:(r=t,r.normalize("NFKD").replace(/[\u0300-\u036f]/g,"").trim().toLowerCase().replace(/[^a-z0-9 -]/g,"").replace(/\s+/g," ").replace(/(?:^\w|[A-Z]|\b\w)/g,((t,e)=>0===e?t.toLowerCase():t.toUpperCase())).replace(/\s+/g,"")),position:H(t),type:o};var r;if("pin"===o&&(i.pin={bracket:S(t),enclose:C(t),subtle:k(t),parent:v(t),text:P(t),useSVGLine:T(t),useCurlyBrackets:N(t)}),"measure"===o&&(i.measure={slim:B(t),height:L(t),width:R(t)}),"typography"===o&&(i.typography={useSyntaxHighlighting:q(t)}),"grid"===o){const e=(t=>t?.includes("columns")?"columns":t?.includes("rows")?"rows":"both")(t);i.grid={toggle:e,both:"both"===e,rows:"rows"===e,columns:"columns"===e}}if("spacing"===o){const e=(t=>t?.includes("margin")?"margin":t?.includes("padding")?"padding":"both")(t);i.spacing={both:"both"===e,margin:"margin"===e,padding:"padding"===e,bound:t.includes("bound")}}return{...i,...n}},O=()=>"_"+Math.random().toString(36).substring(2,11),V=t=>!t.checkVisibility({opacityProperty:!0,checkVisibilityCSS:!0}),z=()=>new Promise(requestAnimationFrame),G=async(t,e,n)=>{await z();return getComputedStyle(t)[e]===n},j=async(t,e,n)=>{if(!t.parentElement)return null;return await G(t.parentElement,e,n)?t.parentElement:await j(t.parentElement,e,n)},W=(t,e,n)=>t-e.width/2+n.width/2,D=(t,e,n)=>t-e.height/2+n.height/2,F=async t=>{await z();let e=t.getBoundingClientRect(),n=e.top+window.scrollY;const o=e.left+window.scrollX,i=await(async t=>await j(t,"position","sticky"))(t);if(await(async t=>await G(t,"position","sticky"))(t)){const o=t.style.position;await z(),t.style.position="relative",await z(),e=t.getBoundingClientRect(),n=e.top,await z(),t.style.position=o}else if(i){const o=i.style.position;await z(),i.style.position="relative",await z(),e=t.getBoundingClientRect(),n=e.top,await z(),i.style.position=o}return{height:e.height,width:e.width,top:n,left:o}},_=async(t,e)=>{await z();const n=t.getBoundingClientRect(),o=await F(e),i=await(async(t,e)=>{await z();const n=t.getBoundingClientRect();await z();const o=e.getBoundingClientRect(),i=o.top+window.scrollY,r=o.left+window.scrollX;return{height:o.height,width:o.width,top:D(i,n,o),left:W(r,n,o)}})(t,e),r=o.height,s=o.width,a=n.height,c=n.width;return{absolute:()=>({top:o.top,left:o.left,height:r,width:s}),toTop:({center:t=!1,sourceHeight:e=a,modifier:n=0}={})=>({top:o.top+e+n,left:t?i.left:o.left,height:r,width:s}),fromTop:({center:t=!1,sourceHeight:e=a,modifier:n=0}={})=>({top:o.top-e-n,left:t?i.left:o.left,height:r,width:s}),toBottom:({center:t=!1,sourceHeight:e=a,targetHeight:n=r,modifier:c=0}={})=>({top:o.top+n-(e+c),left:t?i.left:o.left,height:r,width:s}),fromBottom:({center:t=!1,targetHeight:e=r,modifier:n=0}={})=>({top:o.top+e+n,left:t?i.left:o.left,height:r,width:s}),toLeft:({center:t=!1,sourceWidth:e=c,modifier:n=0}={})=>({top:t?i.top:o.top,left:o.left+e+n,height:r,width:s}),fromLeft:({center:t=!1,sourceWidth:e=c,modifier:n=0}={})=>({top:t?i.top:o.top,left:o.left-e-n,height:r,width:s}),toRight:({center:t=!1,sourceWidth:e=c,targetWidth:n=s,modifier:a=0}={})=>({top:t?i.top:o.top,left:o.left+n-(e+a),height:r,width:s}),fromRight:({center:t=!1,targetWidth:e=s,modifier:n=0}={})=>({top:t?i.top:o.top,left:o.left+e+n,height:r,width:s})}},X=async(t,n)=>{var i;!t||!n||e(n)||o(n)||(i=n,"boolean"==typeof i)||Array.isArray(n)&&!n.length||!Object.keys(n).length&&n.constructor===Object||(await z(),Array.isArray(n)&&(n=n.reduce(((t,e)=>(t[e.key]=e.value,t)),{})),Object.assign(t.style,n))},Y=async t=>(await z(),getComputedStyle(t,null)),K=async(t,e,n)=>{await z();const{grid:o}=n;if(!o)return;const{toggle:i}=o,{height:r,width:a}=t.getBoundingClientRect(),{top:c,left:p}=await F(t),{gridTemplateColumns:l,gridTemplateRows:d,padding:h}=e,u=`speccer-${n.slug}-${t.getAttribute("id")||O()}`;if(t.setAttribute("data-speccer-element-id",u),"columns"===i||"both"===i){const t=parseInt(e.columnGap||"0"),n=document.createElement("div");document.documentElement.style.setProperty("--ph-speccer-grid-gap-original",`${t}px`),document.documentElement.style.setProperty("--ph-speccer-grid-gap",`${t<24?24:t}px`),t<24&&n.classList.add("speccer-small-grid"),n.setAttribute("data-speccer-id",u),s(n,"ph-speccer speccer speccer-grid-container"),X(n,{height:`${r+64}px`,width:`${a}px`,left:`${p}px`,top:c-32+"px",padding:h,gridTemplateColumns:l});const o=l?.split(" ").length||0;for(let t=0;t<o;t++){const t=document.createElement("div");s(t,"ph-speccer speccer speccer-grid-item"),n.appendChild(t)}document.body.appendChild(n)}if("rows"===i||"both"===i){const t=parseInt(e.rowGap||"0"),n=document.createElement("div");document.documentElement.style.setProperty("--ph-speccer-grid-row-gap-original",`${t}px`),document.documentElement.style.setProperty("--ph-speccer-grid-row-gap",`${t<24?24:t}px`),t<24&&n.classList.add("speccer-small-grid"),n.setAttribute("data-speccer-id",u),n.classList.add("ph-speccer"),n.classList.add("speccer"),n.classList.add("speccer-grid-row-container"),s(n,"ph-speccer speccer speccer-grid-row-container"),X(n,{width:`${a+64}px`,height:`${r}px`,top:`${c}px`,left:p-32+"px",padding:h,gridTemplateRows:d});const o=d?.split(" ").length||0;for(let t=0;t<o;t++){const t=document.createElement("div");s(t,"ph-speccer speccer speccer-grid-row-item"),n.appendChild(t)}document.body.appendChild(n)}},U=async(t,e)=>{if(!t)return;if(V(t))return;const n=t.getAttribute(p)||"",o=await Y(t),i=I(n,o,e);"grid"===i.type&&i.grid&&(await z(),await K(t,o,i))},Z=(t,e="span")=>{const n=document.createElement(e);return n.setAttribute("id",t),s(n,"ph-speccer speccer mark"),n},J=async t=>{if(!t)return;if(V(t))return;const e=t.getAttribute(p)||"";await z();const n=I(e,getComputedStyle(t));if("mark"!==n.type)return;const o=`speccer-${n.slug}-${t.getAttribute("id")||O()}`;t.setAttribute("data-speccer-element-id",o);const i=Z(o);i.setAttribute("data-speccer-id",o),document.body.appendChild(i);const r=await _(i,t),{left:s,top:a,height:c,width:l}=r.absolute(),d={left:`${s}px`,top:`${a}px`,height:`${c}px`,width:`${l}px`};await X(i,d)},Q=(t="",e,n,o="span")=>{const i=document.createElement(o);i.setAttribute("title",`${t}px`),i.setAttribute("id",n),i.setAttribute("data-speccer-id",n),i.setAttribute("data-measure",`${parseInt(String(t),10)}px`);const{measure:r,position:c}=e,p=a("ph-speccer speccer measure",{height:r?.height||!1,width:r?.width||!1,slim:r?.slim||!1,[c]:!0});return s(i,p),i},tt=async(t,e)=>{if(!t)return;if(V(t))return;const n=t.getAttribute("data-speccer")||"";await z();const o=I(n,getComputedStyle(t),e);if("measure"!==o.type||!o.measure)return;const{measure:i,position:r}=o;await z();const s=t.getBoundingClientRect(),a=i.slim?0:48,c=i.slim?0:96,p=`speccer-${o.slug}-${t.getAttribute("id")||O()}`;if(t.setAttribute("data-speccer-element-id",p),i.width)if(r===w.Bottom){const e=Q(s.width,o,p);document.body.appendChild(e);const n=await _(e,t);if(i.slim){const{left:t,top:o,width:i}=n.fromBottom({center:!1});await X(e,{left:`${t}px`,top:`${o}px`,width:`${i}px`})}else{const{left:t,top:o,width:i,height:r}=n.absolute({center:!1});await X(e,{left:`${t}px`,top:`${o}px`,width:`${i}px`,height:`${r+a}px`})}}else{const e=Q(s.width,o,p);document.body.appendChild(e);const n=await _(e,t);if(i.slim){const{left:t,top:o,width:i}=n.fromTop({center:!1});await X(e,{left:`${t}px`,top:`${o}px`,width:`${i}px`})}else{const{left:t,top:o,width:i,height:r}=n.absolute({center:!1});await X(e,{left:`${t}px`,top:o-a+"px",width:`${i}px`,height:`${r+a}px`})}}else if(i.height)if(r===w.Right){const e=Q(s.height,o,p);document.body.appendChild(e);const n=await _(e,t);if(i.slim){const{left:t,top:o,height:i}=n.fromRight({center:!1});await X(e,{left:`${t}px`,top:`${o}px`,height:`${i}px`})}else{const{left:t,top:o,height:i,width:r}=n.absolute({center:!1});await X(e,{left:`${t}px`,top:`${o}px`,height:`${i}px`,width:`${r+c}px`})}}else{const e=Q(s.height,o,p);document.body.appendChild(e);const n=await _(e,t);if(i.slim){const{left:t,top:o,height:i}=n.fromLeft({center:!1});await X(e,{left:`${t}px`,top:`${o}px`,height:`${i}px`})}else{const{left:t,top:o,height:i,width:r}=n.absolute({center:!1});await X(e,{left:t-c+"px",top:`${o}px`,height:`${i}px`,width:`${r+c}px`})}}},et=(t="",e,n="",o="span")=>{const i=document.createElement(o),r={},{position:c,pin:p={}}=e,{useSVGLine:l,useCurlyBrackets:d,text:h,parent:u,bracket:f,enclose:g,subtle:m}=p;r.text=h,r.parent=u,r.bracket=f,r.enclose=g,r.subtle=m,r.svg=l,r.curly=d,r[c]=!0,!u||f||d||m||(r.svg=!0),!f&&!g||f&&d?i.innerHTML=t:(f||g)&&i.setAttribute("data-pin-counter",t);const y=a("ph-speccer speccer pin",r);return s(i,y),i.setAttribute("id",n),i.setAttribute("data-speccer-id",n),i},nt=()=>{const{body:t,documentElement:e}=document;return Math.max(t.scrollHeight,t.offsetHeight,e.clientHeight,e.scrollHeight,e.offsetHeight)},ot=t=>t.top,it=t=>t.left+t.width,rt=t=>t.top+t.height,st=t=>t.left,at=t=>t.left+t.width/2,ct=t=>t.top+t.height/2,pt={center:t=>({x:at(t),y:ct(t)}),top:t=>({x:at(t),y:ot(t)}),right:t=>({x:it(t),y:ct(t)}),bottom:t=>({x:at(t),y:rt(t)}),left:t=>({x:st(t),y:ct(t)}),"right-top":t=>({x:it(t),y:ot(t)}),"right-bottom":t=>({x:it(t),y:rt(t)}),"left-top":t=>({x:st(t),y:ot(t)}),"left-bottom":t=>({x:st(t),y:rt(t)}),"top-left":t=>({x:st(t),y:ot(t)}),"top-right":t=>({x:it(t),y:ot(t)}),"bottom-left":t=>({x:st(t),y:rt(t)}),"bottom-right":t=>({x:it(t),y:rt(t)}),"top-center":t=>({x:at(t),y:ot(t)}),"right-center":t=>({x:it(t),y:ct(t)}),"bottom-center":t=>({x:at(t),y:rt(t)}),"left-center":t=>({x:st(t),y:ct(t)})},lt=async(t,e="center")=>{if(!e)throw Error("No position given");if(n(e))throw Error("The position given is not the required type: pos: "+typeof e);const o=["center","left","right","top","bottom","right-top","right-bottom","left-top","left-bottom","top-left","top-right","bottom-left","bottom-right","top-center","right-center","bottom-center","left-center"];if(!o.includes(e))throw Error(`The position given does not match allowed positions to use! Valid positions are: ${o.join(", ")}`);await z();const i=t.getBoundingClientRect();return pt[e](i)};class dt{#t;el;circle;radius;options;constructor(t,e,n){this.#e(t,e,n)}#e(t,e,n){if(!t||!e||!n)throw Error("Missing inputs el or radius or options");if(!document.body.contains(t))throw Error("el is not in the DOM");if(this.el=t,this.radius=e,this.options=n,this.#t=document.getElementById("ph-speccer-svg"),!this.#t)throw Error("Missing required SVG element to draw circles. Please see the documentation");const o=nt();X(this.#t,{height:`${o}px`}),this.draw()}async draw(){const t=`ph_draw-circle-${O()}`;this.circle=document.createElementNS("http://www.w3.org/2000/svg","circle");const e=this.el.getAttribute("id")||O();if(this.el.setAttribute("id",e),this.circle.setAttribute("id",t),this.circle.setAttribute("data-el",e),this.circle.classList.add("ph-speccer"),this.circle.classList.add("speccer"),this.circle.classList.add("circle"),!this.#t)throw Error("No parentNode found for circle");this.#t.appendChild(this.circle);const{x:n,y:o}=await lt(this.el,this.options.position);this.circle.setAttribute("r",this.radius+""),this.circle.setAttribute("cx",Math.round(n)+""),this.circle.setAttribute("cy",Math.round(o+document.documentElement.scrollTop)+""),this.circle.setAttribute("fill","currentColor")}}window.DrawCircle=dt;const ht=async(t,e,n="center",o="center")=>{if(!t||!e)throw Error("No element given");const{x:i,y:r}=await lt(t,n),{x:s,y:a}=await lt(e,o);return{x1:i,y1:r,x2:s,y2:a}},ut=(t,e)=>{const{x1:n,x2:o,y1:i,y2:r}=t,{direct:s=!1,firstSet:a=!1,direction:c}=e,p={x:n,y:i},l={x:o,y:r};return s?a?"west"===c?{firstPoint:p,firstControl:{x:n-32,y:i-8},lastPoint:l,lastControl:{x:o+32,y:r}}:"south"===c?{firstPoint:p,firstControl:{x:n-8,y:i+32},lastPoint:l,lastControl:{x:o,y:r-32}}:"east"===c?{firstPoint:p,firstControl:{x:n+32,y:i-8},lastPoint:l,lastControl:{x:o-32,y:r}}:{firstPoint:p,firstControl:{x:n-8,y:i-32},lastPoint:l,lastControl:{x:o,y:r+32}}:"west"===c?{firstPoint:p,firstControl:{x:n-32,y:i+8},lastPoint:l,lastControl:{x:o+32,y:r}}:"south"===c?{firstPoint:p,firstControl:{x:n+8,y:i+32},lastPoint:l,lastControl:{x:o,y:r-32}}:"east"===c?{firstPoint:p,firstControl:{x:n+32,y:i+8},lastPoint:l,lastControl:{x:o-32,y:r}}:{firstPoint:p,firstControl:{x:n+8,y:i-32},lastPoint:l,lastControl:{x:o,y:r+32}}:{firstPoint:p,firstControl:{x:n+(o-n)/2,y:i},lastPoint:l,lastControl:{x:n+(o-n)/2,y:r}}},ft=async(t,e,n)=>{const{pos1:o,pos2:i,firstSet:r=!1,direction:s}=n,{x1:a,y1:c,x2:p,y2:l}=await ht(t,e,o,i);let d=0,h=0;"north"===s?h=8:"west"===s?d=8:"east"===s?d=-8:"south"===s&&(h=-8);const{firstPoint:u,firstControl:f,lastControl:g,lastPoint:m}=ut({x1:a+0,x2:p+d,y1:c+0+document.documentElement.scrollTop,y2:l+h+document.documentElement.scrollTop},{direct:!0,firstSet:r,direction:s});return`M ${u.x} ${u.y}C ${f.x} ${f.y}, ${g.x} ${g.y}, ${m.x} ${m.y}`},gt=async({start:t,stop:e,crude:n=!1})=>{const{x1:o,y1:s,x2:a,y2:c}=await ht(t,e),p=((t,e,n,o,s=!0)=>{if(r(t)||r(e)||r(n)||r(o))throw new SyntaxError("Missing input for `angle`");if(i(t)||i(e)||i(n)||i(o))throw TypeError(`Parameters for \`angle\` do not have the required type. Requires number! Got: ${typeof t} ${typeof e} ${typeof n} ${typeof o}`);const a=o-e,c=n-t;let p=Math.atan2(a,c);return p*=180/Math.PI,s&&p<0&&(p+=360),p})(o,s,a,c);return n?(t=>{if(t>360)throw new RangeError("Parameter cannot exceed 360");if(t<0)throw new RangeError("Parameter cannot be lower than 0");return t>=45&&t<=135?"south":t>135&&t<=225?"west":t>225&&t<=315?"north":"east"})(p):(t=>{if(t>360)throw new RangeError("Parameter cannot exceed 360");if(t<0)throw new RangeError("Parameter cannot be lower than 0");return t>=0&&t<=22.5?"east":t>=22.5&&t<=67.5?"south-east":t>=67.5&&t<=112.5?"south":t>=112.5&&t<=157.5?"south-west":t>=157.5&&t<=202.5?"west":t>=202.5&&t<=247.5?"north-west":t>=247.5&&t<=292.5?"north":t>=292.5&&t<=337.5?"north-east":"east"})(p)};class mt{#t;#n;startElement;stopElement;firstPathElement;secondPathElement;constructor(t,e){this.#e(t,e)}#e(t,e){if(!t||!e)throw Error("Missing inputs startElement and stopElement");if(!document.body.contains(e))throw Error("stopElement is not in the DOM");if(!document.body.contains(t))throw Error("startElement is not in the DOM");if(this.startElement=t,this.stopElement=e,this.#t=document.getElementById("ph-speccer-svg"),this.#n=document.getElementById("ph-speccer-path"),!this.#n||!this.#t)throw Error("Missing required SVG element to draw lines. Please see the documentation");const n=nt();X(this.#t,{height:`${n}px`}),this.connect()}connect(){this.draw(this.#n)}#o(t){if(!t)throw Error("No path given to #getPathElement!");const e=`ph_draw_path-path-${O()}`,n=t.cloneNode(!1),o=this.startElement.getAttribute("id")||O();return this.startElement.setAttribute("id",o),n.setAttribute("data-start-el",o),n.setAttribute("id",e),n.classList.remove("original"),n.classList.add("speccer"),n}async draw(t){if(!t)throw Error("No path given to draw!");const e=this.#o(t),n=this.#o(t);if(!t.parentNode)throw Error("No parentNode found for path");this.firstPathElement=t.parentNode.insertBefore(e,t.nextSibling),this.secondPathElement=t.parentNode.insertBefore(n,t.nextSibling);const o=await gt({stop:this.stopElement,start:this.startElement,crude:!0}),{path1pos1:i,path1pos2:r,path2pos1:s,path2pos2:a}=(t=>{let e,n,o,i;switch(t){case"east":e="right-top",n="left-center",o="right-bottom",i="left-center";break;case"south":e="bottom-left",n="top-center",o="bottom-right",i="top-center";break;case"west":e="left-top",n="right-center",o="left-bottom",i="right-center";break;default:e="top-left",n="bottom-center",o="top-right",i="bottom-center"}return{path1pos1:e,path1pos2:n,path2pos1:o,path2pos2:i}})(o),c=await ft(this.startElement,this.stopElement,{pos1:i,pos2:r,firstSet:!0,direction:o}),p=await ft(this.startElement,this.stopElement,{pos1:s,pos2:a,direction:o});this.firstPathElement.setAttribute("data-direction",o),this.firstPathElement.setAttribute("data-pos1",i),this.firstPathElement.setAttribute("data-pos2",r),this.firstPathElement.setAttribute("d",c),this.secondPathElement.setAttribute("data-direction",o),this.secondPathElement.setAttribute("data-pos1",s),this.secondPathElement.setAttribute("data-pos2",a),this.secondPathElement.setAttribute("d",p)}}window.DrawSVGCurlyBracket=mt;class yt{#t;#n;startElement;stopElement;options;line;constructor(t,e,n={}){this.#e(t,e,n)}#e(t,e,n={}){if(!t||!e)throw Error("Missing inputs startElement and stopElement");if(!document.body.contains(e))throw Error("stopElement is not in the DOM");if(!document.body.contains(t))throw Error("startElement is not in the DOM");if(this.startElement=t,this.stopElement=e,this.options=n,this.#t=document.getElementById("ph-speccer-svg"),this.#n=document.getElementById("ph-speccer-path"),!this.#n||!this.#t)throw Error("Missing required SVG element to draw lines. Please see the documentation");const o=nt();X(this.#t,{height:`${o}px`}),this.connect()}connect(){this.draw(this.#n)}async draw(t){if(!t)throw Error("No path given to draw!");const e=`ph_draw_path-path-${O()}`,n=t.cloneNode(!1),o=this.startElement.getAttribute("id")||O();this.startElement.setAttribute("id",o),n.setAttribute("id",e),n.setAttribute("data-start-el",o),n.classList.remove("original"),n.classList.add("speccer");const{pin:i}=this.options;if(i?.text&&n.classList.add("text"),!t.parentNode)throw Error("No parentNode found for path");this.line=t.parentNode.insertBefore(n,t.nextSibling);const r=await gt({start:this.startElement,stop:this.stopElement,crude:!0}),{pos1:s,pos2:a}=(t=>{let e,n;switch(t){case"east":e="right",n="left";break;case"south":e="bottom",n="top";break;case"west":e="left",n="right";break;default:e="top",n="bottom"}return{pos1:e,pos2:n}})(r),c=await(async(t,e,n)=>{const{pos1:o,pos2:i}=n,{x1:r,y1:s,x2:a,y2:c}=await ht(t,e,o,i),{firstPoint:p,firstControl:l,lastControl:d,lastPoint:h}=ut({x1:r,x2:a,y1:s+document.documentElement.scrollTop,y2:c+document.documentElement.scrollTop},{direction:""});return`M ${p.x} ${p.y}C ${l.x} ${l.y}, ${d.x} ${d.y}, ${h.x} ${h.y}`})(this.startElement,this.stopElement,{pos1:s,pos2:a});this.line.setAttribute("data-direction",r),this.line.setAttribute("data-pos1",s),this.line.setAttribute("data-pos2",a),this.line.setAttribute("d",c)}}window.DrawSVGLine=yt;const wt=t=>parseInt(t,10),bt=t=>wt(getComputedStyle(t).getPropertyValue("--ph-speccer-pin-space"))||48,xt=async(t,e,n,o)=>{await z();const{pin:i={},position:r}=o,{useCurlyBrackets:s,subtle:a,bracket:c,text:p,parent:l,enclose:d}=i,h=bt(e),u=wt(getComputedStyle(e).getPropertyValue("--ph-speccer-measure-size"))||8;const f=await _(e,t);if(d){const{left:t,top:e,height:n,width:o}=f.absolute();return{left:`${t}px`,top:`${e}px`,height:`${n}px`,width:`${o}px`}}if((l||p)&&!c&&!s&&!a){if(r===y.Right){const{top:t}=f.fromRight({center:!0});await z();const{left:e,width:o}=n.getBoundingClientRect();return{left:`${e+o+h}px`,top:`${t}px`}}if(r===y.Bottom){const{left:t}=f.toBottom({center:!0});await z();const{top:e,height:o}=n.getBoundingClientRect();return{left:`${t}px`,top:`${e+o+h}px`}}if(r===y.Left){const{top:t}=f.fromLeft({center:!0});await z();const{left:e}=n.getBoundingClientRect();return{left:e-1.5*h-(p?170:0)+"px",top:`${t}px`}}const{left:t}=f.fromTop({center:!0});await z();const{top:e}=n.getBoundingClientRect();return{left:`${t}px`,top:e-1.5*h+"px"}}if(r===y.Left){if(c&&!s){const{left:t,top:e,height:n}=f.fromLeft({sourceWidth:u});return{left:`${t}px`,top:`${e}px`,height:`${n}px`}}const{left:t,top:e}=f.fromLeft({center:!0,modifier:s?h/1.5:h});return{left:`${t}px`,top:`${e}px`}}if(r===y.Right){if(c&&!s){const{left:t,top:e,height:n}=f.fromRight({center:!1});return{left:`${t}px`,top:`${e}px`,height:`${n}px`}}const{left:t,top:e}=f.fromRight({center:!0,modifier:s?h/1.5:h});return{left:`${t}px`,top:`${e}px`}}if(r===y.Bottom){if(c&&!s){const{left:t,top:e,width:n}=f.fromBottom({center:!1});return{left:`${t}px`,top:`${e}px`,width:`${n}px`}}const{left:t,top:e}=f.fromBottom({center:!0,modifier:s?h/1.5:h});return{left:`${t}px`,top:`${e}px`}}if(c&&!s){const{left:t,top:e,width:n}=f.fromTop({center:!1});return{left:`${t}px`,top:`${e}px`,width:`${n}px`}}const{left:g,top:m}=f.fromTop({center:!0,modifier:s?h/1.5:h});return{left:`${g}px`,top:`${m}px`}},$t=async(t,e,n,o)=>{if(!t)return;if("pin"!==o.type||!o.pin)return;const i=`speccer-${o.slug}-${t.getAttribute("id")||O()}`,r=et(n,o,i);t.setAttribute("data-speccer-element-id",i),document.body.appendChild(r);const s=await xt(t,r,e,o);await X(r,s);const a=o.pin.text&&null!==t.getAttribute("data-speccer-title"),c=o.pin.parent&&!o.pin.enclose&&!o.pin.bracket&&!a;return o.pin.useSVGLine?(new yt(t,r,o),c&&new dt(t,5,o)):o.pin.useCurlyBrackets&&new mt(t,r),i};let Et=0;const At=async(t,e)=>{if(!t)return;const n=t.querySelectorAll('[data-speccer^="pin"]');if(!n||0===n.length)return;const o=t.getAttribute("data-speccer-literals")||window.SPECCER_LITERALS||c;[...n].filter((async t=>!V(t))).forEach((async(n,i)=>{const r=((t,e)=>{let n=e[t];return 0===t&&(Et=0),n||(n=`${e[Et]}${e[Et].toLowerCase()}`,Et++),n})(i,o),s=n.getAttribute("data-speccer")||"";await z();const a=getComputedStyle(n),c=I(s,a,e),p=((t,e,n)=>{const{pin:o}=n;if(!o)return t;const{text:i}=o;if(!i||null===e.getAttribute("data-speccer-title"))return t;const r=e.getAttribute("data-speccer-title"),s=e.getAttribute("data-speccer-description"),a=0===e.nodeName.indexOf("H")?`<span class="ph-speccer heading">${e.nodeName}</span>`:"";return!s&&r?`${a}<span class="ph-speccer title">${r}</span>`:s&&r?`${a}<span class="ph-speccer title">${r}</span><span class="ph-speccer description">${s.replaceAll("\\n","<br/>")}</span>`:t})(r,n,c);await $t(n,t,p,c)}))},St=(t="",e="span")=>{const n=document.createElement(e),o=document.createTextNode(`${t}px`);return n.appendChild(o),n.setAttribute("title",`${t}px`),s(n,"ph-speccer speccer spacing"),n},Ct=async(t,e)=>{if(!t)return;if(V(t))return;const n=t.getAttribute("data-speccer")||"",o=await Y(t),i=I(n,o,e);if("spacing"!==i.type||!i.spacing)return;const r=((t,e)=>{const{marginTop:n,marginBottom:o,marginLeft:i,marginRight:r,paddingTop:s,paddingBottom:a,paddingLeft:c,paddingRight:p}=t;return e?.spacing?.padding?{paddingTop:s,paddingBottom:a,paddingLeft:c,paddingRight:p}:e?.spacing?.margin?{marginTop:n,marginBottom:o,marginLeft:i,marginRight:r}:{marginTop:n,marginBottom:o,marginLeft:i,marginRight:r,paddingTop:s,paddingBottom:a,paddingLeft:c,paddingRight:p}})(o,i),c=Object.keys(r).filter((t=>"0px"!==r[t]));if(!c.length)return;t.classList.add("is-specced");const p=`speccer-spacing-${t.getAttribute("id")||O()}`;t.setAttribute("data-speccer-element-id",p),c.forEach((async e=>{const n=wt(r[e]),o=St(n);o.setAttribute("data-speccer-id",p);const c=(t=>t.includes("Top")?t.replace("Top"," top"):t.includes("Right")?t.replace("Right"," right"):t.includes("Bottom")?t.replace("Bottom"," bottom"):t.includes("Left")?t.replace("Left"," left"):"")(e);s(o,a(c,{bound:!!i?.spacing?.bound})),document.body.appendChild(o);const l=await(async(t,e,n,o)=>{await z();const i=n.getBoundingClientRect(),r=await F(n),s=o?.spacing?.bound?0:96,a=o?.spacing?.bound?0:48;return"marginTop"===t?{height:`${e}px`,width:i.width+s+"px",left:r.left-s+"px",top:r.top-e+"px"}:"marginRight"===t?{height:i.height+a+"px",width:`${e}px`,left:r.left+parseInt(i.width+"",10)+"px",top:r.top+"px"}:"marginBottom"===t?{height:`${e}px`,width:i.width+s+"px",left:r.left-s+"px",top:r.top+parseInt(i.height+"",10)+"px"}:"marginLeft"===t?{height:i.height+a+"px",width:`${e}px`,left:r.left-e+"px",top:r.top+"px"}:"paddingTop"===t?{height:`${e}px`,width:i.width+s+"px",left:r.left-s+"px",top:r.top+"px"}:"paddingBottom"===t?{height:`${e}px`,width:i.width+s+"px",left:r.left-s+"px",top:r.top+(parseInt(i.height+"",10)-e)+"px"}:"paddingRight"===t?{height:i.height+a+"px",width:`${e}px`,left:r.left+(parseInt(i.width+"",10)-e)+"px",top:r.top+"px"}:"paddingLeft"===t?{height:i.height+a+"px",width:`${e}px`,left:r.left+"px",top:r.top+"px"}:void 0})(e,n,t,i);await X(o,l)}))},kt=(t,e=3)=>parseFloat(String(t)).toFixed(e),vt=(t,e,n)=>{const o=document.createElement("div"),{typography:i,position:r}=e,c=a("ph-speccer speccer typography",{syntax:i?.useSyntaxHighlighting||!1,[r]:!0});return o.setAttribute("id",n),o.setAttribute("data-speccer-id",n),o.innerHTML=t,s(o,c),o},Pt=async(t,e)=>{if(!t)return;if(V(t))return;const n=t.getAttribute("data-speccer")||"";await z();const o=I(n,getComputedStyle(t),e);if("typography"!==o.type||!o.typography)return;t.classList.add("is-specced");const i=await(async(t,e=!1)=>{const n=(t=>{const{lineHeight:e,letterSpacing:n,fontFamily:o,fontSize:i,fontStyle:r,fontVariationSettings:s,fontWeight:a}=t;return{lineHeight:e,letterSpacing:n,fontFamily:o,fontSize:i,fontStyle:r,fontVariationSettings:s,fontWeight:a}})(await Y(t));if(e){const t=(n.fontFamily||"").split(",").map((t=>t.includes('"\'"')?`<span class="token string">${t}</span>`:t)).join('<span class="token punctuation">, </span>'),e=`<span class="token number">${parseInt(n.fontSize||"NaN",10)}</span><span class="token unit">px</span> <span class="token operator">/</span> <span class="token number">${parseInt(n.fontSize||"NaN",10)/16}</span><span class="token unit">rem</span>`,o=n.letterSpacing?n.letterSpacing.includes("px")?`<span class="token number">${parseInt(n.letterSpacing,10)}</span><span class="token unit">px</span>`:n.letterSpacing:"",i=n.lineHeight?"normal"!==n.lineHeight?`<span class="token number">${parseInt(n.lineHeight,10)}</span><span class="token unit">px</span> <span class="token operator">/</span> <span class="token number">${parseInt(n.lineHeight,10)/16}</span><span class="token unit">rem</span>`:"normal":"";return`\n<pre class="language-css" tabindex="-1"><code class="language-css"><span class="token selector"><span class="token class">.typography</span></span> <span class="token punctuation">{</span>\n <span class="token property">font-family</span><span class="token punctuation">:</span> ${t}<span class="token punctuation">;</span>\n <span class="token property">font-size</span><span class="token punctuation">:</span> ${e}<span class="token punctuation">;</span>\n <span class="token property">font-weight</span><span class="token punctuation">:</span> <span class="token number">${n.fontWeight}</span><span class="token punctuation">;</span>\n <span class="token property">font-variation-settings</span><span class="token punctuation">:</span> ${n.fontVariationSettings}<span class="token punctuation">;</span>\n <span class="token property">line-height</span><span class="token punctuation">:</span> ${i}<span class="token punctuation">;</span>\n <span class="token property">letter-spacing</span><span class="token punctuation">:</span> ${o}<span class="token punctuation">;</span>\n <span class="token property">font-style</span><span class="token punctuation">:</span> ${n.fontStyle}<span class="token punctuation">;</span>\n<span class="token punctuation">}</span></code></pre>`}return`\ntypography: {<ul class="speccer-styles"> <li><span class="property">font-family:</span> ${n.fontFamily};</li> <li><span class="property">font-size:</span> ${n.fontSize} / ${parseInt(n.fontSize||"NaN",10)/16}rem;</li> <li><span class="property">font-weight:</span> ${n.fontWeight};</li> <li><span class="property">font-variation-settings:</span> ${n.fontVariationSettings};</li> <li><span class="property">line-height:</span> ${"normal"!==n.lineHeight?`${parseInt(n.lineHeight||"NaN",10)}px / ${parseInt(n.lineHeight||"NaN",10)/16}rem`:"normal"};</li> <li><span class="property">letter-spacing:</span> ${n.letterSpacing};</li> <li><span class="property">font-style:</span> ${n.fontStyle};</li></ul>}`})(t,o.typography.useSyntaxHighlighting),r=`speccer-${o.slug}-${t.getAttribute("id")||O()}`;t.setAttribute("data-speccer-element-id",r);const s=vt(i,o,r);document.body.appendChild(s);const a=await(async(t,e,n)=>{const o=e.getBoundingClientRect(),i=bt(n),r=n.getBoundingClientRect(),s=await F(e),{typography:a,position:c}=t;if(a&&c===b.Right)return{left:s.left+o.width+i+"px",top:kt(D(s.top,r,o))+"px"};if(a&&c===b.Top)return{left:kt(W(s.left,r,o))+"px",top:s.top-r.height-i+"px"};if(a&&c===b.Bottom)return{left:kt(W(s.left,r,o))+"px",top:s.top+o.height+i+"px"};return{left:s.left-r.width-i+"px",top:kt(D(s.top,r,o))+"px"}})(o,t,s);X(s,a)},Lt=t=>{const e=()=>((t,e,n=!1)=>{let o;return function(i,...r){const s=n&&!o;o&&clearTimeout(o),o=setTimeout((function(){o=null,n||t.apply(i,r)}),e),s&&t.apply(i,r)}})((()=>{t()}),300);window.removeEventListener("resize",e),window.addEventListener("resize",e)},Bt=t=>{"loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>{t()})):t()},Rt=()=>{const t=new IntersectionObserver(((t,e)=>{for(const n of t)n.intersectionRatio>0&&(Ct(n.target),e.unobserve(n.target))}));for(const e of document.querySelectorAll(`[${p}^="${l}"],[${p}^="${l}"] *:not(td):not(tr):not(th):not(tfoot):not(thead):not(tbody)`))t.observe(e);const e=new IntersectionObserver(((t,e)=>{for(const n of t)n.intersectionRatio>0&&(tt(n.target),e.unobserve(n.target))}));for(const t of document.querySelectorAll(`[${p}^="${d}"]`))e.observe(t);const n=new IntersectionObserver(((t,e)=>{for(const n of t)n.intersectionRatio>0&&(J(n.target),e.unobserve(n.target))}));for(const t of document.querySelectorAll(`[${p}^="${u}"]`))n.observe(t);const o=new IntersectionObserver(((t,e)=>{for(const n of t)n.intersectionRatio>0&&(Pt(n.target),e.unobserve(n.target))}));for(const t of document.querySelectorAll(`[${p}^="${h}"]`))o.observe(t);const i=new IntersectionObserver(((t,e)=>{for(const n of t)n.intersectionRatio>0&&(U(n.target),e.unobserve(n.target))}));for(const t of document.querySelectorAll(`[${p}^="${f}"]`))i.observe(t);const r=new IntersectionObserver((async(t,e)=>{for(const n of t)n.intersectionRatio>0&&(await At(n.target),e.unobserve(n.target))}));for(const t of document.querySelectorAll(`[${p}="${g}"]`))r.observe(t)},Tt=t=>{window.speccer=t},Nt=t=>{const e=document.currentScript;if(e){const n=e.getAttribute("src");n?.includes("speccer.js")&&(e.hasAttribute("data-manual")?Tt(t):e.hasAttribute("data-instant")?t():e.hasAttribute("data-dom")?Bt(t):e.hasAttribute("data-lazy")?Rt():Bt(t),e.hasAttribute("data-manual")||e.hasAttribute("data-lazy")||Lt(t))}},qt=["alt","altgraph","capslock","control","fn","fnlock","hyper","meta","numlock","os","scrolllock","shift","super","symbol","command","ctrl","altgr","symbollock"],Mt=["escape","esc","enter","return","⏎","␛"],Ht=async(t,e,n)=>{await z();const o=bt(n),i=await _(n,e);if("tabstops"===t){let{left:t,top:e}=i.fromTop();return t-=32,e+=32,t<=0&&(t=32),e<=0&&(e=32),{left:`${t}px`,top:`${e}px`}}if("landmark"===t||"autocomplete"===t||"headings"===t){let{left:t,top:e}=i.fromLeft();return t-=o,t<=0&&(t=o),e<=0&&(e=o),{left:`${t}px`,top:`${e}px`}}if("region"===t){const{left:t,top:e,height:n,width:o}=i.fromTop();return{height:`${n}px`,width:`${o}px`,left:`${t}px`,top:`${e}px`}}if("shortcut"===t){const{left:t,top:e}=i.fromBottom();return{left:`${t}px`,top:`${e}px`}}const{left:r,top:s}=i.fromTop({center:!0,modifier:o});return{left:r-32+"px",top:s-32+"px"}},It=async(t,e,n)=>{if(!t||!t.checkVisibility())return;const o=((t="tabstops",e,n="span")=>{const o=document.createElement(n),i=a("ph-speccer speccer a11y",{tabstops:"tabstops"===t,landmark:"landmark"===t,autocomplete:"autocomplete"===t,headings:"headings"===t,region:"region"===t});if("landmark"===t&&e){const t=document.createTextNode(String(e));o.appendChild(t)}return s(o,i),o})(n,e);if("landmark"===n){const e=(t=>{if(!t)return"";if(t.role&&""!==t.role)return t.role;const e=t.nodeName.toLowerCase();return["header","footer","section","form","main","nav","aside"].includes(e)?e:"N/A"})(t),n=t.nodeName.toLowerCase();o.innerHTML=`<${n} role="${e}">`}if("autocomplete"===n){const e=t.getAttribute("autocomplete")||"";o.innerHTML=`autocomplete="${e}"`}"headings"===n&&(o.innerHTML=t.nodeName,o.classList.add(t.nodeName.toLowerCase())),"tabstops"===n&&o.setAttribute("data-speccer-a11y-tabstops",e);const i=`speccer-a11y-${t.getAttribute("id")||O()}`;o.setAttribute("data-speccer-id",i),document.body.appendChild(o);const r=await Ht(n,t,o);await X(o,r)},Ot=async(t,e)=>{const n=e.split(/\s\+\s/).map((t=>t.trim())),o=document.createElement("div"),i=a("ph-speccer speccer a11y shortcut-holder");s(o,i);for(const t of n){const e=document.createElement("kbd"),n=document.createTextNode(t),i=a("ph-speccer speccer a11y shortcut",{modifier:qt.includes(t.toLowerCase()),physical:Mt.includes(t.toLowerCase())});s(e,i),e.appendChild(n);const r=`speccer-a11y-shortcut-${O()}`;o.setAttribute("data-speccer-id",r),o.appendChild(e)}document.body.appendChild(o);const r=await Ht("shortcut",t,o);await X(o,r)},Vt={create:K,element:U},zt={create:St,element:Ct},Gt={createPinElement:et,pinElement:$t,pinElements:At},jt={create:Q,element:tt},Wt={create:Z,element:J},Dt={create:vt,element:Pt},Ft={dom:Bt,lazy:Rt,manual:Tt,activate:Nt},_t=()=>{((t,e=document)=>{[].forEach.call(e.querySelectorAll(t),(function(t){t.remove()}))})(".ph-speccer.speccer");const t=document.querySelectorAll(`[${p}^="${l}"]`),e=document.querySelectorAll(`[${p}^="${d}"]`),n=document.querySelectorAll(`[${p}^="${h}"]`),o=document.querySelectorAll(`[${p}="${g}"]`),i=document.querySelectorAll(`[${p}^="${u}"]`),r=document.querySelectorAll(`[${p}^="${f}"]`);for(const t of i)J(t);for(const t of r)U(t);for(const e of t)if(Ct(e),e.hasChildNodes()){const t=e.querySelectorAll("*:not(td):not(tr):not(th):not(tfoot):not(thead):not(tbody):not([data-speccer])"),n=e.getAttribute("data-speccer")||"";if(t?.length)for(const e of t)e.setAttribute("data-speccer",n),Ct(e)}for(const t of e)tt(t);for(const t of n)Pt(t);for(const t of o)At(t);(()=>{const t=document.querySelectorAll('[data-speccer*="a11y tabstops"]'),e=document.querySelectorAll('[data-speccer*="a11y landmark"]'),n=document.querySelectorAll('[data-speccer*="a11y shortcut"]'),o=document.querySelectorAll('[data-speccer*="a11y autocomplete"]'),i=document.querySelectorAll('[data-speccer*="a11y headings"]');if(n.length)for(const t of n){const e=t.getAttribute("data-speccer-a11y-shortcut");e&&""!==e&&!V(t)&&Ot(t,e)}if(t.length)for(const e of t){const t=e.querySelectorAll("\n a[href], area[href], input:not([disabled]):not([tabindex='-1']),\n button:not([disabled]):not([tabindex='-1']),select:not([disabled]):not([tabindex='-1']),\n textarea:not([disabled]):not([tabindex='-1']),\n iframe, object, embed, *[tabindex]:not([tabindex='-1']), *[contenteditable=true]\n");for(const[e,n]of t.entries()){if(!V(n)){It(n,e+1,"tabstops");continue}const t=n.getAttribute("id");if(!t)continue;const o=document.querySelector(`[for="${t}"]`);o&&!V(o)&&It(o,e+1,"tabstops")}}if(o.length)for(const t of o){const e=t.querySelectorAll("[autocomplete]");for(const t of e)V(t)||It(t,null,"autocomplete")}if(i.length)for(const t of i){const e=t.querySelectorAll('h1,h2,h3,h4,h5,h6, [role="heading"]');for(const t of e)V(t)||It(t,null,"headings")}if(e.length)for(const t of e){const e=t.querySelectorAll('\nheader, footer, section, form, main, nav, aside, [role="section"], [role="banner"],\n[role="complementary"], [role="contentinfo"], [role="form"], [role="main"],\n[role="navigation"], [role="region"], [role="search"]\n');for(const[t,n]of e.entries())V(n)||(It(n,t+1,"landmark"),It(n,null,"region"))}})()};Nt(_t),t.default=_t,t.grid=Vt,t.mark=Wt,t.measure=jt,t.modes=Ft,t.pin=Gt,t.removeSpeccerElement=t=>{const e=t.getAttribute("data-speccer-element-id");if(!e)return;const n=document.getElementById(e)||document.querySelectorAll(`[data-speccer-id="${e}"]`);if(n)if(Object.prototype.isPrototypeOf.call(NodeList.prototype,n))[...n].forEach((t=>t.remove()));else if(n.classList.contains("curly")||n.classList.contains("svg")){const e=t.getAttribute("id");document.querySelectorAll(`#ph-speccer-svg path[data-start-el="${e}"]`).forEach((t=>t.remove()))}},t.spacing=zt,t.typography=Dt,Object.defineProperty(t,"__esModule",{value:!0})}));
|
|
27
|
+
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).speccer={})}(this,(function(t){"use strict";const e=t=>"string"==typeof t,n=t=>!e(t),o=t=>"number"==typeof t,i=t=>!o(t),r=t=>void 0===t,s=(t,e,n="noop")=>{if(!t)return;if(!e||e&&!e.length)return;const o=e.trim().split(" ").filter((t=>t!==n)).filter((t=>""!==t)).map((t=>t.trim()));t.classList.add(...o)},a=(t,e)=>t?!e&&n(t)?Object.keys(t).filter((e=>t[e])).join(" ").trim():`${t.trim()} ${e?Object.keys(e).filter((t=>e[t])).join(" "):""}`.trim():"",c=[..."ABCDEFGHIJKLMNOPQRSTUVWXYZ"],p="data-speccer",l="spacing",d="measure",h="typography",u="mark",f="grid",g="pin-area";var m,y,w,b,x,$,E;!function(t){t.Empty="",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top"}(m||(m={})),function(t){t.Pin="pin",t.Parent="parent",t.Text="text",t.Enclose="enclose",t.Subtle="subtle",t.Bracket="bracket",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top",t.SVG="svg",t.Curly="curly"}(y||(y={})),function(t){t.Measure="measure",t.Slim="slim",t.Width="width",t.Height="height",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top"}(w||(w={})),function(t){t.Typography="typography",t.Syntax="syntax",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top"}(b||(b={})),function(t){t.Spacing="spacing"}(x||(x={})),function(t){t.Mark="mark"}($||($={})),function(t){t.Grid="grid"}(E||(E={}));const A=t=>t.split(" "),S=t=>{if(null===t)return!1;return A(t).includes(y.Bracket)},C=t=>{if(null===t)return!1;return A(t).includes(y.Enclose)},k=t=>{if(null===t)return!1;return A(t).includes(y.Subtle)},v=t=>{if(null===t)return!1;return A(t).includes(y.Parent)},P=t=>{if(null===t)return!1;return A(t).includes(y.Text)},L=t=>{if(null===t)return!1;return A(t).includes(w.Height)},B=t=>{if(null===t)return!1;return A(t).includes(w.Slim)},R=t=>{if(null===t)return!1;return A(t).includes(w.Width)},T=t=>{if(null===t)return!1;const e=A(t);return(v(t)&&!C(t)&&!S(t)||P(t)||e.includes(y.SVG))&&!N(t)},N=t=>{if(null===t)return!1;const e=A(t);return e.includes(y.Curly)&&e.includes(y.Bracket)},q=t=>!!t&&t.split(" ").includes(b.Syntax),M=(t,n)=>(t=>null!==t&&t.split(" ").includes(y.Pin))(t)?"pin":((t,n)=>null!==t&&t.split(" ").includes(E.Grid)&&e(n.display)&&("grid"===n.display||(n.display||"").includes("grid")))(t,n)?"grid":(t=>null!==t&&t.split(" ").includes($.Mark))(t)?"mark":(t=>null!==t&&t.split(" ").includes(w.Measure))(t)?"measure":(t=>null!==t&&t.split(" ").includes(x.Spacing))(t)?"spacing":(t=>null!==t&&t.split(" ").includes(b.Typography))(t)?"typography":"pin",H=t=>(t=>null!==t&&A(t).includes(y.Left))(t)?"left":(t=>null!==t&&A(t).includes(y.Right))(t)?"right":(t=>null!==t&&A(t).includes(y.Bottom))(t)?"bottom":"top",I=(t,e,n)=>{const o=M(t,e),i={slug:(r=t,r.normalize("NFKD").replace(/[\u0300-\u036f]/g,"").trim().toLowerCase().replace(/[^a-z0-9 -]/g,"").replace(/\s+/g," ").replace(/(?:^\w|[A-Z]|\b\w)/g,((t,e)=>0===e?t.toLowerCase():t.toUpperCase())).replace(/\s+/g,"")),position:H(t),type:o};var r;if("pin"===o&&(i.pin={bracket:S(t),enclose:C(t),subtle:k(t),parent:v(t),text:P(t),useSVGLine:T(t),useCurlyBrackets:N(t)}),"measure"===o&&(i.measure={slim:B(t),height:L(t),width:R(t)}),"typography"===o&&(i.typography={useSyntaxHighlighting:q(t)}),"grid"===o){const e=(t=>t?.includes("columns")?"columns":t?.includes("rows")?"rows":"both")(t);i.grid={toggle:e,both:"both"===e,rows:"rows"===e,columns:"columns"===e}}if("spacing"===o){const e=(t=>t?.includes("margin")?"margin":t?.includes("padding")?"padding":"both")(t);i.spacing={both:"both"===e,margin:"margin"===e,padding:"padding"===e,bound:t.includes("bound")}}return{...i,...n}},O=()=>"_"+Math.random().toString(36).substring(2,11),V=t=>!t.checkVisibility({opacityProperty:!0,checkVisibilityCSS:!0}),z=()=>new Promise(requestAnimationFrame),G=async(t,e,n)=>{await z();return getComputedStyle(t)[e]===n},j=async(t,e,n)=>{if(!t.parentElement)return null;return await G(t.parentElement,e,n)?t.parentElement:await j(t.parentElement,e,n)},W=(t,e,n)=>t-e.width/2+n.width/2,D=(t,e,n)=>t-e.height/2+n.height/2,F=async t=>{await z();let e=t.getBoundingClientRect(),n=e.top+window.scrollY;const o=e.left+window.scrollX,i=await(async t=>await j(t,"position","sticky"))(t);if(await(async t=>await G(t,"position","sticky"))(t)){const o=t.style.position;await z(),t.style.position="relative",await z(),e=t.getBoundingClientRect(),n=e.top,await z(),t.style.position=o}else if(i){const o=i.style.position;await z(),i.style.position="relative",await z(),e=t.getBoundingClientRect(),n=e.top,await z(),i.style.position=o}return{height:e.height,width:e.width,top:n,left:o}},_=async(t,e)=>{await z();const n=t.getBoundingClientRect(),o=await F(e),i=await(async(t,e)=>{await z();const n=t.getBoundingClientRect();await z();const o=e.getBoundingClientRect(),i=o.top+window.scrollY,r=o.left+window.scrollX;return{height:o.height,width:o.width,top:D(i,n,o),left:W(r,n,o)}})(t,e),r=o.height,s=o.width,a=n.height,c=n.width;return{absolute:()=>({top:o.top,left:o.left,height:r,width:s}),toTop:({center:t=!1,sourceHeight:e=a,modifier:n=0}={})=>({top:o.top+e+n,left:t?i.left:o.left,height:r,width:s}),fromTop:({center:t=!1,sourceHeight:e=a,modifier:n=0}={})=>({top:o.top-e-n,left:t?i.left:o.left,height:r,width:s}),toBottom:({center:t=!1,sourceHeight:e=a,targetHeight:n=r,modifier:c=0}={})=>({top:o.top+n-(e+c),left:t?i.left:o.left,height:r,width:s}),fromBottom:({center:t=!1,targetHeight:e=r,modifier:n=0}={})=>({top:o.top+e+n,left:t?i.left:o.left,height:r,width:s}),toLeft:({center:t=!1,sourceWidth:e=c,modifier:n=0}={})=>({top:t?i.top:o.top,left:o.left+e+n,height:r,width:s}),fromLeft:({center:t=!1,sourceWidth:e=c,modifier:n=0}={})=>({top:t?i.top:o.top,left:o.left-e-n,height:r,width:s}),toRight:({center:t=!1,sourceWidth:e=c,targetWidth:n=s,modifier:a=0}={})=>({top:t?i.top:o.top,left:o.left+n-(e+a),height:r,width:s}),fromRight:({center:t=!1,targetWidth:e=s,modifier:n=0}={})=>({top:t?i.top:o.top,left:o.left+e+n,height:r,width:s})}},X=async(t,n)=>{var i;!t||!n||e(n)||o(n)||(i=n,"boolean"==typeof i)||Array.isArray(n)&&!n.length||!Object.keys(n).length&&n.constructor===Object||(await z(),Array.isArray(n)&&(n=n.reduce(((t,e)=>(t[e.key]=e.value,t)),{})),Object.assign(t.style,n))},Y=async t=>(await z(),getComputedStyle(t,null)),K=async(t,e,n)=>{await z();const{grid:o}=n;if(!o)return;const{toggle:i}=o,{height:r,width:a}=t.getBoundingClientRect(),{top:c,left:p}=await F(t),{gridTemplateColumns:l,gridTemplateRows:d,padding:h}=e,u=`speccer-${n.slug}-${t.getAttribute("id")||O()}`;if(t.setAttribute("data-speccer-element-id",u),"columns"===i||"both"===i){const t=parseInt(e.columnGap||"0"),n=document.createElement("div");document.documentElement.style.setProperty("--ph-speccer-grid-gap-original",`${t}px`),document.documentElement.style.setProperty("--ph-speccer-grid-gap",`${t<24?24:t}px`),t<24&&n.classList.add("speccer-small-grid"),n.setAttribute("data-speccer-id",u),s(n,"ph-speccer speccer speccer-grid-container"),X(n,{height:`${r+64}px`,width:`${a}px`,left:`${p}px`,top:c-32+"px",padding:h,gridTemplateColumns:l});const o=l?.split(" ").length||0;for(let t=0;t<o;t++){const t=document.createElement("div");s(t,"ph-speccer speccer speccer-grid-item"),n.appendChild(t)}document.body.appendChild(n)}if("rows"===i||"both"===i){const t=parseInt(e.rowGap||"0"),n=document.createElement("div");document.documentElement.style.setProperty("--ph-speccer-grid-row-gap-original",`${t}px`),document.documentElement.style.setProperty("--ph-speccer-grid-row-gap",`${t<24?24:t}px`),t<24&&n.classList.add("speccer-small-grid"),n.setAttribute("data-speccer-id",u),n.classList.add("ph-speccer"),n.classList.add("speccer"),n.classList.add("speccer-grid-row-container"),s(n,"ph-speccer speccer speccer-grid-row-container"),X(n,{width:`${a+64}px`,height:`${r}px`,top:`${c}px`,left:p-32+"px",padding:h,gridTemplateRows:d});const o=d?.split(" ").length||0;for(let t=0;t<o;t++){const t=document.createElement("div");s(t,"ph-speccer speccer speccer-grid-row-item"),n.appendChild(t)}document.body.appendChild(n)}},U=async(t,e)=>{if(!t)return;if(V(t))return;const n=t.getAttribute(p)||"",o=await Y(t),i=I(n,o,e);"grid"===i.type&&i.grid&&(await z(),await K(t,o,i))},Z=(t,e="span")=>{const n=document.createElement(e);return n.setAttribute("id",t),s(n,"ph-speccer speccer mark"),n},J=async t=>{if(!t)return;if(V(t))return;const e=t.getAttribute(p)||"";await z();const n=I(e,getComputedStyle(t));if("mark"!==n.type)return;const o=`speccer-${n.slug}-${t.getAttribute("id")||O()}`;t.setAttribute("data-speccer-element-id",o);const i=Z(o);i.setAttribute("data-speccer-id",o),document.body.appendChild(i);const r=await _(i,t),{left:s,top:a,height:c,width:l}=r.absolute(),d={left:`${s}px`,top:`${a}px`,height:`${c}px`,width:`${l}px`};await X(i,d)},Q=(t="",e,n,o="span")=>{const i=document.createElement(o);i.setAttribute("title",`${t}px`),i.setAttribute("id",n),i.setAttribute("data-speccer-id",n),i.setAttribute("data-measure",`${parseInt(String(t),10)}px`);const{measure:r,position:c}=e,p=a("ph-speccer speccer measure",{height:r?.height||!1,width:r?.width||!1,slim:r?.slim||!1,[c]:!0});return s(i,p),i},tt=async(t,e)=>{if(!t)return;if(V(t))return;const n=t.getAttribute("data-speccer")||"";await z();const o=I(n,getComputedStyle(t),e);if("measure"!==o.type||!o.measure)return;const{measure:i,position:r}=o;await z();const s=t.getBoundingClientRect(),a=i.slim?0:48,c=i.slim?0:96,p=`speccer-${o.slug}-${t.getAttribute("id")||O()}`;if(t.setAttribute("data-speccer-element-id",p),i.width)if(r===w.Bottom){const e=Q(s.width,o,p);document.body.appendChild(e);const n=await _(e,t);if(i.slim){const{left:t,top:o,width:i}=n.fromBottom({center:!1});await X(e,{left:`${t}px`,top:`${o}px`,width:`${i}px`})}else{const{left:t,top:o,width:i,height:r}=n.absolute({center:!1});await X(e,{left:`${t}px`,top:`${o}px`,width:`${i}px`,height:`${r+a}px`})}}else{const e=Q(s.width,o,p);document.body.appendChild(e);const n=await _(e,t);if(i.slim){const{left:t,top:o,width:i}=n.fromTop({center:!1});await X(e,{left:`${t}px`,top:`${o}px`,width:`${i}px`})}else{const{left:t,top:o,width:i,height:r}=n.absolute({center:!1});await X(e,{left:`${t}px`,top:o-a+"px",width:`${i}px`,height:`${r+a}px`})}}else if(i.height)if(r===w.Right){const e=Q(s.height,o,p);document.body.appendChild(e);const n=await _(e,t);if(i.slim){const{left:t,top:o,height:i}=n.fromRight({center:!1});await X(e,{left:`${t}px`,top:`${o}px`,height:`${i}px`})}else{const{left:t,top:o,height:i,width:r}=n.absolute({center:!1});await X(e,{left:`${t}px`,top:`${o}px`,height:`${i}px`,width:`${r+c}px`})}}else{const e=Q(s.height,o,p);document.body.appendChild(e);const n=await _(e,t);if(i.slim){const{left:t,top:o,height:i}=n.fromLeft({center:!1});await X(e,{left:`${t}px`,top:`${o}px`,height:`${i}px`})}else{const{left:t,top:o,height:i,width:r}=n.absolute({center:!1});await X(e,{left:t-c+"px",top:`${o}px`,height:`${i}px`,width:`${r+c}px`})}}},et=(t="",e,n="",o="span")=>{const i=document.createElement(o),r={},{position:c,pin:p={}}=e,{useSVGLine:l,useCurlyBrackets:d,text:h,parent:u,bracket:f,enclose:g,subtle:m}=p;r.text=h,r.parent=u,r.bracket=f,r.enclose=g,r.subtle=m,r.svg=l,r.curly=d,r[c]=!0,!u||f||d||m||(r.svg=!0),!f&&!g||f&&d?i.innerHTML=t:(f||g)&&i.setAttribute("data-pin-counter",t);const y=a("ph-speccer speccer pin",r);return s(i,y),i.setAttribute("id",n),i.setAttribute("data-speccer-id",n),i},nt=()=>{const{body:t,documentElement:e}=document;return Math.max(t.scrollHeight,t.offsetHeight,e.clientHeight,e.scrollHeight,e.offsetHeight)},ot=t=>t.top,it=t=>t.left+t.width,rt=t=>t.top+t.height,st=t=>t.left,at=t=>t.left+t.width/2,ct=t=>t.top+t.height/2,pt={center:t=>({x:at(t),y:ct(t)}),top:t=>({x:at(t),y:ot(t)}),right:t=>({x:it(t),y:ct(t)}),bottom:t=>({x:at(t),y:rt(t)}),left:t=>({x:st(t),y:ct(t)}),"right-top":t=>({x:it(t),y:ot(t)}),"right-bottom":t=>({x:it(t),y:rt(t)}),"left-top":t=>({x:st(t),y:ot(t)}),"left-bottom":t=>({x:st(t),y:rt(t)}),"top-left":t=>({x:st(t),y:ot(t)}),"top-right":t=>({x:it(t),y:ot(t)}),"bottom-left":t=>({x:st(t),y:rt(t)}),"bottom-right":t=>({x:it(t),y:rt(t)}),"top-center":t=>({x:at(t),y:ot(t)}),"right-center":t=>({x:it(t),y:ct(t)}),"bottom-center":t=>({x:at(t),y:rt(t)}),"left-center":t=>({x:st(t),y:ct(t)})},lt=async(t,e="center")=>{if(!e)throw Error("No position given");if(n(e))throw Error("The position given is not the required type: pos: "+typeof e);const o=["center","left","right","top","bottom","right-top","right-bottom","left-top","left-bottom","top-left","top-right","bottom-left","bottom-right","top-center","right-center","bottom-center","left-center"];if(!o.includes(e))throw Error(`The position given does not match allowed positions to use! Valid positions are: ${o.join(", ")}`);await z();const i=t.getBoundingClientRect();return pt[e](i)};class dt{#t;el;circle;radius;options;constructor(t,e,n){this.#e(t,e,n)}#e(t,e,n){if(!t||!e||!n)throw Error("Missing inputs el or radius or options");if(!document.body.contains(t))throw Error("el is not in the DOM");if(this.el=t,this.radius=e,this.options=n,this.#t=document.getElementById("ph-speccer-svg"),!this.#t)throw Error("Missing required SVG element to draw circles. Please see the documentation");const o=nt();X(this.#t,{height:`${o}px`}),this.draw()}async draw(){const t=`ph_draw-circle-${O()}`;this.circle=document.createElementNS("http://www.w3.org/2000/svg","circle");const e=this.el.getAttribute("id")||O();if(this.el.setAttribute("id",e),this.circle.setAttribute("id",t),this.circle.setAttribute("data-el",e),this.circle.classList.add("ph-speccer"),this.circle.classList.add("speccer"),this.circle.classList.add("circle"),!this.#t)throw Error("No parentNode found for circle");this.#t.appendChild(this.circle);const{x:n,y:o}=await lt(this.el,this.options.position);this.circle.setAttribute("r",this.radius+""),this.circle.setAttribute("cx",Math.round(n)+""),this.circle.setAttribute("cy",Math.round(o+document.documentElement.scrollTop)+""),this.circle.setAttribute("fill","currentColor")}}window.DrawCircle=dt;const ht=async(t,e,n="center",o="center")=>{if(!t||!e)throw Error("No element given");const{x:i,y:r}=await lt(t,n),{x:s,y:a}=await lt(e,o);return{x1:i,y1:r,x2:s,y2:a}},ut=(t,e)=>{const{x1:n,x2:o,y1:i,y2:r}=t,{direct:s=!1,firstSet:a=!1,direction:c}=e,p={x:n,y:i},l={x:o,y:r};return s?a?"west"===c?{firstPoint:p,firstControl:{x:n-32,y:i-8},lastPoint:l,lastControl:{x:o+32,y:r}}:"south"===c?{firstPoint:p,firstControl:{x:n-8,y:i+32},lastPoint:l,lastControl:{x:o,y:r-32}}:"east"===c?{firstPoint:p,firstControl:{x:n+32,y:i-8},lastPoint:l,lastControl:{x:o-32,y:r}}:{firstPoint:p,firstControl:{x:n-8,y:i-32},lastPoint:l,lastControl:{x:o,y:r+32}}:"west"===c?{firstPoint:p,firstControl:{x:n-32,y:i+8},lastPoint:l,lastControl:{x:o+32,y:r}}:"south"===c?{firstPoint:p,firstControl:{x:n+8,y:i+32},lastPoint:l,lastControl:{x:o,y:r-32}}:"east"===c?{firstPoint:p,firstControl:{x:n+32,y:i+8},lastPoint:l,lastControl:{x:o-32,y:r}}:{firstPoint:p,firstControl:{x:n+8,y:i-32},lastPoint:l,lastControl:{x:o,y:r+32}}:{firstPoint:p,firstControl:{x:n+(o-n)/2,y:i},lastPoint:l,lastControl:{x:n+(o-n)/2,y:r}}},ft=async(t,e,n)=>{const{pos1:o,pos2:i,firstSet:r=!1,direction:s}=n,{x1:a,y1:c,x2:p,y2:l}=await ht(t,e,o,i);let d=0,h=0;"north"===s?h=8:"west"===s?d=8:"east"===s?d=-8:"south"===s&&(h=-8);const{firstPoint:u,firstControl:f,lastControl:g,lastPoint:m}=ut({x1:a+0,x2:p+d,y1:c+0+document.documentElement.scrollTop,y2:l+h+document.documentElement.scrollTop},{direct:!0,firstSet:r,direction:s});return`M ${u.x} ${u.y}C ${f.x} ${f.y}, ${g.x} ${g.y}, ${m.x} ${m.y}`},gt=async({start:t,stop:e,crude:n=!1})=>{const{x1:o,y1:s,x2:a,y2:c}=await ht(t,e),p=((t,e,n,o,s=!0)=>{if(r(t)||r(e)||r(n)||r(o))throw new SyntaxError("Missing input for `angle`");if(i(t)||i(e)||i(n)||i(o))throw TypeError(`Parameters for \`angle\` do not have the required type. Requires number! Got: ${typeof t} ${typeof e} ${typeof n} ${typeof o}`);const a=o-e,c=n-t;let p=Math.atan2(a,c);return p*=180/Math.PI,s&&p<0&&(p+=360),p})(o,s,a,c);return n?(t=>{if(t>360)throw new RangeError("Parameter cannot exceed 360");if(t<0)throw new RangeError("Parameter cannot be lower than 0");return t>=45&&t<=135?"south":t>135&&t<=225?"west":t>225&&t<=315?"north":"east"})(p):(t=>{if(t>360)throw new RangeError("Parameter cannot exceed 360");if(t<0)throw new RangeError("Parameter cannot be lower than 0");return t>=0&&t<=22.5?"east":t>=22.5&&t<=67.5?"south-east":t>=67.5&&t<=112.5?"south":t>=112.5&&t<=157.5?"south-west":t>=157.5&&t<=202.5?"west":t>=202.5&&t<=247.5?"north-west":t>=247.5&&t<=292.5?"north":t>=292.5&&t<=337.5?"north-east":"east"})(p)};class mt{#t;#n;startElement;stopElement;firstPathElement;secondPathElement;constructor(t,e){this.#e(t,e)}#e(t,e){if(!t||!e)throw Error("Missing inputs startElement and stopElement");if(!document.body.contains(e))throw Error("stopElement is not in the DOM");if(!document.body.contains(t))throw Error("startElement is not in the DOM");if(this.startElement=t,this.stopElement=e,this.#t=document.getElementById("ph-speccer-svg"),this.#n=document.getElementById("ph-speccer-path"),!this.#n||!this.#t)throw Error("Missing required SVG element to draw lines. Please see the documentation");const n=nt();X(this.#t,{height:`${n}px`}),this.connect()}connect(){this.draw(this.#n)}#o(t){if(!t)throw Error("No path given to #getPathElement!");const e=`ph_draw_path-path-${O()}`,n=t.cloneNode(!1),o=this.startElement.getAttribute("id")||O();return this.startElement.setAttribute("id",o),n.setAttribute("data-start-el",o),n.setAttribute("id",e),n.classList.remove("original"),n.classList.add("speccer"),n}async draw(t){if(!t)throw Error("No path given to draw!");const e=this.#o(t),n=this.#o(t);if(!t.parentNode)throw Error("No parentNode found for path");this.firstPathElement=t.parentNode.insertBefore(e,t.nextSibling),this.secondPathElement=t.parentNode.insertBefore(n,t.nextSibling);const o=await gt({stop:this.stopElement,start:this.startElement,crude:!0}),{path1pos1:i,path1pos2:r,path2pos1:s,path2pos2:a}=(t=>{let e,n,o,i;switch(t){case"east":e="right-top",n="left-center",o="right-bottom",i="left-center";break;case"south":e="bottom-left",n="top-center",o="bottom-right",i="top-center";break;case"west":e="left-top",n="right-center",o="left-bottom",i="right-center";break;default:e="top-left",n="bottom-center",o="top-right",i="bottom-center"}return{path1pos1:e,path1pos2:n,path2pos1:o,path2pos2:i}})(o),c=await ft(this.startElement,this.stopElement,{pos1:i,pos2:r,firstSet:!0,direction:o}),p=await ft(this.startElement,this.stopElement,{pos1:s,pos2:a,direction:o});this.firstPathElement.setAttribute("data-direction",o),this.firstPathElement.setAttribute("data-pos1",i),this.firstPathElement.setAttribute("data-pos2",r),this.firstPathElement.setAttribute("d",c),this.secondPathElement.setAttribute("data-direction",o),this.secondPathElement.setAttribute("data-pos1",s),this.secondPathElement.setAttribute("data-pos2",a),this.secondPathElement.setAttribute("d",p)}}window.DrawSVGCurlyBracket=mt;class yt{#t;#n;startElement;stopElement;options;line;constructor(t,e,n={}){this.#e(t,e,n)}#e(t,e,n={}){if(!t||!e)throw Error("Missing inputs startElement and stopElement");if(!document.body.contains(e))throw Error("stopElement is not in the DOM");if(!document.body.contains(t))throw Error("startElement is not in the DOM");if(this.startElement=t,this.stopElement=e,this.options=n,this.#t=document.getElementById("ph-speccer-svg"),this.#n=document.getElementById("ph-speccer-path"),!this.#n||!this.#t)throw Error("Missing required SVG element to draw lines. Please see the documentation");const o=nt();X(this.#t,{height:`${o}px`}),this.connect()}connect(){this.draw(this.#n)}async draw(t){if(!t)throw Error("No path given to draw!");const e=`ph_draw_path-path-${O()}`,n=t.cloneNode(!1),o=this.startElement.getAttribute("id")||O();this.startElement.setAttribute("id",o),n.setAttribute("id",e),n.setAttribute("data-start-el",o),n.classList.remove("original"),n.classList.add("speccer");const{pin:i}=this.options;if(i?.text&&n.classList.add("text"),!t.parentNode)throw Error("No parentNode found for path");this.line=t.parentNode.insertBefore(n,t.nextSibling);const r=await gt({start:this.startElement,stop:this.stopElement,crude:!0}),{pos1:s,pos2:a}=(t=>{let e,n;switch(t){case"east":e="right",n="left";break;case"south":e="bottom",n="top";break;case"west":e="left",n="right";break;default:e="top",n="bottom"}return{pos1:e,pos2:n}})(r),c=await(async(t,e,n)=>{const{pos1:o,pos2:i}=n,{x1:r,y1:s,x2:a,y2:c}=await ht(t,e,o,i),{firstPoint:p,firstControl:l,lastControl:d,lastPoint:h}=ut({x1:r,x2:a,y1:s+document.documentElement.scrollTop,y2:c+document.documentElement.scrollTop},{direction:""});return`M ${p.x} ${p.y}C ${l.x} ${l.y}, ${d.x} ${d.y}, ${h.x} ${h.y}`})(this.startElement,this.stopElement,{pos1:s,pos2:a});this.line.setAttribute("data-direction",r),this.line.setAttribute("data-pos1",s),this.line.setAttribute("data-pos2",a),this.line.setAttribute("d",c)}}window.DrawSVGLine=yt;const wt=t=>parseInt(t,10),bt=t=>wt(getComputedStyle(t).getPropertyValue("--ph-speccer-pin-space"))||48,xt=async(t,e,n,o)=>{await z();const{pin:i={},position:r}=o,{useCurlyBrackets:s,subtle:a,bracket:c,text:p,parent:l,enclose:d}=i,h=bt(e),u=wt(getComputedStyle(e).getPropertyValue("--ph-speccer-measure-size"))||8;const f=await _(e,t);if(d){const{left:t,top:e,height:n,width:o}=f.absolute();return{left:`${t}px`,top:`${e}px`,height:`${n}px`,width:`${o}px`}}if((l||p)&&!c&&!s&&!a){if(r===y.Right){const{top:t}=f.fromRight({center:!0});await z();const{left:e,width:o}=n.getBoundingClientRect();return{left:`${e+o+h}px`,top:`${t}px`}}if(r===y.Bottom){const{left:t}=f.toBottom({center:!0});await z();const{top:e,height:o}=n.getBoundingClientRect();return{left:`${t}px`,top:`${e+o+h}px`}}if(r===y.Left){const{top:t}=f.fromLeft({center:!0});await z();const{left:e}=n.getBoundingClientRect();return{left:e-1.5*h-(p?170:0)+"px",top:`${t}px`}}const{left:t}=f.fromTop({center:!0});await z();const{top:e}=n.getBoundingClientRect();return{left:`${t}px`,top:e-1.5*h+"px"}}if(r===y.Left){if(c&&!s){const{left:t,top:e,height:n}=f.fromLeft({sourceWidth:u});return{left:`${t}px`,top:`${e}px`,height:`${n}px`}}const{left:t,top:e}=f.fromLeft({center:!0,modifier:s?h/1.5:h});return{left:`${t}px`,top:`${e}px`}}if(r===y.Right){if(c&&!s){const{left:t,top:e,height:n}=f.fromRight({center:!1});return{left:`${t}px`,top:`${e}px`,height:`${n}px`}}const{left:t,top:e}=f.fromRight({center:!0,modifier:s?h/1.5:h});return{left:`${t}px`,top:`${e}px`}}if(r===y.Bottom){if(c&&!s){const{left:t,top:e,width:n}=f.fromBottom({center:!1});return{left:`${t}px`,top:`${e}px`,width:`${n}px`}}const{left:t,top:e}=f.fromBottom({center:!0,modifier:s?h/1.5:h});return{left:`${t}px`,top:`${e}px`}}if(c&&!s){const{left:t,top:e,width:n}=f.fromTop({center:!1});return{left:`${t}px`,top:`${e}px`,width:`${n}px`}}const{left:g,top:m}=f.fromTop({center:!0,modifier:s?h/1.5:h});return{left:`${g}px`,top:`${m}px`}},$t=async(t,e,n,o)=>{if("pin"!==o.type||!o.pin)return;const i=`speccer-${o.slug}-${t.getAttribute("id")||O()}`,r=et(n,o,i);t.setAttribute("data-speccer-element-id",i),document.body.appendChild(r);const s=await xt(t,r,e,o);await X(r,s);const a=o.pin.text&&null!==t.getAttribute("data-speccer-title"),c=o.pin.parent&&!o.pin.enclose&&!o.pin.bracket&&!a;return o.pin.useSVGLine?(new yt(t,r,o),c&&new dt(t,5,o)):o.pin.useCurlyBrackets&&new mt(t,r),i};let Et=0;const At=async(t,e)=>{if(!t)return;const n=t.querySelectorAll('[data-speccer^="pin"]');if(!n||0===n.length)return;const o=t.getAttribute("data-speccer-literals")||window.SPECCER_LITERALS||c;[...n].filter((async t=>!V(t))).forEach((async(n,i)=>{const r=((t,e)=>{let n=e[t];return 0===t&&(Et=0),n||(n=`${e[Et]}${e[Et].toLowerCase()}`,Et++),n})(i,o),s=n.getAttribute("data-speccer")||"";await z();const a=getComputedStyle(n),c=I(s,a,e),p=((t,e,n)=>{const{pin:o}=n;if(!o)return t;const{text:i}=o;if(!i||null===e.getAttribute("data-speccer-title"))return t;const r=e.getAttribute("data-speccer-title"),s=e.getAttribute("data-speccer-description"),a=0===e.nodeName.indexOf("H")?`<span class="ph-speccer heading">${e.nodeName}</span>`:"";return!s&&r?`${a}<span class="ph-speccer title">${r}</span>`:s&&r?`${a}<span class="ph-speccer title">${r}</span><span class="ph-speccer description">${s.replaceAll("\\n","<br/>")}</span>`:t})(r,n,c);await $t(n,t,p,c)}))},St=(t="",e="span")=>{const n=document.createElement(e),o=document.createTextNode(`${t}px`);return n.appendChild(o),n.setAttribute("title",`${t}px`),s(n,"ph-speccer speccer spacing"),n},Ct=async(t,e)=>{if(!t)return;if(V(t))return;const n=t.getAttribute("data-speccer")||"",o=await Y(t),i=I(n,o,e);if("spacing"!==i.type||!i.spacing)return;const r=((t,e)=>{const{marginTop:n,marginBottom:o,marginLeft:i,marginRight:r,paddingTop:s,paddingBottom:a,paddingLeft:c,paddingRight:p}=t;return e?.spacing?.padding?{paddingTop:s,paddingBottom:a,paddingLeft:c,paddingRight:p}:e?.spacing?.margin?{marginTop:n,marginBottom:o,marginLeft:i,marginRight:r}:{marginTop:n,marginBottom:o,marginLeft:i,marginRight:r,paddingTop:s,paddingBottom:a,paddingLeft:c,paddingRight:p}})(o,i),c=Object.keys(r).filter((t=>"0px"!==r[t]));if(!c.length)return;t.classList.add("is-specced");const p=`speccer-spacing-${t.getAttribute("id")||O()}`;t.setAttribute("data-speccer-element-id",p),c.forEach((async e=>{const n=wt(r[e]),o=St(n);o.setAttribute("data-speccer-id",p);const c=(t=>t.includes("Top")?t.replace("Top"," top"):t.includes("Right")?t.replace("Right"," right"):t.includes("Bottom")?t.replace("Bottom"," bottom"):t.includes("Left")?t.replace("Left"," left"):"")(e);s(o,a(c,{bound:!!i?.spacing?.bound})),document.body.appendChild(o);const l=await(async(t,e,n,o)=>{await z();const i=n.getBoundingClientRect(),r=await F(n),s=o?.spacing?.bound?0:96,a=o?.spacing?.bound?0:48;return"marginTop"===t?{height:`${e}px`,width:i.width+s+"px",left:r.left-s+"px",top:r.top-e+"px"}:"marginRight"===t?{height:i.height+a+"px",width:`${e}px`,left:r.left+parseInt(i.width+"",10)+"px",top:r.top+"px"}:"marginBottom"===t?{height:`${e}px`,width:i.width+s+"px",left:r.left-s+"px",top:r.top+parseInt(i.height+"",10)+"px"}:"marginLeft"===t?{height:i.height+a+"px",width:`${e}px`,left:r.left-e+"px",top:r.top+"px"}:"paddingTop"===t?{height:`${e}px`,width:i.width+s+"px",left:r.left-s+"px",top:r.top+"px"}:"paddingBottom"===t?{height:`${e}px`,width:i.width+s+"px",left:r.left-s+"px",top:r.top+(parseInt(i.height+"",10)-e)+"px"}:"paddingRight"===t?{height:i.height+a+"px",width:`${e}px`,left:r.left+(parseInt(i.width+"",10)-e)+"px",top:r.top+"px"}:"paddingLeft"===t?{height:i.height+a+"px",width:`${e}px`,left:r.left+"px",top:r.top+"px"}:void 0})(e,n,t,i);await X(o,l)}))},kt=(t,e=3)=>parseFloat(String(t)).toFixed(e),vt=(t,e,n)=>{const o=document.createElement("div"),{typography:i,position:r}=e,c=a("ph-speccer speccer typography",{syntax:i?.useSyntaxHighlighting||!1,[r]:!0});return o.setAttribute("id",n),o.setAttribute("data-speccer-id",n),o.innerHTML=t,s(o,c),o},Pt=async(t,e)=>{if(!t)return;if(V(t))return;const n=t.getAttribute("data-speccer")||"";await z();const o=I(n,getComputedStyle(t),e);if("typography"!==o.type||!o.typography)return;t.classList.add("is-specced");const i=await(async(t,e=!1)=>{const n=(t=>{const{lineHeight:e,letterSpacing:n,fontFamily:o,fontSize:i,fontStyle:r,fontVariationSettings:s,fontWeight:a}=t;return{lineHeight:e,letterSpacing:n,fontFamily:o,fontSize:i,fontStyle:r,fontVariationSettings:s,fontWeight:a}})(await Y(t));if(e){const t=(n.fontFamily||"").split(",").map((t=>t.includes('"\'"')?`<span class="token string">${t}</span>`:t)).join('<span class="token punctuation">, </span>'),e=`<span class="token number">${parseInt(n.fontSize||"NaN",10)}</span><span class="token unit">px</span> <span class="token operator">/</span> <span class="token number">${parseInt(n.fontSize||"NaN",10)/16}</span><span class="token unit">rem</span>`,o=n.letterSpacing?n.letterSpacing.includes("px")?`<span class="token number">${parseInt(n.letterSpacing,10)}</span><span class="token unit">px</span>`:n.letterSpacing:"",i=n.lineHeight?"normal"!==n.lineHeight?`<span class="token number">${parseInt(n.lineHeight,10)}</span><span class="token unit">px</span> <span class="token operator">/</span> <span class="token number">${parseInt(n.lineHeight,10)/16}</span><span class="token unit">rem</span>`:"normal":"";return`\n<pre class="language-css" tabindex="-1"><code class="language-css"><span class="token selector"><span class="token class">.typography</span></span> <span class="token punctuation">{</span>\n <span class="token property">font-family</span><span class="token punctuation">:</span> ${t}<span class="token punctuation">;</span>\n <span class="token property">font-size</span><span class="token punctuation">:</span> ${e}<span class="token punctuation">;</span>\n <span class="token property">font-weight</span><span class="token punctuation">:</span> <span class="token number">${n.fontWeight}</span><span class="token punctuation">;</span>\n <span class="token property">font-variation-settings</span><span class="token punctuation">:</span> ${n.fontVariationSettings}<span class="token punctuation">;</span>\n <span class="token property">line-height</span><span class="token punctuation">:</span> ${i}<span class="token punctuation">;</span>\n <span class="token property">letter-spacing</span><span class="token punctuation">:</span> ${o}<span class="token punctuation">;</span>\n <span class="token property">font-style</span><span class="token punctuation">:</span> ${n.fontStyle}<span class="token punctuation">;</span>\n<span class="token punctuation">}</span></code></pre>`}return`\ntypography: {<ul class="speccer-styles"> <li><span class="property">font-family:</span> ${n.fontFamily};</li> <li><span class="property">font-size:</span> ${n.fontSize} / ${parseInt(n.fontSize||"NaN",10)/16}rem;</li> <li><span class="property">font-weight:</span> ${n.fontWeight};</li> <li><span class="property">font-variation-settings:</span> ${n.fontVariationSettings};</li> <li><span class="property">line-height:</span> ${"normal"!==n.lineHeight?`${parseInt(n.lineHeight||"NaN",10)}px / ${parseInt(n.lineHeight||"NaN",10)/16}rem`:"normal"};</li> <li><span class="property">letter-spacing:</span> ${n.letterSpacing};</li> <li><span class="property">font-style:</span> ${n.fontStyle};</li></ul>}`})(t,o.typography.useSyntaxHighlighting),r=`speccer-${o.slug}-${t.getAttribute("id")||O()}`;t.setAttribute("data-speccer-element-id",r);const s=vt(i,o,r);document.body.appendChild(s);const a=await(async(t,e,n)=>{const o=e.getBoundingClientRect(),i=bt(n),r=n.getBoundingClientRect(),s=await F(e),{typography:a,position:c}=t;if(a&&c===b.Right)return{left:s.left+o.width+i+"px",top:kt(D(s.top,r,o))+"px"};if(a&&c===b.Top)return{left:kt(W(s.left,r,o))+"px",top:s.top-r.height-i+"px"};if(a&&c===b.Bottom)return{left:kt(W(s.left,r,o))+"px",top:s.top+o.height+i+"px"};return{left:s.left-r.width-i+"px",top:kt(D(s.top,r,o))+"px"}})(o,t,s);X(s,a)},Lt=t=>{const e=()=>((t,e,n=!1)=>{let o;return function(i,...r){const s=n&&!o;o&&clearTimeout(o),o=setTimeout((function(){o=null,n||t.apply(i,r)}),e),s&&t.apply(i,r)}})((()=>{t()}),300);window.removeEventListener("resize",e),window.addEventListener("resize",e)},Bt=t=>{"loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>{t()})):t()},Rt=()=>{const t=new IntersectionObserver(((t,e)=>{for(const n of t)n.intersectionRatio>0&&(Ct(n.target),e.unobserve(n.target))}));for(const e of document.querySelectorAll(`[${p}^="${l}"],[${p}^="${l}"] *:not(td):not(tr):not(th):not(tfoot):not(thead):not(tbody)`))t.observe(e);const e=new IntersectionObserver(((t,e)=>{for(const n of t)n.intersectionRatio>0&&(tt(n.target),e.unobserve(n.target))}));for(const t of document.querySelectorAll(`[${p}^="${d}"]`))e.observe(t);const n=new IntersectionObserver(((t,e)=>{for(const n of t)n.intersectionRatio>0&&(J(n.target),e.unobserve(n.target))}));for(const t of document.querySelectorAll(`[${p}^="${u}"]`))n.observe(t);const o=new IntersectionObserver(((t,e)=>{for(const n of t)n.intersectionRatio>0&&(Pt(n.target),e.unobserve(n.target))}));for(const t of document.querySelectorAll(`[${p}^="${h}"]`))o.observe(t);const i=new IntersectionObserver(((t,e)=>{for(const n of t)n.intersectionRatio>0&&(U(n.target),e.unobserve(n.target))}));for(const t of document.querySelectorAll(`[${p}^="${f}"]`))i.observe(t);const r=new IntersectionObserver((async(t,e)=>{for(const n of t)n.intersectionRatio>0&&(await At(n.target),e.unobserve(n.target))}));for(const t of document.querySelectorAll(`[${p}="${g}"]`))r.observe(t)},Tt=t=>{window.speccer=t},Nt=t=>{const e=document.currentScript;if(e){const n=e.getAttribute("src");n?.includes("speccer.js")&&(e.hasAttribute("data-manual")?Tt(t):e.hasAttribute("data-instant")?t():e.hasAttribute("data-dom")?Bt(t):e.hasAttribute("data-lazy")?Rt():Bt(t),e.hasAttribute("data-manual")||e.hasAttribute("data-lazy")||Lt(t))}},qt=["alt","altgraph","capslock","control","fn","fnlock","hyper","meta","numlock","os","scrolllock","shift","super","symbol","command","ctrl","altgr","symbollock"],Mt=["escape","esc","enter","return","⏎","␛"],Ht=async(t,e,n)=>{await z();const o=bt(n),i=await _(n,e);if("tabstops"===t){let{left:t,top:e}=i.fromTop();return t-=32,e+=32,t<=0&&(t=32),e<=0&&(e=32),{left:`${t}px`,top:`${e}px`}}if("landmark"===t||"autocomplete"===t||"headings"===t){let{left:t,top:e}=i.fromLeft();return t-=o,t<=0&&(t=o),e<=0&&(e=o),{left:`${t}px`,top:`${e}px`}}if("region"===t){const{left:t,top:e,height:n,width:o}=i.fromTop();return{height:`${n}px`,width:`${o}px`,left:`${t}px`,top:`${e}px`}}if("shortcut"===t){const{left:t,top:e}=i.fromBottom();return{left:`${t}px`,top:`${e}px`}}const{left:r,top:s}=i.fromTop({center:!0,modifier:o});return{left:r-32+"px",top:s-32+"px"}},It=async(t,e,n)=>{if(!t||!t.checkVisibility())return;const o=((t="tabstops",e,n="span")=>{const o=document.createElement(n),i=a("ph-speccer speccer a11y",{tabstops:"tabstops"===t,landmark:"landmark"===t,autocomplete:"autocomplete"===t,headings:"headings"===t,region:"region"===t});if("landmark"===t&&e){const t=document.createTextNode(String(e));o.appendChild(t)}return s(o,i),o})(n,e);if("landmark"===n){const e=(t=>{if(!t)return"";if(t.role&&""!==t.role)return t.role;const e=t.nodeName.toLowerCase();return["header","footer","section","form","main","nav","aside"].includes(e)?e:"N/A"})(t),n=t.nodeName.toLowerCase();o.innerHTML=`<${n} role="${e}">`}if("autocomplete"===n){const e=t.getAttribute("autocomplete")||"";o.innerHTML=`autocomplete="${e}"`}"headings"===n&&(o.innerHTML=t.nodeName,o.classList.add(t.nodeName.toLowerCase())),"tabstops"===n&&o.setAttribute("data-speccer-a11y-tabstops",e);const i=`speccer-a11y-${t.getAttribute("id")||O()}`;o.setAttribute("data-speccer-id",i),document.body.appendChild(o);const r=await Ht(n,t,o);await X(o,r)},Ot=async(t,e)=>{const n=e.split(/\s\+\s/).map((t=>t.trim())),o=document.createElement("div"),i=a("ph-speccer speccer a11y shortcut-holder");s(o,i);for(const t of n){const e=document.createElement("kbd"),n=document.createTextNode(t),i=a("ph-speccer speccer a11y shortcut",{modifier:qt.includes(t.toLowerCase()),physical:Mt.includes(t.toLowerCase())});s(e,i),e.appendChild(n);const r=`speccer-a11y-shortcut-${O()}`;o.setAttribute("data-speccer-id",r),o.appendChild(e)}document.body.appendChild(o);const r=await Ht("shortcut",t,o);await X(o,r)},Vt=()=>{const t=document.querySelectorAll('[data-speccer*="a11y tabstops"]'),e=document.querySelectorAll('[data-speccer*="a11y landmark"]'),n=document.querySelectorAll('[data-speccer*="a11y shortcut"]'),o=document.querySelectorAll('[data-speccer*="a11y autocomplete"]'),i=document.querySelectorAll('[data-speccer*="a11y headings"]');if(n.length)for(const t of n){const e=t.getAttribute("data-speccer-a11y-shortcut");e&&""!==e&&!V(t)&&Ot(t,e)}if(t.length)for(const e of t){const t=e.querySelectorAll("\n a[href], area[href], input:not([disabled]):not([tabindex='-1']),\n button:not([disabled]):not([tabindex='-1']),select:not([disabled]):not([tabindex='-1']),\n textarea:not([disabled]):not([tabindex='-1']),\n iframe, object, embed, *[tabindex]:not([tabindex='-1']), *[contenteditable=true]\n");for(const[e,n]of t.entries()){if(!V(n)){It(n,e+1,"tabstops");continue}const t=n.getAttribute("id");if(!t)continue;const o=document.querySelector(`[for="${t}"]`);o&&!V(o)&&It(o,e+1,"tabstops")}}if(o.length)for(const t of o){const e=t.querySelectorAll("[autocomplete]");for(const t of e)V(t)||It(t,null,"autocomplete")}if(i.length)for(const t of i){const e=t.querySelectorAll('h1,h2,h3,h4,h5,h6, [role="heading"]');for(const t of e)V(t)||It(t,null,"headings")}if(e.length)for(const t of e){const e=t.querySelectorAll('\nheader, footer, section, form, main, nav, aside, [role="section"], [role="banner"],\n[role="complementary"], [role="contentinfo"], [role="form"], [role="main"],\n[role="navigation"], [role="region"], [role="search"]\n');for(const[t,n]of e.entries())V(n)||(It(n,t+1,"landmark"),It(n,null,"region"))}},zt={create:K,element:U},Gt={create:St,element:Ct},jt={createPinElement:et,pinElement:$t,pinElements:At},Wt={create:Q,element:tt},Dt={create:Z,element:J},Ft={create:vt,element:Pt},_t={dom:Bt,lazy:Rt,manual:Tt,activate:Nt},Xt=()=>{((t,e=document)=>{[].forEach.call(e.querySelectorAll(t),(function(t){t.remove()}))})(".ph-speccer.speccer");const t=document.querySelectorAll(`[${p}^="${l}"]`),e=document.querySelectorAll(`[${p}^="${d}"]`),n=document.querySelectorAll(`[${p}^="${h}"]`),o=document.querySelectorAll(`[${p}="${g}"]`),i=document.querySelectorAll(`[${p}^="${u}"]`),r=document.querySelectorAll(`[${p}^="${f}"]`);for(const t of i)J(t);for(const t of r)U(t);for(const e of t)if(Ct(e),e.hasChildNodes()){const t=e.querySelectorAll("*:not(td):not(tr):not(th):not(tfoot):not(thead):not(tbody):not([data-speccer])"),n=e.getAttribute("data-speccer")||"";if(t?.length)for(const e of t)e.setAttribute("data-speccer",n),Ct(e)}for(const t of e)tt(t);for(const t of n)Pt(t);for(const t of o)At(t);Vt()};Nt(Xt),t.a11y=Vt,t.default=Xt,t.grid=zt,t.mark=Dt,t.measure=Wt,t.modes=_t,t.pin=jt,t.removeSpeccerElement=t=>{const e=t.getAttribute("data-speccer-element-id");if(!e)return;const n=document.getElementById(e)||document.querySelectorAll(`[data-speccer-id="${e}"]`);if(n)if(Object.prototype.isPrototypeOf.call(NodeList.prototype,n))[...n].forEach((t=>t.remove()));else if(n.classList.contains("curly")||n.classList.contains("svg")){const e=t.getAttribute("id");document.querySelectorAll(`#ph-speccer-svg path[data-start-el="${e}"]`).forEach((t=>t.remove()))}},t.spacing=Gt,t.typography=Ft,Object.defineProperty(t,"__esModule",{value:!0})}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phun-ky/speccer",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.3.0",
|
|
4
4
|
"description": "A script to annotate, show spacing specs and to display typography information in documentation/website on HTML elements",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"a11y",
|
|
@@ -63,6 +63,10 @@
|
|
|
63
63
|
"commit": "npx git-cz",
|
|
64
64
|
"dev": "npx browser-sync start --server 'dev' --files 'dist' --ss 'dist'",
|
|
65
65
|
"docs:gen": "node ./node_modules/.bin/typedoc",
|
|
66
|
+
"predocs:dev": "npm run docs:gen",
|
|
67
|
+
"docs:dev": "vitepress dev docs",
|
|
68
|
+
"docs:build": "vitepress build docs",
|
|
69
|
+
"docs:preview": "vitepress preview docs",
|
|
66
70
|
"postcss": "rm -rf ./dist/speccer.min.css && postcss ./dist/speccer.css -o ./dist/speccer.min.css",
|
|
67
71
|
"release": "release-it",
|
|
68
72
|
"prerollup:dev": "npm run clean && npm run styles",
|
|
@@ -99,9 +103,9 @@
|
|
|
99
103
|
"eslint-config-phun-ky": "^1.0.0",
|
|
100
104
|
"git-cz": "^4.9.0",
|
|
101
105
|
"glob": "^11.0.1",
|
|
102
|
-
"global-jsdom": "^
|
|
106
|
+
"global-jsdom": "^27.0.0",
|
|
103
107
|
"globals": "^16.0.0",
|
|
104
|
-
"jsdom": "^
|
|
108
|
+
"jsdom": "^27.0.0",
|
|
105
109
|
"postcss": "^8.5.2",
|
|
106
110
|
"postcss-cli": "^11.0.0",
|
|
107
111
|
"prettier": "3.6.2",
|
|
@@ -124,8 +128,11 @@
|
|
|
124
128
|
"typedoc-plugin-no-inherit": "^1.4.0",
|
|
125
129
|
"typedoc-plugin-remark": "^2.0.0",
|
|
126
130
|
"typedoc-plugin-rename-defaults": "^0.7.1",
|
|
131
|
+
"typedoc-vitepress-theme": "^1.1.2",
|
|
127
132
|
"typescript": "^5.7.3",
|
|
128
|
-
"unified-prettier": "^2.0.1"
|
|
133
|
+
"unified-prettier": "^2.0.1",
|
|
134
|
+
"vitepress": "^1.6.4",
|
|
135
|
+
"vitepress-plugin-group-icons": "^1.6.3"
|
|
129
136
|
},
|
|
130
137
|
"engines": {
|
|
131
138
|
"node": ">=22.9.0",
|