@phun-ky/speccer 9.0.13 → 9.1.1
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 +42 -1
- package/dist/speccer.css +115 -0
- package/dist/speccer.esm.js +27 -1
- package/dist/speccer.esm.js.map +1 -1
- package/dist/speccer.js +27 -1
- package/dist/speccer.js.map +1 -1
- package/dist/speccer.min.css +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -27,8 +27,13 @@
|
|
|
27
27
|
- [Curly brackets](#curly-brackets)
|
|
28
28
|
- [Element typography](#element-typography)
|
|
29
29
|
- [Mark elements](#mark-elements)
|
|
30
|
+
- [A11y notation](#a11y-notation)
|
|
31
|
+
- [Tab stops](#tab-stops)
|
|
32
|
+
- [Landmarks and regions](#landmarks-and-regions)
|
|
33
|
+
- [Keys and shortcut](#keys-and-shortcut)
|
|
30
34
|
- [Customization](#customization)
|
|
31
35
|
- [Contributing](#contributing)
|
|
36
|
+
- [Sponsor me](#sponsor-me)
|
|
32
37
|
|
|
33
38
|
## About
|
|
34
39
|
|
|
@@ -313,9 +318,37 @@ In your component examples, use the following attribute.
|
|
|
313
318
|
<div data-speccer-mark …>…</div>
|
|
314
319
|
```
|
|
315
320
|
|
|
321
|
+
### A11y notation
|
|
322
|
+
|
|
323
|
+
With speccer, you can also display accessibility notation, like [Accessibility Bluelines](https://dribbble.com/shots/6269661-Accessibility-Bluelines?utm_source=Clipboard_Shot&utm_campaign=jeremyelder&utm_content=Accessibility%20Bluelines&utm_medium=Social_Share&utm_source=Clipboard_Shot&utm_campaign=jeremyelder&utm_content=Accessibility%20Bluelines&utm_medium=Social_Share):
|
|
324
|
+
|
|
325
|
+
Prior art: [Jeremy Elder](https://twitter.com/JeremyElder)
|
|
326
|
+
|
|
327
|
+
#### Tab stops
|
|
328
|
+
|
|
329
|
+

|
|
330
|
+
|
|
331
|
+
If you want to display tab stops, append `data-speccer-a11y-tabstops` as an attribute to the container you want to display the tab stops in.
|
|
332
|
+
|
|
333
|
+
#### Landmarks and regions
|
|
334
|
+
|
|
335
|
+

|
|
336
|
+
|
|
337
|
+
If you want to display landmarks and regions, append `data-speccer-a11y-landmark` as an attribute to the container you want to display the landmarks and regions in.
|
|
338
|
+
|
|
339
|
+
#### Keys and shortcut
|
|
340
|
+
|
|
341
|
+

|
|
342
|
+
|
|
343
|
+
If you want to display the shortcut with keys used for elements, use `data-speccer-a11y-shortcut="<shortcut>"` on the element that uses this shortcut:
|
|
344
|
+
|
|
345
|
+
```html
|
|
346
|
+
<button type="button" data-speccer-a11y-shortcut="ctrl + s">Save</button>
|
|
347
|
+
```
|
|
348
|
+
|
|
316
349
|
## Customization
|
|
317
350
|
|
|
318
|
-

|
|
319
352
|
|
|
320
353
|
Allthough the styling works nicely with dark mode, you can use the provided CSS variables to customize the look and feel. If more control is needed, you can use CSS overrides :)
|
|
321
354
|
|
|
@@ -352,3 +385,11 @@ Allthough the styling works nicely with dark mode, you can use the provided CSS
|
|
|
352
385
|
## Contributing
|
|
353
386
|
|
|
354
387
|
If you want to contribute, please read the [CONTRIBUTING.md](https://github.com/phun-ky/speccer/blob/main/CONTRIBUTING.md) and [CODE_OF_CONDUCT.md](https://github.com/phun-ky/speccer/blob/main/CODE_OF_CONDUCT.md)
|
|
388
|
+
|
|
389
|
+
## Sponsor me
|
|
390
|
+
|
|
391
|
+
I'm an Open Source evangelist, creating stuff that does not exist yet to help get rid of secondary activities and to enhance systems already in place, be it documentation or web sites.
|
|
392
|
+
|
|
393
|
+
The sponsorship is an unique opportunity to alleviate more hours for me to maintain my projects, create new ones and contribute to the large community we're all part of :)
|
|
394
|
+
|
|
395
|
+
[Support me with GitHub Sponsors](https://github.com/sponsors/phun-ky).
|
package/dist/speccer.css
CHANGED
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
--ph-speccer-line-width: 1px;
|
|
25
25
|
--ph-speccer-line-width-negative: -1px;
|
|
26
26
|
--ph-speccer-measure-size: 8px;
|
|
27
|
+
--ph-speccer-a11y-color-background: #1868b2;
|
|
28
|
+
--ph-speccer-a11y-landmark-color-background: #7e60c5;
|
|
27
29
|
}
|
|
28
30
|
svg.ph-speccer,
|
|
29
31
|
.ph-speccer.speccer,
|
|
@@ -736,3 +738,116 @@ svg.ph-speccer .ph-speccer.path {
|
|
|
736
738
|
border-style: solid;
|
|
737
739
|
position: absolute;
|
|
738
740
|
}
|
|
741
|
+
[data-speccer-a11y] {
|
|
742
|
+
counter-reset: speccer-a11y-tabstops;
|
|
743
|
+
}
|
|
744
|
+
.ph-speccer.speccer.a11y.tabstops {
|
|
745
|
+
position: absolute;
|
|
746
|
+
height: 48px;
|
|
747
|
+
width: 48px;
|
|
748
|
+
background-color: var(--ph-speccer-a11y-color-background);
|
|
749
|
+
border-radius: 0.5rem;
|
|
750
|
+
color: var(--ph-speccer-color-text-light);
|
|
751
|
+
font-family: var(--ph-speccer-font-family);
|
|
752
|
+
counter-increment: speccer-a11y-tabstops;
|
|
753
|
+
border: 3px solid var(--ph-speccer-a11y-color-background);
|
|
754
|
+
}
|
|
755
|
+
.ph-speccer.speccer.a11y.tabstops::before {
|
|
756
|
+
position: absolute;
|
|
757
|
+
top: calc(0.5rem - 2px);
|
|
758
|
+
left: calc(0.5rem - 2px);
|
|
759
|
+
content: counter(speccer-a11y-tabstops);
|
|
760
|
+
font-size: 12px;
|
|
761
|
+
text-align: left;
|
|
762
|
+
}
|
|
763
|
+
.ph-speccer.speccer.a11y.tabstops::after {
|
|
764
|
+
display: flex;
|
|
765
|
+
justify-content: flex-end;
|
|
766
|
+
align-items: flex-end;
|
|
767
|
+
position: absolute;
|
|
768
|
+
left: 0.5rem;
|
|
769
|
+
right: 0.5rem;
|
|
770
|
+
bottom: 0.5rem;
|
|
771
|
+
height: 2rem;
|
|
772
|
+
content: "⇥";
|
|
773
|
+
font-size: 2rem;
|
|
774
|
+
color: var(--ph-speccer-color-text-light);
|
|
775
|
+
font-family: var(--ph-speccer-font-family);
|
|
776
|
+
}
|
|
777
|
+
.ph-speccer.speccer.a11y.landmark {
|
|
778
|
+
position: absolute;
|
|
779
|
+
height: 48px;
|
|
780
|
+
width: 48px;
|
|
781
|
+
background-color: var(--ph-speccer-a11y-landmark-color-background);
|
|
782
|
+
border-radius: 0.5rem;
|
|
783
|
+
color: var(--ph-speccer-color-text-light);
|
|
784
|
+
font-family: var(--ph-speccer-font-family);
|
|
785
|
+
border: 3px solid var(--ph-speccer-a11y-landmark-color-background);
|
|
786
|
+
box-shadow: inset 0 0 0 2px var(--ph-speccer-color-text-light);
|
|
787
|
+
justify-content: center;
|
|
788
|
+
font-size: 1rem;
|
|
789
|
+
line-height: 100%;
|
|
790
|
+
align-items: center;
|
|
791
|
+
padding: 0.5rem;
|
|
792
|
+
pointer-events: auto;
|
|
793
|
+
}
|
|
794
|
+
.ph-speccer.speccer.a11y.landmark::after {
|
|
795
|
+
top: 100%;
|
|
796
|
+
left: 50%;
|
|
797
|
+
border: solid transparent;
|
|
798
|
+
content: "";
|
|
799
|
+
height: 0;
|
|
800
|
+
width: 0;
|
|
801
|
+
position: absolute;
|
|
802
|
+
pointer-events: none;
|
|
803
|
+
border-color: rgba(126,96,197,0);
|
|
804
|
+
border-top-color: var(--ph-speccer-a11y-landmark-color-background);
|
|
805
|
+
border-width: 12px;
|
|
806
|
+
margin-left: -12px;
|
|
807
|
+
}
|
|
808
|
+
.ph-speccer.speccer.a11y.region {
|
|
809
|
+
position: absolute;
|
|
810
|
+
outline: 2px solid var(--ph-speccer-a11y-landmark-color-background);
|
|
811
|
+
outline-offset: 2px;
|
|
812
|
+
}
|
|
813
|
+
.ph-speccer.speccer.a11y.shortcut-holder {
|
|
814
|
+
position: absolute;
|
|
815
|
+
height: 48px;
|
|
816
|
+
min-width: 120px;
|
|
817
|
+
display: flex;
|
|
818
|
+
flex-direction: row;
|
|
819
|
+
justify-content: flex-start;
|
|
820
|
+
align-items: center;
|
|
821
|
+
grid-gap: 0.5rem;
|
|
822
|
+
}
|
|
823
|
+
.ph-speccer.speccer.a11y.shortcut-holder kbd.ph-speccer.speccer.a11y.shortcut {
|
|
824
|
+
flex-shrink: 0;
|
|
825
|
+
position: relative;
|
|
826
|
+
background-color: var(--ph-speccer-a11y-color-background);
|
|
827
|
+
border-radius: 0.5rem;
|
|
828
|
+
color: var(--ph-speccer-color-text-light);
|
|
829
|
+
font-family: var(--ph-speccer-font-family);
|
|
830
|
+
display: inline-flex;
|
|
831
|
+
text-transform: uppercase;
|
|
832
|
+
height: 48px;
|
|
833
|
+
border: 3px solid var(--ph-speccer-a11y-color-background);
|
|
834
|
+
min-width: 48px;
|
|
835
|
+
font-size: 1.5rem;
|
|
836
|
+
justify-content: center;
|
|
837
|
+
align-items: center;
|
|
838
|
+
}
|
|
839
|
+
.ph-speccer.speccer.a11y.shortcut-holder kbd.ph-speccer.speccer.a11y.shortcut.modifier {
|
|
840
|
+
justify-content: flex-start;
|
|
841
|
+
align-items: flex-end;
|
|
842
|
+
padding: 0.25rem;
|
|
843
|
+
font-size: 1rem;
|
|
844
|
+
width: 80px;
|
|
845
|
+
text-transform: lowercase;
|
|
846
|
+
}
|
|
847
|
+
.ph-speccer.speccer.a11y.shortcut-holder kbd.ph-speccer.speccer.a11y.shortcut.physical {
|
|
848
|
+
justify-content: flex-start;
|
|
849
|
+
align-items: flex-end;
|
|
850
|
+
padding: 0.25rem;
|
|
851
|
+
font-size: 1rem;
|
|
852
|
+
text-transform: lowercase;
|
|
853
|
+
}
|
package/dist/speccer.esm.js
CHANGED
|
@@ -1,2 +1,28 @@
|
|
|
1
|
-
var t,e,o;!function(t){t.Empty="",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top"}(t||(t={})),function(t){t.Outline="outline",t.Enclose="enclose",t.Full="full",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top",t.SVG="svg",t.Curly="curly"}(e||(e={})),function(t){t.Width="width",t.Height="height",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top"}(o||(o={}));const i=t=>t.split(" "),n=t=>i(t).includes(e.Right),r=t=>i(t).includes(e.Bottom),s=t=>i(t).includes(e.Full),a=t=>i(t).includes(e.Enclose),p=t=>t.includes(e.Curly)&&t.includes(e.Full),c=t=>"string"==typeof t,l=t=>!c(t),h=t=>"number"==typeof t,d=t=>!h(t),f=t=>void 0===t,m=()=>new Promise(requestAnimationFrame),u=t=>t.top,g=t=>t.left+t.width,y=t=>t.top+t.height,w=t=>t.left,x=t=>t.left+t.width/2,b=t=>t.top+t.height/2,E={center:t=>({x:x(t),y:b(t)}),top:t=>({x:x(t),y:u(t)}),right:t=>({x:g(t),y:b(t)}),bottom:t=>({x:x(t),y:y(t)}),left:t=>({x:w(t),y:b(t)}),"right-top":t=>({x:g(t),y:u(t)}),"right-bottom":t=>({x:g(t),y:y(t)}),"left-top":t=>({x:w(t),y:u(t)}),"left-bottom":t=>({x:w(t),y:y(t)}),"top-left":t=>({x:w(t),y:u(t)}),"top-right":t=>({x:g(t),y:u(t)}),"bottom-left":t=>({x:w(t),y:y(t)}),"bottom-right":t=>({x:g(t),y:y(t)}),"top-center":t=>({x:x(t),y:u(t)}),"right-center":t=>({x:g(t),y:b(t)}),"bottom-center":t=>({x:x(t),y:y(t)}),"left-center":t=>({x:w(t),y:b(t)})},$=async(t,e="center")=>{if(!e)throw Error("No position given");if(l(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 m();const i=t.getBoundingClientRect();return E[e](i)},A=async(t,e,o="center",i="center")=>{if(!t||!e)throw Error("No element given");const{x:n,y:r}=await $(t,o),{x:s,y:a}=await $(e,i);return{x1:n,y1:r,x2:s,y2:a}},v=(t,e)=>{const{x1:o,x2:i,y1:n,y2:r}=t,{direct:s=!1,firstSet:a=!1,direction:p}=e;let c={x:o+(i-o)/2,y:n},l={x:o+(i-o)/2,y:r};return s&&(a?"west"===p?(c={x:o-32,y:n-8},l={x:i+32,y:r}):"south"===p?(c={x:o-8,y:n+32},l={x:i,y:r-32}):"east"===p?(c={x:o+32,y:n-8},l={x:i-32,y:r}):(c={x:o-8,y:n-32},l={x:i,y:r+32}):"west"===p?(c={x:o-32,y:n+8},l={x:i+32,y:r}):"south"===p?(c={x:o+8,y:n+32},l={x:i,y:r-32}):"east"===p?(c={x:o+32,y:n+8},l={x:i-32,y:r}):(c={x:o+8,y:n-32},l={x:i,y:r+32})),{firstPoint:{x:o,y:n},firstControl:c,lastPoint:{x:i,y:r},lastControl:l}},S=async(t,e,o)=>{const{pos1:i,pos2:n,firstSet:r=!1,direction:s}=o,{x1:a,y1:p,x2:c,y2:l}=await A(t,e,i,n);let h=0,d=0;"north"===s?d=8:"west"===s?h=8:"east"===s?h=-8:"south"===s&&(d=-8);const{firstPoint:f,firstControl:m,lastControl:u,lastPoint:g}=v({x1:a+0,x2:c+h,y1:p+0+document.documentElement.scrollTop,y2:l+d+document.documentElement.scrollTop},{direct:!0,firstSet:r,direction:s});return`M ${f.x} ${f.y}C ${m.x} ${m.y}, ${u.x} ${u.y}, ${g.x} ${g.y}`},P=async({start:t,stop:e,crude:o=!1})=>{const{x1:i,y1:n,x2:r,y2:s}=await A(t,e),a=((t,e,o,i,n=!0)=>{if(f(t)||f(e)||f(o)||f(i))throw new SyntaxError("Missing input for `angle`");if(d(t)||d(e)||d(o)||d(i))throw TypeError(`Parameters for \`angle\` do not have the required type. Requires number! Got: ${typeof t} ${typeof e} ${typeof o} ${typeof i}`);const r=i-e,s=o-t;let a=Math.atan2(r,s);return a*=180/Math.PI,n&&a<0&&(a+=360),a})(i,n,r,s);return o?(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"})(a):(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"})(a)},C=()=>"_"+Math.random().toString(36).substring(2,11),B=async(t,e)=>{var o;if(!(!t||!e||c(e)||h(e)||(o=e,"boolean"==typeof o)||Array.isArray(e)&&!e.length||!Object.keys(e).length&&e.constructor===Object))if(await m(),Array.isArray(e))for(const o of e)t.style[o.key]=o.value;else for(const o of Object.keys(e))t.style[o]=e[o]},R=async t=>(await m(),getComputedStyle(t,null));class L{#t;#e;startElement;stopElement;firstPathElement;secondPathElement;constructor(t,e){this.#o(t,e)}#o(t,e){if(!t||!e)throw new Error("Missing inputs startElement and stopElement");if(!document.body.contains(e))throw new Error("stopElement is not in the DOM");if(!document.body.contains(t))throw new Error("startElement is not in the DOM");if(this.startElement=t,this.stopElement=e,this.#t=document.getElementById("ph-speccer-svg"),this.#e=document.getElementById("ph-speccer-path"),!this.#e||!this.#t)throw new Error("Missing required SVG element to draw lines. Please see the documentation");B(this.#t,{height:`${document.body.scrollHeight}px`}),this.connect()}connect(){this.draw(this.#e)}#i(t){if(!t)throw new Error("No path given to #getPathElement!");const e=`ph_draw_path-path-${C()}`,o=t.cloneNode(!1),i=this.startElement.getAttribute("id")||C();return this.startElement.setAttribute("id",i),o.setAttribute("data-start-el",i),o.setAttribute("id",e),o.classList.remove("original"),o.classList.add("speccer"),o}async draw(t){if(!t)throw new Error("No path given to draw!");const e=this.#i(t),o=this.#i(t);if(!t.parentNode)throw new Error("No parentNode found for path");this.firstPathElement=t.parentNode.insertBefore(e,t.nextSibling),this.secondPathElement=t.parentNode.insertBefore(o,t.nextSibling);const i=await P({stop:this.stopElement,start:this.startElement,crude:!0}),{path1pos1:n,path1pos2:r,path2pos1:s,path2pos2:a}=(t=>{let e,o,i,n;switch(t){case"east":e="right-top",o="left-center",i="right-bottom",n="left-center";break;case"south":e="bottom-left",o="top-center",i="bottom-right",n="top-center";break;case"west":e="left-top",o="right-center",i="left-bottom",n="right-center";break;default:e="top-left",o="bottom-center",i="top-right",n="bottom-center"}return{path1pos1:e,path1pos2:o,path2pos1:i,path2pos2:n}})(i),p=await S(this.startElement,this.stopElement,{pos1:n,pos2:r,firstSet:!0,direction:i}),c=await S(this.startElement,this.stopElement,{pos1:s,pos2:a,direction:i});this.firstPathElement.setAttribute("data-direction",i),this.firstPathElement.setAttribute("data-pos1",n),this.firstPathElement.setAttribute("data-pos2",r),this.firstPathElement.setAttribute("d",p),this.secondPathElement.setAttribute("data-direction",i),this.secondPathElement.setAttribute("data-pos1",s),this.secondPathElement.setAttribute("data-pos2",a),this.secondPathElement.setAttribute("d",c)}}window.DrawSVGCurlyBracket=L;class T{#t;#e;startElement;stopElement;line;constructor(t,e){this.#o(t,e)}#o(t,e){if(!t||!e)throw new Error("Missing inputs startElement and stopElement");if(!document.body.contains(e))throw new Error("stopElement is not in the DOM");if(!document.body.contains(t))throw new Error("startElement is not in the DOM");if(this.startElement=t,this.stopElement=e,this.#t=document.getElementById("ph-speccer-svg"),this.#e=document.getElementById("ph-speccer-path"),!this.#e||!this.#t)throw new Error("Missing required SVG element to draw lines. Please see the documentation");B(this.#t,{height:`${document.body.scrollHeight}px`}),this.connect()}connect(){this.draw(this.#e)}async draw(t){if(!t)throw new Error("No path given to draw!");const e=`ph_draw_path-path-${C()}`,o=t.cloneNode(!1),i=this.startElement.getAttribute("id")||C();if(this.startElement.setAttribute("id",i),o.setAttribute("id",e),o.setAttribute("data-start-el",i),o.classList.remove("original"),o.classList.add("speccer"),!t.parentNode)throw new Error("No parentNode found for path");this.line=t.parentNode.insertBefore(o,t.nextSibling);const n=await P({start:this.startElement,stop:this.stopElement,crude:!0}),{pos1:r,pos2:s}=(t=>{let e,o;switch(t){case"east":e="right",o="left";break;case"south":e="bottom",o="top";break;case"west":e="left",o="right";break;default:e="top",o="bottom"}return{pos1:e,pos2:o}})(n),a=await(async(t,e,o)=>{const{pos1:i,pos2:n}=o,{x1:r,y1:s,x2:a,y2:p}=await A(t,e,i,n),{firstPoint:c,firstControl:l,lastControl:h,lastPoint:d}=v({x1:r,x2:a,y1:s,y2:p},{direction:""});return`M ${c.x} ${c.y}C ${l.x} ${l.y}, ${h.x} ${h.y}, ${d.x} ${d.y}`})(this.startElement,this.stopElement,{pos1:r,pos2:s});this.line.setAttribute("data-direction",n),this.line.setAttribute("data-pos1",r),this.line.setAttribute("data-pos2",s),this.line.setAttribute("d",a)}}window.DrawSVGLine=T;const N=(t,e,o="noop")=>{t&&(!e||e&&!e.length||e.trim().split(" ").filter((t=>t!==o)).forEach((e=>t.classList.add(e))))},I=(t,e)=>t?!e&&l(t)?Object.keys(t).filter((e=>t[e])).join(" ").trim():`${t.trim()} ${e?Object.keys(e).filter((t=>e[t])).join(" "):""}`.trim():"",M=[..."ABCDEFGHIJKLMNOPQRSTUVWXYZ"],O=t=>parseInt(t,10),q=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"):"",H=t=>O(getComputedStyle(t).getPropertyValue("--ph-speccer-pin-space"))||48,k=(t,e,o)=>t-e.width/2+o.width/2,V=(t,e,o)=>t-e.height/2+o.height/2,W=async t=>{await m();const e=t.getBoundingClientRect(),o=e.top+window.scrollY,i=e.left+window.scrollX;return{height:e.height,width:e.width,top:o,left:i}},z=async(t,e)=>{await m();const o=t.getBoundingClientRect(),i=await W(e),n=await(async(t,e)=>{await m();const o=t.getBoundingClientRect(),i=e.getBoundingClientRect(),n=i.top+window.scrollY,r=i.left+window.scrollX;return{height:i.height,width:i.width,top:V(n,o,i),left:k(r,o,i)}})(t,e),r=i.height,s=i.width,a=o.height,p=o.width;return{absolute:()=>({top:i.top,left:i.left,height:r,width:s}),toTop:({center:t=!1,sourceHeight:e=a,modifier:o=0}={})=>({top:i.top+e+o,left:t?n.left:i.left,height:r,width:s}),fromTop:({center:t=!1,sourceHeight:e=a,modifier:o=0}={})=>({top:i.top-e-o,left:t?n.left:i.left,height:r,width:s}),toBottom:({center:t=!1,sourceHeight:e=a,targetHeight:o=r,modifier:p=0}={})=>({top:i.top+o-(e+p),left:t?n.left:i.left,height:r,width:s}),fromBottom:({center:t=!1,targetHeight:e=r,modifier:o=0}={})=>({top:i.top+e+o,left:t?n.left:i.left,height:r,width:s}),toLeft:({center:t=!1,sourceWidth:e=p,modifier:o=0}={})=>({top:t?n.top:i.top,left:i.left+e+o,height:r,width:s}),fromLeft:({center:t=!1,sourceWidth:e=p,modifier:o=0}={})=>({top:t?n.top:i.top,left:i.left-e-o,height:r,width:s}),toRight:({center:t=!1,sourceWidth:e=p,targetWidth:o=s,modifier:a=0}={})=>({top:t?n.top:i.top,left:i.left+o-(e+a),height:r,width:s}),fromRight:({center:t=!1,targetWidth:e=s,modifier:o=0}={})=>({top:t?n.top:i.top,left:i.left+e+o,height:r,width:s})}},j=async(t,o,p,c)=>{await m();const{isCurly:l=!1}=c||{},h=H(p),d=O(getComputedStyle(p).getPropertyValue("--ph-speccer-measure-size"))||8;const f=await z(p,o);if(a(t)){const{left:t,top:e,height:o,width:i}=f.absolute();return{left:`${t}px`,top:`${e}px`,height:`${o}px`,width:`${i}px`}}if(i(t).includes(e.Left)){if(s(t)&&!l){const{left:t,top:e,height:o}=f.fromLeft({sourceWidth:d});return{left:`${t}px`,top:`${e}px`,height:`${o}px`}}const{left:e,top:o}=f.fromLeft({center:!0,modifier:l?h/1.5:h});return{left:`${e}px`,top:`${o}px`}}if(n(t)){if(s(t)&&!l){const{left:t,top:e,height:o}=f.fromRight({center:!1});return{left:`${t}px`,top:`${e}px`,height:`${o}px`}}const{left:e,top:o}=f.fromRight({center:!0,modifier:l?h/1.5:h});return{left:`${e}px`,top:`${o}px`}}if(r(t)){if(s(t)&&!l){const{left:t,top:e,width:o}=f.fromBottom({center:!1});return{left:`${t}px`,top:`${e}px`,width:`${o}px`}}const{left:e,top:o}=f.fromBottom({center:!0,modifier:l?h/1.5:h});return{left:`${e}px`,top:`${o}px`}}if(s(t)&&!l){const{left:t,top:e,width:o}=f.fromTop({center:!1});return{left:`${t}px`,top:`${e}px`,width:`${o}px`}}const{left:u,top:g}=f.fromTop({center:!0,modifier:l?h/1.5:h});return{left:`${u}px`,top:`${g}px`}},F=(t="",e,o="span")=>{const i=document.createElement(o),n=document.createTextNode(t),r={};null!==e&&""!==e&&(r[e]=!0),!s(e)&&!a(e)||s(e)&&p(e)?i.appendChild(n):(s(e)||a(e))&&i.setAttribute("data-dissection-counter",t);const c=I("ph-speccer speccer dissection",r);return N(i,c),i},D=async t=>{if(!t)return;const o=t.querySelectorAll("[data-anatomy]");if(o){let t=0;o.forEach((async(o,i)=>{if(!o)return;const n=o.getAttribute("data-anatomy")||"";if(!n||""===n||!n.includes(e.Outline))return;let r=M[i];r||(r=`${M[t]}${M[t].toLowerCase()}`,t++);const s=F(r,n);document.body.appendChild(s);const a=await j(n,o,s,{isCurly:p(n)});await B(s,a),n.includes(e.SVG)&&!p(n)?new T(o,s):p(n)&&new L(o,s)}))}},G=(t="",e="",o="span")=>{const i=document.createElement(o);return i.setAttribute("title",`${t}px`),i.setAttribute("data-measure",`${parseInt(`${t}`,10)}px`),N(i,`ph-speccer speccer measure ${e}`),i},_=async t=>{if(!t)return;const e=t.getAttribute("data-speccer-measure");if(""===e||!e)return;const s=await R(t);if("none"===s.display||"0"===s.opacity||"hidden"===s.visibility)return;await m();const a=t.getBoundingClientRect();if(i(e).includes(o.Width))if(r(e)){const o=G(a.width,e);document.body.appendChild(o);const i=await z(o,t),{left:n,top:r,width:s}=i.fromBottom({center:!1});await B(o,{left:`${n}px`,top:`${r}px`,width:`${s}px`})}else{const o=G(a.width,e);document.body.appendChild(o);const i=await z(o,t),{left:n,top:r,width:s}=i.fromTop({center:!1,modifier:-8});await B(o,{left:`${n}px`,top:`${r}px`,width:`${s}px`})}else if((t=>i(t).includes(o.Height))(e))if(n(e)){const o=G(a.height,e);document.body.appendChild(o);const i=await z(o,t),{left:n,top:r,height:s}=i.fromRight({center:!1});await B(o,{left:`${n}px`,top:`${r}px`,height:`${s}px`})}else{const o=G(a.height,e);document.body.appendChild(o);const i=await z(o,t),{left:n,top:r,height:s}=i.fromLeft({center:!1,modifier:-8});await B(o,{left:`${n}px`,top:`${r}px`,height:`${s}px`})}},X=async(t,e,o,i)=>{await m();const n=i.getBoundingClientRect(),r=await W(i);"marginTop"===t&&B(o,{height:`${e}px`,width:n.width+"px",left:r.left+"px",top:r.top-e+"px"}),"marginRight"===t&&B(o,{height:n.height+"px",width:`${e}px`,left:r.left+parseInt(n.width+"",10)+"px",top:r.top+"px"}),"marginBottom"===t&&B(o,{height:`${e}px`,width:n.width+"px",left:r.left+"px",top:r.top+parseInt(n.height+"",10)+"px"}),"marginLeft"===t&&B(o,{height:n.height+"px",width:`${e}px`,left:r.left-e+"px",top:r.top+"px"}),"paddingTop"===t&&B(o,{height:`${e}px`,width:n.width+"px",left:r.left+"px",top:r.top+"px"}),"paddingBottom"===t&&B(o,{height:`${e}px`,width:n.width+"px",left:r.left+"px",top:r.top+(parseInt(n.height+"",10)-e)+"px"}),"paddingRight"===t&&B(o,{height:n.height+"px",width:`${e}px`,left:r.left+(parseInt(n.width+"",10)-e)+"px",top:r.top+"px"}),"paddingLeft"===t&&B(o,{height:n.height+"px",width:`${e}px`,left:r.left+"px",top:r.top+"px"})},Y=(t="",e="span")=>{const o=document.createElement(e),i=document.createTextNode(`${t}`);return o.appendChild(i),o.setAttribute("title",`${t}px`),N(o,"ph-speccer speccer spacing"),o},J=async t=>{if(!t)return;const e=await R(t);if("none"===e.display||"0"===e.opacity||"hidden"===e.visibility)return;const o=(t=>{const{marginTop:e,marginBottom:o,marginLeft:i,marginRight:n,paddingTop:r,paddingBottom:s,paddingLeft:a,paddingRight:p}=t;return{marginTop:e,marginBottom:o,marginLeft:i,marginRight:n,paddingTop:r,paddingBottom:s,paddingLeft:a,paddingRight:p}})(e),i=Object.keys(o).filter((t=>"0px"!==o[t]));if(i.length)for(const e of i){const i=O(o[e]),n=Y(i),r=q(e);N(n,r),document.body.appendChild(n),t.classList.add("is-specced"),await X(e,i,n,t)}},K=t=>{const e=()=>((t,e,o=!1)=>{let i;return function(n,...r){const s=o&&!i;i&&clearTimeout(i),i=setTimeout((function(){i=null,o||t.apply(n,r)}),e),s&&t.apply(n,r)}})((()=>{t()}),300);window.removeEventListener("resize",e),window.addEventListener("resize",e)},Q=t=>{"loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>{t()})):t()},U=()=>{const t=new IntersectionObserver(((t,e)=>{for(const o of t)o.intersectionRatio>0&&(J(o.target),e.unobserve(o.target))}));for(const e of document.querySelectorAll("[data-speccer],[data-speccer] *:not(td):not(tr):not(th):not(tfoot):not(thead):not(tbody)"))t.observe(e);const e=new IntersectionObserver(((t,e)=>{for(const o of t)o.intersectionRatio>0&&(_(o.target),e.unobserve(o.target))}));for(const t of document.querySelectorAll("[data-speccer-measure]"))e.observe(t);const o=new IntersectionObserver((async(t,e)=>{for(const o of t)o.intersectionRatio>0&&(await D(o.target),e.unobserve(o.target))}));for(const t of document.querySelectorAll("[data-anatomy-section]"))o.observe(t)},Z=t=>{window.speccer=t},tt=t=>{const e=document.currentScript;if(e){const o=e.getAttribute("src");o&&o.includes("speccer.js")&&(e.hasAttribute("data-manual")?Z(t):e.hasAttribute("data-instant")?t():e.hasAttribute("data-dom")?Q(t):e.hasAttribute("data-lazy")?U():Q(t),e.hasAttribute("data-manual")||e.hasAttribute("data-lazy")||K(t))}},et=(t="span")=>{const e=document.createElement(t),o=I("ph-speccer speccer mark");return N(e,o),e},ot=async t=>{if(!t)return;const e=et();document.body.appendChild(e);const o=await z(e,t),{left:i,top:n,height:r,width:s}=o.absolute(),a={left:`${i}px`,top:`${n}px`,height:`${r}px`,width:`${s}px`};await B(e,a)},it=(t,e=3)=>parseFloat(t+"").toFixed(e),nt=(t,e)=>{const o=document.createElement("div"),i={};null!==e&&""!==e&&(i[e]=!0);const n=I("ph-speccer speccer typography",i);return o.innerHTML=t,N(o,n),o},rt=async e=>{if(!e)return;const o=e.getAttribute("data-speccer-typography"),i=await R(e);if("none"===i.display||"0"===i.opacity||"hidden"===i.visibility)return;e.classList.add("is-specced");const n=await(async t=>{const e=(t=>{const{lineHeight:e,letterSpacing:o,fontFamily:i,fontSize:n,fontStyle:r,fontVariationSettings:s,fontWeight:a}=t;return{lineHeight:e,letterSpacing:o,fontFamily:i,fontSize:n,fontStyle:r,fontVariationSettings:s,fontWeight:a}})(await R(t)),o="normal"!==e.lineHeight?parseInt(e.lineHeight,10)/16+"rem":"normal";return`\nfont-styles: {<ul class="speccer-styles"> <li><span class="property">font-family:</span> ${e.fontFamily};</li> <li><span class="property">font-size:</span> ${e.fontSize} / ${parseInt(e.fontSize,10)/16}rem;</li> <li><span class="property">font-weight:</span> ${e.fontWeight};</li> <li><span class="property">font-variation-settings:</span> ${e.fontVariationSettings};</li> <li><span class="property">line-height:</span> ${e.lineHeight} / ${o};</li> <li><span class="property">letter-spacing:</span> ${e.letterSpacing};</li> <li><span class="property">font-style:</span> ${e.fontStyle};</li></ul>}`})(e),r=nt(n,o);document.body.appendChild(r);const s=await(async(e,o,i)=>{const n=o.getBoundingClientRect(),r=H(i),s=i.getBoundingClientRect(),a=await W(o),p=a.left-s.width-r+"px",c=it(V(a.top,s,n))+"px",l=a.left+n.width+r+"px",h=it(V(a.top,s,n))+"px",d=it(k(a.left,s,n))+"px",f=a.top-s.height-r+"px",m=it(k(a.left,s,n))+"px",u=a.top+n.height+r+"px";let g={left:p,top:c};return e?.includes(t.Right)?g={left:l,top:h}:e?.includes(t.Top)?g={left:d,top:f}:e?.includes(t.Bottom)&&(g={left:m,top:u}),g})(o,e,r);B(r,s)},st={create:Y,element:J},at={create:F,element:D},pt={create:G,element:_},ct={create:et,element:ot},lt={create:nt,element:rt},ht={dom:Q,lazy:U,manual:Z,activate:tt},dt=()=>{((t,e=document)=>{[].forEach.call(e.querySelectorAll(t),(function(t){t.remove()}))})(".ph-speccer.speccer");const t=document.querySelectorAll("[data-speccer],[data-speccer] *:not(td):not(tr):not(th):not(tfoot):not(thead):not(tbody)"),e=document.querySelectorAll("[data-speccer-measure]"),o=document.querySelectorAll("[data-speccer-typography]"),i=document.querySelectorAll("[data-anatomy-section]"),n=document.querySelectorAll("[data-speccer-mark]");for(const t of n)ot(t);for(const e of t)J(e);for(const t of e)_(t);for(const t of o)rt(t);for(const t of i)D(t)};tt(dt);export{dt as default,at as dissect,ct as mark,pt as measure,ht as modes,st as spacing,lt as typography};
|
|
1
|
+
/**
|
|
2
|
+
* @phun-ky/speccer
|
|
3
|
+
* A script to annotate, show spacing specs and to display typography information in documentation/website on HTML elements
|
|
4
|
+
* @author Alexander Vassbotn Røyne-Helgesen <alexander@phun-ky.net>
|
|
5
|
+
* @version 9.1.1
|
|
6
|
+
* @license
|
|
7
|
+
* Copyright (c) 2018 Alexander Vassbotn Røyne-Helgesen
|
|
8
|
+
*
|
|
9
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
11
|
+
* in the Software without restriction, including without limitation the rights
|
|
12
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
14
|
+
* furnished to do so, subject to the following conditions:
|
|
15
|
+
*
|
|
16
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
17
|
+
* copies or substantial portions of the Software.
|
|
18
|
+
*
|
|
19
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
+
* SOFTWARE.
|
|
26
|
+
*/
|
|
27
|
+
var t,e,o;!function(t){t.Empty="",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top"}(t||(t={})),function(t){t.Outline="outline",t.Enclose="enclose",t.Full="full",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top",t.SVG="svg",t.Curly="curly"}(e||(e={})),function(t){t.Width="width",t.Height="height",t.Left="left",t.Right="right",t.Bottom="bottom",t.Top="top"}(o||(o={}));const n=t=>t.split(" "),i=t=>n(t).includes(e.Right),r=t=>n(t).includes(e.Bottom),s=t=>n(t).includes(e.Full),a=t=>n(t).includes(e.Enclose),c=t=>t.includes(e.Curly)&&t.includes(e.Full),l=t=>"string"==typeof t,p=t=>!l(t),h=t=>"number"==typeof t,d=t=>!h(t),f=t=>void 0===t,m=()=>new Promise(requestAnimationFrame),u=t=>t.top,g=t=>t.left+t.width,y=t=>t.top+t.height,w=t=>t.left,x=t=>t.left+t.width/2,b=t=>t.top+t.height/2,E={center:t=>({x:x(t),y:b(t)}),top:t=>({x:x(t),y:u(t)}),right:t=>({x:g(t),y:b(t)}),bottom:t=>({x:x(t),y:y(t)}),left:t=>({x:w(t),y:b(t)}),"right-top":t=>({x:g(t),y:u(t)}),"right-bottom":t=>({x:g(t),y:y(t)}),"left-top":t=>({x:w(t),y:u(t)}),"left-bottom":t=>({x:w(t),y:y(t)}),"top-left":t=>({x:w(t),y:u(t)}),"top-right":t=>({x:g(t),y:u(t)}),"bottom-left":t=>({x:w(t),y:y(t)}),"bottom-right":t=>({x:g(t),y:y(t)}),"top-center":t=>({x:x(t),y:u(t)}),"right-center":t=>({x:g(t),y:b(t)}),"bottom-center":t=>({x:x(t),y:y(t)}),"left-center":t=>({x:w(t),y:b(t)})},$=async(t,e="center")=>{if(!e)throw Error("No position given");if(p(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 m();const n=t.getBoundingClientRect();return E[e](n)},A=async(t,e,o="center",n="center")=>{if(!t||!e)throw Error("No element given");const{x:i,y:r}=await $(t,o),{x:s,y:a}=await $(e,n);return{x1:i,y1:r,x2:s,y2:a}},v=(t,e)=>{const{x1:o,x2:n,y1:i,y2:r}=t,{direct:s=!1,firstSet:a=!1,direction:c}=e;let l={x:o+(n-o)/2,y:i},p={x:o+(n-o)/2,y:r};return s&&(a?"west"===c?(l={x:o-32,y:i-8},p={x:n+32,y:r}):"south"===c?(l={x:o-8,y:i+32},p={x:n,y:r-32}):"east"===c?(l={x:o+32,y:i-8},p={x:n-32,y:r}):(l={x:o-8,y:i-32},p={x:n,y:r+32}):"west"===c?(l={x:o-32,y:i+8},p={x:n+32,y:r}):"south"===c?(l={x:o+8,y:i+32},p={x:n,y:r-32}):"east"===c?(l={x:o+32,y:i+8},p={x:n-32,y:r}):(l={x:o+8,y:i-32},p={x:n,y:r+32})),{firstPoint:{x:o,y:i},firstControl:l,lastPoint:{x:n,y:r},lastControl:p}},S=async(t,e,o)=>{const{pos1:n,pos2:i,firstSet:r=!1,direction:s}=o,{x1:a,y1:c,x2:l,y2:p}=await A(t,e,n,i);let h=0,d=0;"north"===s?d=8:"west"===s?h=8:"east"===s?h=-8:"south"===s&&(d=-8);const{firstPoint:f,firstControl:m,lastControl:u,lastPoint:g}=v({x1:a+0,x2:l+h,y1:c+0+document.documentElement.scrollTop,y2:p+d+document.documentElement.scrollTop},{direct:!0,firstSet:r,direction:s});return`M ${f.x} ${f.y}C ${m.x} ${m.y}, ${u.x} ${u.y}, ${g.x} ${g.y}`},C=async({start:t,stop:e,crude:o=!1})=>{const{x1:n,y1:i,x2:r,y2:s}=await A(t,e),a=((t,e,o,n,i=!0)=>{if(f(t)||f(e)||f(o)||f(n))throw new SyntaxError("Missing input for `angle`");if(d(t)||d(e)||d(o)||d(n))throw TypeError(`Parameters for \`angle\` do not have the required type. Requires number! Got: ${typeof t} ${typeof e} ${typeof o} ${typeof n}`);const r=n-e,s=o-t;let a=Math.atan2(r,s);return a*=180/Math.PI,i&&a<0&&(a+=360),a})(n,i,r,s);return o?(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"})(a):(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"})(a)},L=()=>"_"+Math.random().toString(36).substring(2,11),P=async(t,e)=>{var o;if(!(!t||!e||l(e)||h(e)||(o=e,"boolean"==typeof o)||Array.isArray(e)&&!e.length||!Object.keys(e).length&&e.constructor===Object))if(await m(),Array.isArray(e))for(const o of e)t.style[o.key]=o.value;else for(const o of Object.keys(e))t.style[o]=e[o]},B=async t=>(await m(),getComputedStyle(t,null));class R{#t;#e;startElement;stopElement;firstPathElement;secondPathElement;constructor(t,e){this.#o(t,e)}#o(t,e){if(!t||!e)throw new Error("Missing inputs startElement and stopElement");if(!document.body.contains(e))throw new Error("stopElement is not in the DOM");if(!document.body.contains(t))throw new Error("startElement is not in the DOM");if(this.startElement=t,this.stopElement=e,this.#t=document.getElementById("ph-speccer-svg"),this.#e=document.getElementById("ph-speccer-path"),!this.#e||!this.#t)throw new Error("Missing required SVG element to draw lines. Please see the documentation");P(this.#t,{height:`${document.body.scrollHeight}px`}),this.connect()}connect(){this.draw(this.#e)}#n(t){if(!t)throw new Error("No path given to #getPathElement!");const e=`ph_draw_path-path-${L()}`,o=t.cloneNode(!1),n=this.startElement.getAttribute("id")||L();return this.startElement.setAttribute("id",n),o.setAttribute("data-start-el",n),o.setAttribute("id",e),o.classList.remove("original"),o.classList.add("speccer"),o}async draw(t){if(!t)throw new Error("No path given to draw!");const e=this.#n(t),o=this.#n(t);if(!t.parentNode)throw new Error("No parentNode found for path");this.firstPathElement=t.parentNode.insertBefore(e,t.nextSibling),this.secondPathElement=t.parentNode.insertBefore(o,t.nextSibling);const n=await C({stop:this.stopElement,start:this.startElement,crude:!0}),{path1pos1:i,path1pos2:r,path2pos1:s,path2pos2:a}=(t=>{let e,o,n,i;switch(t){case"east":e="right-top",o="left-center",n="right-bottom",i="left-center";break;case"south":e="bottom-left",o="top-center",n="bottom-right",i="top-center";break;case"west":e="left-top",o="right-center",n="left-bottom",i="right-center";break;default:e="top-left",o="bottom-center",n="top-right",i="bottom-center"}return{path1pos1:e,path1pos2:o,path2pos1:n,path2pos2:i}})(n),c=await S(this.startElement,this.stopElement,{pos1:i,pos2:r,firstSet:!0,direction:n}),l=await S(this.startElement,this.stopElement,{pos1:s,pos2:a,direction:n});this.firstPathElement.setAttribute("data-direction",n),this.firstPathElement.setAttribute("data-pos1",i),this.firstPathElement.setAttribute("data-pos2",r),this.firstPathElement.setAttribute("d",c),this.secondPathElement.setAttribute("data-direction",n),this.secondPathElement.setAttribute("data-pos1",s),this.secondPathElement.setAttribute("data-pos2",a),this.secondPathElement.setAttribute("d",l)}}window.DrawSVGCurlyBracket=R;class T{#t;#e;startElement;stopElement;line;constructor(t,e){this.#o(t,e)}#o(t,e){if(!t||!e)throw new Error("Missing inputs startElement and stopElement");if(!document.body.contains(e))throw new Error("stopElement is not in the DOM");if(!document.body.contains(t))throw new Error("startElement is not in the DOM");if(this.startElement=t,this.stopElement=e,this.#t=document.getElementById("ph-speccer-svg"),this.#e=document.getElementById("ph-speccer-path"),!this.#e||!this.#t)throw new Error("Missing required SVG element to draw lines. Please see the documentation");P(this.#t,{height:`${document.body.scrollHeight}px`}),this.connect()}connect(){this.draw(this.#e)}async draw(t){if(!t)throw new Error("No path given to draw!");const e=`ph_draw_path-path-${L()}`,o=t.cloneNode(!1),n=this.startElement.getAttribute("id")||L();if(this.startElement.setAttribute("id",n),o.setAttribute("id",e),o.setAttribute("data-start-el",n),o.classList.remove("original"),o.classList.add("speccer"),!t.parentNode)throw new Error("No parentNode found for path");this.line=t.parentNode.insertBefore(o,t.nextSibling);const i=await C({start:this.startElement,stop:this.stopElement,crude:!0}),{pos1:r,pos2:s}=(t=>{let e,o;switch(t){case"east":e="right",o="left";break;case"south":e="bottom",o="top";break;case"west":e="left",o="right";break;default:e="top",o="bottom"}return{pos1:e,pos2:o}})(i),a=await(async(t,e,o)=>{const{pos1:n,pos2:i}=o,{x1:r,y1:s,x2:a,y2:c}=await A(t,e,n,i),{firstPoint:l,firstControl:p,lastControl:h,lastPoint:d}=v({x1:r,x2:a,y1:s,y2:c},{direction:""});return`M ${l.x} ${l.y}C ${p.x} ${p.y}, ${h.x} ${h.y}, ${d.x} ${d.y}`})(this.startElement,this.stopElement,{pos1:r,pos2:s});this.line.setAttribute("data-direction",i),this.line.setAttribute("data-pos1",r),this.line.setAttribute("data-pos2",s),this.line.setAttribute("d",a)}}window.DrawSVGLine=T;const k=(t,e,o="noop")=>{t&&(!e||e&&!e.length||e.trim().split(" ").filter((t=>t!==o)).forEach((e=>t.classList.add(e))))},N=(t,e)=>t?!e&&p(t)?Object.keys(t).filter((e=>t[e])).join(" ").trim():`${t.trim()} ${e?Object.keys(e).filter((t=>e[t])).join(" "):""}`.trim():"",q=[..."ABCDEFGHIJKLMNOPQRSTUVWXYZ"],I=t=>parseInt(t,10),M=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"):"",O=t=>I(getComputedStyle(t).getPropertyValue("--ph-speccer-pin-space"))||48,H=async(t,e,o)=>{await m();return getComputedStyle(t)[e]===o},V=async(t,e,o)=>{if(!t.parentElement)return null;return await H(t.parentElement,e,o)?t.parentElement:await V(t.parentElement,e,o)},W=(t,e,o)=>t-e.width/2+o.width/2,j=(t,e,o)=>t-e.height/2+o.height/2,z=async t=>{await m();let e=t.getBoundingClientRect(),o=e.top+window.scrollY;const n=e.left+window.scrollX,i=await(async t=>await V(t,"position","sticky"))(t),r=await(async t=>await H(t,"position","sticky"))(t);if(r){const n=t.style.position;await m(),t.style.position="relative",await m(),e=t.getBoundingClientRect(),o=e.top,t.style.position=n}else if(i){const n=i.style.position;await m(),i.style.position="relative",await m(),e=t.getBoundingClientRect(),o=e.top,i.style.position=n}return{height:e.height,width:e.width,top:o,left:n}},F=async(t,e)=>{await m();const o=t.getBoundingClientRect(),n=await z(e),i=await(async(t,e)=>{await m();const o=t.getBoundingClientRect(),n=e.getBoundingClientRect(),i=n.top+window.scrollY,r=n.left+window.scrollX;return{height:n.height,width:n.width,top:j(i,o,n),left:W(r,o,n)}})(t,e),r=n.height,s=n.width,a=o.height,c=o.width;return{absolute:()=>({top:n.top,left:n.left,height:r,width:s}),toTop:({center:t=!1,sourceHeight:e=a,modifier:o=0}={})=>({top:n.top+e+o,left:t?i.left:n.left,height:r,width:s}),fromTop:({center:t=!1,sourceHeight:e=a,modifier:o=0}={})=>({top:n.top-e-o,left:t?i.left:n.left,height:r,width:s}),toBottom:({center:t=!1,sourceHeight:e=a,targetHeight:o=r,modifier:c=0}={})=>({top:n.top+o-(e+c),left:t?i.left:n.left,height:r,width:s}),fromBottom:({center:t=!1,targetHeight:e=r,modifier:o=0}={})=>({top:n.top+e+o,left:t?i.left:n.left,height:r,width:s}),toLeft:({center:t=!1,sourceWidth:e=c,modifier:o=0}={})=>({top:t?i.top:n.top,left:n.left+e+o,height:r,width:s}),fromLeft:({center:t=!1,sourceWidth:e=c,modifier:o=0}={})=>({top:t?i.top:n.top,left:n.left-e-o,height:r,width:s}),toRight:({center:t=!1,sourceWidth:e=c,targetWidth:o=s,modifier:a=0}={})=>({top:t?i.top:n.top,left:n.left+o-(e+a),height:r,width:s}),fromRight:({center:t=!1,targetWidth:e=s,modifier:o=0}={})=>({top:t?i.top:n.top,left:n.left+e+o,height:r,width:s})}},D=async(t,o,c,l)=>{await m();const{isCurly:p=!1}=l||{},h=O(c),d=I(getComputedStyle(c).getPropertyValue("--ph-speccer-measure-size"))||8;const f=await F(c,o);if(a(t)){const{left:t,top:e,height:o,width:n}=f.absolute();return{left:`${t}px`,top:`${e}px`,height:`${o}px`,width:`${n}px`}}if(n(t).includes(e.Left)){if(s(t)&&!p){const{left:t,top:e,height:o}=f.fromLeft({sourceWidth:d});return{left:`${t}px`,top:`${e}px`,height:`${o}px`}}const{left:e,top:o}=f.fromLeft({center:!0,modifier:p?h/1.5:h});return{left:`${e}px`,top:`${o}px`}}if(i(t)){if(s(t)&&!p){const{left:t,top:e,height:o}=f.fromRight({center:!1});return{left:`${t}px`,top:`${e}px`,height:`${o}px`}}const{left:e,top:o}=f.fromRight({center:!0,modifier:p?h/1.5:h});return{left:`${e}px`,top:`${o}px`}}if(r(t)){if(s(t)&&!p){const{left:t,top:e,width:o}=f.fromBottom({center:!1});return{left:`${t}px`,top:`${e}px`,width:`${o}px`}}const{left:e,top:o}=f.fromBottom({center:!0,modifier:p?h/1.5:h});return{left:`${e}px`,top:`${o}px`}}if(s(t)&&!p){const{left:t,top:e,width:o}=f.fromTop({center:!1});return{left:`${t}px`,top:`${e}px`,width:`${o}px`}}const{left:u,top:g}=f.fromTop({center:!0,modifier:p?h/1.5:h});return{left:`${u}px`,top:`${g}px`}},G=(t="",e,o="span")=>{const n=document.createElement(o),i=document.createTextNode(t),r={};null!==e&&""!==e&&(r[e]=!0),!s(e)&&!a(e)||s(e)&&c(e)?n.appendChild(i):(s(e)||a(e))&&n.setAttribute("data-dissection-counter",t);const l=N("ph-speccer speccer dissection",r);return k(n,l),n},_=async t=>{if(!t)return;const o=t.querySelectorAll("[data-anatomy]");if(o){let t=0;o.forEach((async(o,n)=>{if(!o)return;const i=o.getAttribute("data-anatomy")||"";if(!i||""===i||!i.includes(e.Outline))return;let r=q[n];r||(r=`${q[t]}${q[t].toLowerCase()}`,t++);const s=G(r,i);document.body.appendChild(s);const a=await D(i,o,s,{isCurly:c(i)});await P(s,a),i.includes(e.SVG)&&!c(i)?new T(o,s):c(i)&&new R(o,s)}))}},X=(t="",e="",o="span")=>{const n=document.createElement(o);return n.setAttribute("title",`${t}px`),n.setAttribute("data-measure",`${parseInt(`${t}`,10)}px`),k(n,`ph-speccer speccer measure ${e}`),n},Y=async t=>{if(!t)return;const e=t.getAttribute("data-speccer-measure");if(""===e||!e)return;const s=await B(t);if("none"===s.display||"0"===s.opacity||"hidden"===s.visibility)return;await m();const a=t.getBoundingClientRect();if(n(e).includes(o.Width))if(r(e)){const o=X(a.width,e);document.body.appendChild(o);const n=await F(o,t),{left:i,top:r,width:s}=n.fromBottom({center:!1});await P(o,{left:`${i}px`,top:`${r}px`,width:`${s}px`})}else{const o=X(a.width,e);document.body.appendChild(o);const n=await F(o,t),{left:i,top:r,width:s}=n.fromTop({center:!1,modifier:-8});await P(o,{left:`${i}px`,top:`${r}px`,width:`${s}px`})}else if((t=>n(t).includes(o.Height))(e))if(i(e)){const o=X(a.height,e);document.body.appendChild(o);const n=await F(o,t),{left:i,top:r,height:s}=n.fromRight({center:!1});await P(o,{left:`${i}px`,top:`${r}px`,height:`${s}px`})}else{const o=X(a.height,e);document.body.appendChild(o);const n=await F(o,t),{left:i,top:r,height:s}=n.fromLeft({center:!1,modifier:-8});await P(o,{left:`${i}px`,top:`${r}px`,height:`${s}px`})}},J=async(t,e,o,n)=>{await m();const i=n.getBoundingClientRect(),r=await z(n);"marginTop"===t&&P(o,{height:`${e}px`,width:i.width+"px",left:r.left+"px",top:r.top-e+"px"}),"marginRight"===t&&P(o,{height:i.height+"px",width:`${e}px`,left:r.left+parseInt(i.width+"",10)+"px",top:r.top+"px"}),"marginBottom"===t&&P(o,{height:`${e}px`,width:i.width+"px",left:r.left+"px",top:r.top+parseInt(i.height+"",10)+"px"}),"marginLeft"===t&&P(o,{height:i.height+"px",width:`${e}px`,left:r.left-e+"px",top:r.top+"px"}),"paddingTop"===t&&P(o,{height:`${e}px`,width:i.width+"px",left:r.left+"px",top:r.top+"px"}),"paddingBottom"===t&&P(o,{height:`${e}px`,width:i.width+"px",left:r.left+"px",top:r.top+(parseInt(i.height+"",10)-e)+"px"}),"paddingRight"===t&&P(o,{height:i.height+"px",width:`${e}px`,left:r.left+(parseInt(i.width+"",10)-e)+"px",top:r.top+"px"}),"paddingLeft"===t&&P(o,{height:i.height+"px",width:`${e}px`,left:r.left+"px",top:r.top+"px"})},K=(t="",e="span")=>{const o=document.createElement(e),n=document.createTextNode(t+"");return o.appendChild(n),o.setAttribute("title",`${t}px`),k(o,"ph-speccer speccer spacing"),o},Q=async t=>{if(!t)return;const e=await B(t);if("none"===e.display||"0"===e.opacity||"hidden"===e.visibility)return;const o=(t=>{const{marginTop:e,marginBottom:o,marginLeft:n,marginRight:i,paddingTop:r,paddingBottom:s,paddingLeft:a,paddingRight:c}=t;return{marginTop:e,marginBottom:o,marginLeft:n,marginRight:i,paddingTop:r,paddingBottom:s,paddingLeft:a,paddingRight:c}})(e),n=Object.keys(o).filter((t=>"0px"!==o[t]));if(n.length)for(const e of n){const n=I(o[e]),i=K(n),r=M(e);k(i,r),document.body.appendChild(i),t.classList.add("is-specced"),await J(e,n,i,t)}},U=t=>{const e=()=>((t,e,o=!1)=>{let n;return function(i,...r){const s=o&&!n;n&&clearTimeout(n),n=setTimeout((function(){n=null,o||t.apply(i,r)}),e),s&&t.apply(i,r)}})((()=>{t()}),300);window.removeEventListener("resize",e),window.addEventListener("resize",e)},Z=t=>{"loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>{t()})):t()},tt=()=>{const t=new IntersectionObserver(((t,e)=>{for(const o of t)o.intersectionRatio>0&&(Q(o.target),e.unobserve(o.target))}));for(const e of document.querySelectorAll("[data-speccer],[data-speccer] *:not(td):not(tr):not(th):not(tfoot):not(thead):not(tbody)"))t.observe(e);const e=new IntersectionObserver(((t,e)=>{for(const o of t)o.intersectionRatio>0&&(Y(o.target),e.unobserve(o.target))}));for(const t of document.querySelectorAll("[data-speccer-measure]"))e.observe(t);const o=new IntersectionObserver((async(t,e)=>{for(const o of t)o.intersectionRatio>0&&(await _(o.target),e.unobserve(o.target))}));for(const t of document.querySelectorAll("[data-anatomy-section]"))o.observe(t)},et=t=>{window.speccer=t},ot=t=>{const e=document.currentScript;if(e){const o=e.getAttribute("src");o?.includes("speccer.js")&&(e.hasAttribute("data-manual")?et(t):e.hasAttribute("data-instant")?t():e.hasAttribute("data-dom")?Z(t):e.hasAttribute("data-lazy")?tt():Z(t),e.hasAttribute("data-manual")||e.hasAttribute("data-lazy")||U(t))}},nt=["alt","altgraph","capslock","control","fn","fnlock","hyper","meta","numlock","os","scrolllock","shift","super","symbol","command","ctrl","altgr","symbollock"],it=["escape","esc","enter","return","⏎","␛"],rt=async(t,e,o)=>{await m();const n=O(o),i=await F(o,e);if("tabstops"===t){let{left:t,top:e}=i.fromTop();return t-=32,t<=0&&(t=32),e<=0&&(e=32),{left:`${t}px`,top:`${e}px`}}if("landmark"===t){let{left:t,top:e}=i.fromTop();return t-=16,e-=16,t<=0&&(t=32),e<=0&&(e=32),{left:`${t}px`,top:`${e}px`}}if("region"===t){const{left:t,top:e,height:o,width:n}=i.fromTop();return{height:`${o}px`,width:`${n}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:n});return{left:r-32+"px",top:s-32+"px"}},st=async(t,e,o)=>{if(!t||!t.checkVisibility())return;const n=((t="tabstops",e,o="span")=>{const n=document.createElement(o),i=N("ph-speccer speccer a11y",{tabstops:"tabstops"===t,landmark:"landmark"===t,region:"region"===t});if("landmark"===t&&e){const t=document.createTextNode(e+"");n.appendChild(t)}return k(n,i),n})(o,e);if("landmark"===o){n.setAttribute("data-speccer-nodename",t.nodeName);const e=t.role||`semantic role: ${t.nodeName.toLowerCase()}`,o=t.getAttribute("aria-label")||"unnamed";n.setAttribute("title",`${o}: ${e}`)}document.body.appendChild(n);const i=await rt(o,t,n);await P(n,i)},at=async(t,e)=>{const o=e.split(/\s\+\s/).map((t=>t.trim())),n=document.createElement("div");n.classList.add("ph-speccer"),n.classList.add("speccer"),n.classList.add("a11y"),n.classList.add("shortcut-holder");for(const t of o){const e=document.createElement("kbd"),o=document.createTextNode(t);e.classList.add("ph-speccer"),e.classList.add("speccer"),e.classList.add("a11y"),e.classList.add("shortcut"),nt.includes(t.toLowerCase())&&e.classList.add("modifier"),it.includes(t.toLowerCase())&&e.classList.add("physical"),e.appendChild(o),n.appendChild(e)}document.body.appendChild(n);const i=await rt("shortcut",t,n);await P(n,i)},ct=(t="span")=>{const e=document.createElement(t),o=N("ph-speccer speccer mark");return k(e,o),e},lt=async t=>{if(!t)return;const e=ct();document.body.appendChild(e);const o=await F(e,t),{left:n,top:i,height:r,width:s}=o.absolute(),a={left:`${n}px`,top:`${i}px`,height:`${r}px`,width:`${s}px`};await P(e,a)},pt=(t,e=3)=>parseFloat(t+"").toFixed(e),ht=(t,e)=>{const o=document.createElement("div"),n={};null!==e&&""!==e&&(n[e]=!0);const i=N("ph-speccer speccer typography",n);return o.innerHTML=t,k(o,i),o},dt=async e=>{if(!e)return;const o=e.getAttribute("data-speccer-typography"),n=await B(e);if("none"===n.display||"0"===n.opacity||"hidden"===n.visibility)return;e.classList.add("is-specced");const i=await(async t=>{const e=(t=>{const{lineHeight:e,letterSpacing:o,fontFamily:n,fontSize:i,fontStyle:r,fontVariationSettings:s,fontWeight:a}=t;return{lineHeight:e,letterSpacing:o,fontFamily:n,fontSize:i,fontStyle:r,fontVariationSettings:s,fontWeight:a}})(await B(t)),o="normal"!==e.lineHeight?parseInt(e.lineHeight,10)/16+"rem":"normal";return`\nfont-styles: {<ul class="speccer-styles"> <li><span class="property">font-family:</span> ${e.fontFamily};</li> <li><span class="property">font-size:</span> ${e.fontSize} / ${parseInt(e.fontSize,10)/16}rem;</li> <li><span class="property">font-weight:</span> ${e.fontWeight};</li> <li><span class="property">font-variation-settings:</span> ${e.fontVariationSettings};</li> <li><span class="property">line-height:</span> ${e.lineHeight} / ${o};</li> <li><span class="property">letter-spacing:</span> ${e.letterSpacing};</li> <li><span class="property">font-style:</span> ${e.fontStyle};</li></ul>}`})(e),r=ht(i,o);document.body.appendChild(r);const s=await(async(e,o,n)=>{const i=o.getBoundingClientRect(),r=O(n),s=n.getBoundingClientRect(),a=await z(o),c=a.left-s.width-r+"px",l=pt(j(a.top,s,i))+"px",p=a.left+i.width+r+"px",h=pt(j(a.top,s,i))+"px",d=pt(W(a.left,s,i))+"px",f=a.top-s.height-r+"px",m=pt(W(a.left,s,i))+"px",u=a.top+i.height+r+"px";let g={left:c,top:l};return e?.includes(t.Right)?g={left:p,top:h}:e?.includes(t.Top)?g={left:d,top:f}:e?.includes(t.Bottom)&&(g={left:m,top:u}),g})(o,e,r);P(r,s)},ft={create:K,element:Q},mt={create:G,element:_},ut={create:X,element:Y},gt={create:ct,element:lt},yt={create:ht,element:dt},wt={dom:Z,lazy:tt,manual:et,activate:ot},xt=()=>{((t,e=document)=>{[].forEach.call(e.querySelectorAll(t),(function(t){t.remove()}))})(".ph-speccer.speccer");const t=document.querySelectorAll("[data-speccer],[data-speccer] *:not(td):not(tr):not(th):not(tfoot):not(thead):not(tbody)"),e=document.querySelectorAll("[data-speccer-measure]"),o=document.querySelectorAll("[data-speccer-typography]"),n=document.querySelectorAll("[data-anatomy-section]"),i=document.querySelectorAll("[data-speccer-mark]");for(const t of i)lt(t);for(const e of t)Q(e);for(const t of e)Y(t);for(const t of o)dt(t);for(const t of n)_(t);(()=>{const t=document.querySelectorAll("[data-speccer-a11y-tabstops]"),e=document.querySelectorAll("[data-speccer-a11y-landmark]"),o=document.querySelectorAll("[data-speccer-a11y-shortcut]");if(o.length)for(const t of o){const e=t.getAttribute("data-speccer-a11y-shortcut");e&&""!==e&&at(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 of t)st(e,null,"tabstops")}if(e.length)for(const t of e){const e=t.querySelectorAll('\nheader, footer, section, 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,o]of e.entries())st(o,t+1,"landmark"),st(o,null,"region")}})()};ot(xt);export{xt as default,mt as dissect,gt as mark,ut as measure,wt as modes,ft as spacing,yt as typography};
|
|
2
28
|
//# sourceMappingURL=speccer.esm.js.map
|