@phun-ky/speccer 11.2.45 → 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 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
- - [Grid spacing](#grid-spacing)
58
- - [Mark elements](#mark-elements)
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/pen/OJejexN).
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
  ![Screenshot of typography with different syntax theme](./public/speccer-typography-syntax-light.png)
681
681
 
682
- ### Grid spacing
682
+ ## Grid spacing
683
683
 
684
684
  ![Screenshot of grid feature](./public/speccer-grid-full-light.png)
685
685
 
@@ -700,7 +700,7 @@ In your component examples, use the following attribute on your grid container.
700
700
 
701
701
  ![Screenshot of grid feature](./public/speccer-grid-full-dark.png)
702
702
 
703
- ### Mark elements
703
+ ## Mark elements
704
704
 
705
705
  ![Screenshot of marked elements](./public/speccer-pin-mark-light.png)
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/README.md).
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
+ * ![Screenshot of speccer with custom literals](https://github.com/phun-ky/speccer/blob/main/public/literals.png?raw=true)
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
+ * ![pin](https://github.com/phun-ky/speccer/blob/main/public/speccer-a11y-tabstops-light.png?raw=true)
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
- * ![Screenshot of speccer with custom literals](https://github.com/phun-ky/speccer/blob/main/public/literals.png?raw=true)
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
+ * ![pin](https://github.com/phun-ky/speccer/blob/main/public/speccer-grid-full-light.png?raw=true)
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
+ * ![pin](https://github.com/phun-ky/speccer/blob/main/public/speccer-spacing-dark.png?raw=true)
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
+ * ![pin](https://github.com/phun-ky/speccer/blob/main/public/anatomy.png?raw=true)
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 | void>;
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
+ * ![pin](https://github.com/phun-ky/speccer/blob/main/public/speccer-pin-measure-height-light.png?raw=true)
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
+ * ![pin](https://github.com/phun-ky/speccer/blob/main/public/speccer-pin-mark-light.png?raw=true)
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
+ * ![pin](https://github.com/phun-ky/speccer/blob/main/public/speccer-typography-light.png?raw=true)
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 };
@@ -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.2.45
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=`&lt;${n} role="${e}"&gt;`}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=`&lt;${n} role="${e}"&gt;`}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.2.45
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=`&lt;${n} role="${e}"&gt;`}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=`&lt;${n} role="${e}"&gt;`}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.2.45",
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",
@@ -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",