@domphy/doctor 0.17.0 → 0.18.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 CHANGED
@@ -42,7 +42,7 @@ console.log(format(issues))
42
42
 
43
43
  ```ts
44
44
  interface Diagnostic {
45
- rule: string // "inline-typography" | "void-content" | "missing-key" | "unknown-tag"
45
+ rule: string // one of the 12 rule ids below, e.g. "inline-typography"
46
46
  severity: "error" | "warning" | "info"
47
47
  path: string // "div > ul > li"
48
48
  message: string
@@ -52,12 +52,22 @@ interface Diagnostic {
52
52
 
53
53
  ## Rules
54
54
 
55
+ The doctor implements 12 rules:
56
+
55
57
  | Rule | Severity | Catches |
56
58
  | --- | --- | --- |
57
- | `inline-typography` | warning | `fontSize`/`lineHeight`/`fontWeight`/`letterSpacing` literals in `style` — use a typography patch |
58
- | `void-content` | error | a void tag (`input`, `img`, `br`, …) with non-null content |
59
59
  | `missing-key` | warning | a **dynamic** list (from a reactive function) of element children missing `_key` |
60
+ | `unstable-key` | warning | a dynamic list whose `_key`s are the array index (`0, 1, 2, …`) — unstable across reorders |
61
+ | `duplicate-key` | error | two sibling elements sharing the same `_key` value |
60
62
  | `unknown-tag` | warning | an element whose first key isn't a valid HTML/SVG tag (typo) |
63
+ | `void-content` | error | a void tag (`input`, `img`, `br`, …) with non-null content |
64
+ | `inline-typography` | warning | `fontSize`/`lineHeight`/`fontWeight`/`letterSpacing`/`fontFamily`/`textDecoration` literals in `style` — use a typography patch |
65
+ | `raw-theme-value` | info | a literal color (`#hex`, `rgb()`/`rgba()`) in a color `style` prop — use `themeColor()` (the hint includes an LCH-derived suggestion) |
66
+ | `raw-spacing-value` | info | a literal `rem`/`em`/`px` spacing value in a spacing `style` prop — use `themeSpacing()` |
67
+ | `unknown-tone` | warning | a `dataTone` that isn't valid tone grammar, or whose offset is out of the 18-step ramp (0–17) |
68
+ | `middle-surface-anchor` | warning | a `dataTone` of `shift-4`…`shift-13` (mid-ramp surface anchor) that may collapse child contrast |
69
+ | `unknown-density` | warning/error | a `dataDensity` that isn't valid grammar, or whose offset is out of the 5-step range (0–4) |
70
+ | `unknown-size` | warning/error | a `dataSize` that isn't valid grammar, or whose offset is out of the 8-step range (0–7) |
61
71
 
62
72
  By default the doctor **invokes reactive content functions** with a no-op listener to inspect their output (this is how `missing-key` is detected). Pass `{ runReactive: false }` if your reactive functions have side effects.
63
73
 
@@ -1,5 +1,5 @@
1
- "use strict";var Domphy=(()=>{var x=Object.defineProperty;var P=Object.getOwnPropertyDescriptor;var U=Object.getOwnPropertyNames;var F=Object.prototype.hasOwnProperty;var C=(e,s)=>{for(var t in s)x(e,t,{get:s[t],enumerable:!0})},z=(e,s,t,n)=>{if(s&&typeof s=="object"||typeof s=="function")for(let r of U(s))!F.call(e,r)&&r!==t&&x(e,r,{get:()=>s[r],enumerable:!(n=P(s,r))||n.enumerable});return e};var H=e=>z(x({},"__esModule",{value:!0}),e);var at={};C(at,{doctor:()=>S});var S={};C(S,{diagnose:()=>$,fix:()=>B,format:()=>D,validate:()=>M});var b=["a","abbr","address","article","aside","audio","b","base","blockquote","br","button","canvas","caption","cite","code","col","colgroup","data","datalist","dd","del","details","dfn","dialog","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","i","iframe","img","input","ins","kbd","label","legend","li","main","map","mark","meta","meter","nav","noscript","object","ol","optgroup","option","output","p","param","picture","pre","progress","q","rp","rt","ruby","s","samp","section","select","slot","small","source","span","strong","sub","summary","sup","table","tbody","td","template","textarea","tfoot","th","thead","time","title","tr","track","u","ul","var","video","wbr","bdi","bdo","math","menu","search","area","embed","hr","animate","animateMotion","animateTransform","circle","clipPath","cursor","defs","desc","ellipse","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feDropShadow","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence","filter","foreignObject","g","image","line","linearGradient","marker","mask","metadata","mpath","path","pattern","polygon","polyline","prefetch","radialGradient","rect","set","solidColor","stop","svg","switch","symbol","tbreak","text","textPath","tspan","use","view"];var w=["svg","circle","path","rect","ellipse","line","polyline","polygon","g","defs","use","symbol","linearGradient","radialGradient","stop","clipPath","mask","filter","text","tspan","textPath","image","pattern","marker","animate","animateTransform","animateMotion","feGaussianBlur","feComposite","feColorMatrix","feMerge","feMergeNode","feOffset","feFlood","feBlend","foreignObject"],v=["area","base","br","col","embed","hr","img","input","link","meta","source","track","wbr"];var q=["onAbort","onAuxClick","onBeforeMatch","onBeforeToggle","onBlur","onCancel","onCanPlay","onCanPlayThrough","onChange","onClick","onClose","onContextLost","onContextMenu","onContextRestored","onCopy","onCueChange","onCut","onDblClick","onDrag","onDragEnd","onDragEnter","onDragLeave","onDragOver","onDragStart","onDrop","onDurationChange","onEmptied","onEnded","onError","onFocus","onFormData","onInput","onInvalid","onKeyDown","onKeyPress","onKeyUp","onLoad","onLoadedData","onLoadedMetadata","onLoadStart","onMouseDown","onMouseEnter","onMouseLeave","onMouseMove","onMouseOut","onMouseOver","onMouseUp","onPaste","onPause","onPlay","onPlaying","onProgress","onRateChange","onReset","onResize","onScroll","onScrollEnd","onSecurityPolicyViolation","onSeeked","onSeeking","onSelect","onSlotChange","onStalled","onSubmit","onSuspend","onTimeUpdate","onToggle","onVolumeChange","onWaiting","onWheel","onTouchStart","onTouchMove","onTouchEnd","onTouchCancel","onPointerDown","onPointerMove","onPointerUp","onPointerCancel","onPointerEnter","onPointerLeave","onPointerOver","onPointerOut","onGotPointerCapture","onLostPointerCapture","onCompositionStart","onCompositionUpdate","onCompositionEnd","onTransitionEnd","onTransitionStart","onAnimationStart","onAnimationEnd","onAnimationIteration","onFullscreenChange","onFullscreenError","onFocusIn","onFocusOut"],ht=q.reduce((e,s)=>{let t=s.slice(2).toLowerCase();return e[t]=s,e},{});var ut=typeof process!="undefined"&&process.env!=null&&process.env.NODE_ENV!=="production";var W=e=>{let s=t=>t>.04045?Math.pow((t+.055)/1.055,2.4):t/12.92;return e.map(s)};var L=e=>{let s=parseInt(e.slice(1,3),16)/255,t=parseInt(e.slice(3,5),16)/255,n=parseInt(e.slice(5,7),16)/255;return W([s,t,n])};var N=e=>{let[s,t,n]=e,r=.4124564*s+.3575761*t+.1804375*n,i=.2126729*s+.7151522*t+.072175*n,u=.0193339*s+.119192*t+.9503041*n,l=.95047,d=1,m=1.08883,f=a=>a>.008856?Math.cbrt(a):7.787*a+16/116,p=f(r/l),g=f(i/d),o=f(u/m);return[116*g-16,500*(p-g),200*(g-o)]};var O=e=>{let[s,t,n]=e,r=Math.sqrt(t*t+n*n);if(r<1e-4)return[s,0,0];let i=(Math.atan2(n,t)*180/Math.PI+360)%360;return i>=359.9999&&(i=0),[s,r,i]};var j=e=>{let s=e.match(/\d+(\.\d+)?/g);if(!s||s.length<3)throw new Error("Invalid CSS rgb()");let t=n=>{let r=n/255;return r<=.04045?r/12.92:Math.pow((r+.055)/1.055,2.4)};return[t(Number(s[0])),t(Number(s[1])),t(Number(s[2]))]};var V=new Set([...b,...w]),G=new Set(v),K=new Set(["$","style","_key","_portal","_context","_metadata"]),Y=new Set(["fontSize","lineHeight","fontWeight","letterSpacing","fontFamily","textDecoration"]),Z=new Set(["color","backgroundColor","background","borderColor","border","outlineColor","outline","fill","stroke"]),J=/#[0-9a-fA-F]{3,8}\b|\b(?:rgba?|hsla?)\s*\(/,X=new Set(["margin","marginTop","marginRight","marginBottom","marginLeft","marginInline","marginBlock","marginInlineStart","marginInlineEnd","marginBlockStart","marginBlockEnd","padding","paddingTop","paddingRight","paddingBottom","paddingLeft","paddingInline","paddingBlock","paddingInlineStart","paddingInlineEnd","paddingBlockStart","paddingBlockEnd","gap","rowGap","columnGap"]),Q=/^(\d+(?:\.\d+)?)(rem|em|px)$/;function _(e){let s=e.match(/^(increase|decrease|shift)-(\d+)$/);return s?{family:s[1],n:parseInt(s[2],10)}:null}function tt(e){if(e==="inherit"||e==="base"||/^-?\d+$/.test(e))return!0;let s=_(e);return s?s.n<=17:!1}function et(e){try{let s=e.trim(),t;if(s.startsWith("#")){let i=s;if(i.length===9&&(i=i.slice(0,7)),i.length===5&&(i=i.slice(0,4)),i.length===4&&(i=`#${i[1]}${i[1]}${i[2]}${i[2]}${i[3]}${i[3]}`),i.length!==7)return null;t=L(i)}else if(/^rgba?\s*\(/.test(s))t=j(s);else return null;let n=N(t),r=O(n);return[r[0],r[1],r[2]]}catch(s){return null}}function st(e){let[s,t,n]=e,r=Math.round((s-50)/10),i=Math.max(-9,Math.min(9,r)),u;Math.abs(i)<=1?u='"base"':i<0?u=`"decrease-${Math.abs(i)}"`:u=`"increase-${i}"`;let l;return t<12?l="neutral":n<30||n>=330?l="error":n<75?l="warning":n<165?l="success":(n<265,l="primary"),`(l) => themeColor(l, ${u}, "${l}") [perceptual LCH L=${Math.round(s)} C=${Math.round(t)} h=${Math.round(n)}\xB0]`}function nt(e,s){let t=Q.exec(s);if(!t)return null;let n=parseFloat(t[1]),r=t[2],i;return r==="rem"||r==="em"?i=Math.round(n*4):i=Math.round(n/4),i<=0?null:`${e}: themeSpacing(${i}) \u2014 themeSpacing(n)=n/4em, so ${i}/4=${i/4}em \u2248 ${s} at default density`}function E(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function A(e){for(let s in e)if(V.has(s))return s}function $(e,s={}){let t=[];return k(e,"",t,!1,s.runReactive!==!1),t}function k(e,s,t,n,r){var g;if(typeof e=="function"){if(!r)return;let o;try{o=e(()=>{})}catch(a){return}k(o,s,t,!0,r);return}if(Array.isArray(e)){let o=e.filter(h=>E(h)&&A(h));n&&(o.length>1&&o.some(h=>h._key===void 0)&&t.push({rule:"missing-key",severity:"warning",path:s||"(list)",message:"Dynamic list child without `_key` \u2014 reordered/keyed lists need a stable `_key` for correct reconcile.",hint:"Add `_key: <stable id>` to each item produced by the reactive function."}),o.length>1&&o.every((h,c)=>h._key===c)&&t.push({rule:"unstable-key",severity:"warning",path:s||"(list)",message:"Dynamic list `_key` values are the array index (0, 1, 2, \u2026) \u2014 index keys are unstable across reorders/inserts.",hint:"Key by a stable identity from the data (e.g. `_key: item.id`), not the loop index."}));let a=new Map;for(let h of o){let c=h._key;if(c==null)continue;let y=`${typeof c}:${String(c)}`;a.set(y,((g=a.get(y))!=null?g:0)+1)}for(let[h,c]of a)if(c>1){let y=h.slice(h.indexOf(":")+1);t.push({rule:"duplicate-key",severity:"error",path:s||"(list)",message:`Duplicate \`_key\` "${y}" among ${c} siblings \u2014 keys must be unique within a list.`,hint:"Give each sibling a distinct stable `_key` (e.g. a record id, not a constant)."})}e.forEach((h,c)=>{k(h,`${s}[${c}]`,t,!1,r)});return}if(!E(e))return;let i=e,u=A(i),l=u?s?`${s} > ${u}`:u:s||"(root)";if(!u){let o=Object.keys(i).filter(a=>!K.has(a)&&!a.startsWith("_on")&&!a.startsWith("on")&&!a.startsWith("data")&&!a.startsWith("aria"));o.length===1&&t.push({rule:"unknown-tag",severity:"warning",path:l,message:`"${o[0]}" is not a known HTML/SVG tag \u2014 likely a typo.`,hint:"An element's first key must be a valid tag (div, button, span, \u2026)."});return}let d=i[u];if(G.has(u)&&d!==null&&d!==void 0&&t.push({rule:"void-content",severity:"error",path:l,message:`Void tag "${u}" must have null content (got ${Array.isArray(d)?"array":typeof d}).`,hint:`Write { ${u}: null, \u2026 } and put attributes as sibling keys.`}),E(i.style)){let o=i.style;for(let a in o){let h=o[a];if(Y.has(a)&&typeof h!="function"&&t.push({rule:"inline-typography",severity:"warning",path:l,message:`Inline \`${a}\` \u2014 avoid inline typography styles.`,hint:"Use a typography patch (paragraph()/heading()/small()/strong()/\u2026) via $ so the theme owns the type scale."}),Z.has(a)&&typeof h=="string"&&J.test(h)){let c=et(h),y=c?st(c):"(l) => themeColor(l, tone, colorName)";t.push({rule:"raw-theme-value",severity:"info",path:l,message:`Inline \`${a}\` uses a literal color (${h}).`,hint:`Prefer a theme token \u2014 ${y} \u2014 so theming and dark mode apply.`})}if(X.has(a)&&typeof h=="string"){let c=nt(a,h);c&&t.push({rule:"raw-spacing-value",severity:"info",path:l,message:`Inline \`${a}: "${h}"\` uses a literal spacing value.`,hint:`Prefer themeSpacing() for theme density: ${c}`})}}}let m=i.dataTone;if(typeof m=="string")if(!tt(m))t.push({rule:"unknown-tone",severity:"warning",path:l,message:`\`dataTone\` "${m}" is not a valid tone.`,hint:'Use "inherit", "base", a number, or "shift-N"/"increase-N"/"decrease-N" with N \u2264 17 (the ramp has 18 steps). Words like "surface"/"text" are not tones.'});else{let o=_(m);(o==null?void 0:o.family)==="shift"&&o.n>=4&&o.n<=13&&t.push({rule:"middle-surface-anchor",severity:"warning",path:l,message:`\`dataTone: "${m}"\` uses a mid-ramp surface anchor (steps 4\u201313). Child tones derived from this surface may clamp and collapse contrast.`,hint:"Prefer edge anchors: shift-0\u20133 for light surfaces, shift-14\u201317 for dark. Mid anchors are only correct for intentionally inverted/highlighted regions."})}let f=i.dataDensity;if(typeof f=="string"&&f!=="inherit"){let o=_(f);!o||o.family==="shift"?t.push({rule:"unknown-density",severity:"warning",path:l,message:`\`dataDensity\` "${f}" is not a valid density offset.`,hint:'Use "inherit", "increase-N", or "decrease-N" where N is 0\u20134. "shift-" is not valid for density.'}):o.n>4&&t.push({rule:"unknown-density",severity:"error",path:l,message:`\`dataDensity\` "${f}" N=${o.n} is out of range \u2014 the density scale has 5 steps (max offset: 4).`,hint:'Use "increase-N" or "decrease-N" where N \u2264 4. Density factors: [0.75, 1, 1.5, 2, 2.5].'})}let p=i.dataSize;if(typeof p=="string"&&p!=="inherit"){let o=_(p);!o||o.family==="shift"?t.push({rule:"unknown-size",severity:"warning",path:l,message:`\`dataSize\` "${p}" is not a valid size offset.`,hint:'Use "inherit", "increase-N", or "decrease-N" where N is 0\u20137. "shift-" is not valid for size.'}):o.n>7&&t.push({rule:"unknown-size",severity:"error",path:l,message:`\`dataSize\` "${p}" N=${o.n} is out of range \u2014 the size scale has 8 steps (max offset: 7).`,hint:'Use "increase-N" or "decrease-N" where N \u2264 7.'})}k(d,l,t,!1,r)}function M(e,s={}){let t=$(e,s),n={error:0,warning:0,info:0,total:t.length};for(let r of t)n[r.severity]+=1;return{ok:n.error===0,issues:t,summary:n}}function D(e){if(e.length===0)return"\u2713 No issues found.";let s=t=>t==="error"?"\u2717":t==="warning"?"\u26A0":"i";return e.map(t=>`${s(t.severity)} [${t.rule}] ${t.path}
2
- ${t.message}${t.hint?`
3
- \u2192 ${t.hint}`:""}`).join(`
4
- `)}var it=new Set([...b,...w]),rt=new Set(v);function I(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function ot(e){for(let s in e)if(it.has(s))return s}function R(e){if(Array.isArray(e))return e.map(R);if(I(e)){let s={};for(let t in e)s[t]=R(e[t]);return s}return e}function B(e,s={}){let t=R(e),n=[];return T(t,"",n),{tree:t,applied:n,report:M(t,s)}}function T(e,s,t){if(Array.isArray(e)){for(let[i,u]of e.entries())T(u,`${s}[${i}]`,t);return}if(!I(e))return;let n=ot(e);if(!n)return;let r=s?`${s} > ${n}`:n;rt.has(n)&&e[n]!==null&&e[n]!==void 0&&(e[n]=null,t.push({rule:"void-content",path:r,message:`Void tag <${n}> cannot have content \u2014 cleared to null.`})),T(e[n],r,t)}return H(at);})();
1
+ "use strict";var Domphy=(()=>{var E=Object.defineProperty;var K=Object.getOwnPropertyDescriptor;var Y=Object.getOwnPropertyNames;var Z=Object.prototype.hasOwnProperty;var j=(e,t)=>{for(var s in t)E(e,s,{get:t[s],enumerable:!0})},J=(e,t,s,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Y(t))!Z.call(e,n)&&n!==s&&E(e,n,{get:()=>t[n],enumerable:!(i=K(t,n))||i.enumerable});return e};var X=e=>J(E({},"__esModule",{value:!0}),e);var pt={};j(pt,{doctor:()=>R});var R={};j(R,{diagnose:()=>C,fix:()=>V,format:()=>W,validate:()=>x});var Q=e=>{let t=s=>s>.04045?Math.pow((s+.055)/1.055,2.4):s/12.92;return e.map(t)};var A=e=>{let t=parseInt(e.slice(1,3),16)/255,s=parseInt(e.slice(3,5),16)/255,i=parseInt(e.slice(5,7),16)/255;return Q([t,s,i])};var I=e=>{let[t,s,i]=e,n=.4124564*t+.3575761*s+.1804375*i,r=.2126729*t+.7151522*s+.072175*i,l=.0193339*t+.119192*s+.9503041*i,c=.95047,u=1,f=1.08883,m=g=>g>.008856?Math.cbrt(g):7.787*g+16/116,w=m(n/c),p=m(r/u),b=m(l/f);return[116*p-16,500*(w-p),200*(p-b)]};var B=e=>{let[t,s,i]=e,n=Math.sqrt(s*s+i*i);if(n<1e-4)return[t,0,0];let r=(Math.atan2(i,s)*180/Math.PI+360)%360;return r>=359.9999&&(r=0),[t,n,r]};var P=e=>{let t=e.match(/\d+(\.\d+)?/g);if(!t||t.length<3)throw new Error("Invalid CSS rgb()");let s=i=>{let n=i/255;return n<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)};return[s(Number(t[0])),s(Number(t[1])),s(Number(t[2]))]};var U=["a","abbr","address","article","aside","audio","b","base","blockquote","br","button","canvas","caption","cite","code","col","colgroup","data","datalist","dd","del","details","dfn","dialog","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","i","iframe","img","input","ins","kbd","label","legend","li","main","map","mark","meta","meter","nav","noscript","object","ol","optgroup","option","output","p","param","picture","pre","progress","q","rp","rt","ruby","s","samp","section","select","slot","small","source","span","strong","sub","summary","sup","table","tbody","td","template","textarea","tfoot","th","thead","time","title","tr","track","u","ul","var","video","wbr","bdi","bdo","math","menu","search","area","embed","hr","animate","animateMotion","animateTransform","circle","clipPath","cursor","defs","desc","ellipse","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feDropShadow","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence","filter","foreignObject","g","image","line","linearGradient","marker","mask","metadata","mpath","path","pattern","polygon","polyline","prefetch","radialGradient","rect","set","solidColor","stop","svg","switch","symbol","tbreak","text","textPath","tspan","use","view"];var F=["svg","circle","path","rect","ellipse","line","polyline","polygon","g","defs","use","symbol","linearGradient","radialGradient","stop","clipPath","mask","filter","text","tspan","textPath","image","pattern","marker","animate","animateTransform","animateMotion","feGaussianBlur","feComposite","feColorMatrix","feMerge","feMergeNode","feOffset","feFlood","feBlend","foreignObject"],z=["area","base","br","col","embed","hr","img","input","link","meta","source","track","wbr"];var tt=["onAbort","onAuxClick","onBeforeMatch","onBeforeToggle","onBlur","onCancel","onCanPlay","onCanPlayThrough","onChange","onClick","onClose","onContextLost","onContextMenu","onContextRestored","onCopy","onCueChange","onCut","onDblClick","onDrag","onDragEnd","onDragEnter","onDragLeave","onDragOver","onDragStart","onDrop","onDurationChange","onEmptied","onEnded","onError","onFocus","onFormData","onInput","onInvalid","onKeyDown","onKeyPress","onKeyUp","onLoad","onLoadedData","onLoadedMetadata","onLoadStart","onMouseDown","onMouseEnter","onMouseLeave","onMouseMove","onMouseOut","onMouseOver","onMouseUp","onPaste","onPause","onPlay","onPlaying","onProgress","onRateChange","onReset","onResize","onScroll","onScrollEnd","onSecurityPolicyViolation","onSeeked","onSeeking","onSelect","onSlotChange","onStalled","onSubmit","onSuspend","onTimeUpdate","onToggle","onVolumeChange","onWaiting","onWheel","onTouchStart","onTouchMove","onTouchEnd","onTouchCancel","onPointerDown","onPointerMove","onPointerUp","onPointerCancel","onPointerEnter","onPointerLeave","onPointerOver","onPointerOut","onGotPointerCapture","onLostPointerCapture","onCompositionStart","onCompositionUpdate","onCompositionEnd","onTransitionEnd","onTransitionStart","onAnimationStart","onAnimationEnd","onAnimationIteration","onFullscreenChange","onFullscreenError","onFocusIn","onFocusOut"],bt=tt.reduce((e,t)=>{let s=t.slice(2).toLowerCase();return e[s]=t,e},{});var vt=typeof process!="undefined"&&process.env!=null&&process.env.NODE_ENV!=="production";var et=new Set([...U,...F]),k=new Set(z);function y(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function _(e){for(let t in e)if(et.has(t))return t}var st=new Set(["$","style","_key","_portal","_context","_metadata","_doctorDisable"]),it=new Set(["fontSize","lineHeight","fontWeight","letterSpacing","fontFamily","textDecoration"]),nt=new Set(["color","backgroundColor","background","borderColor","border","outlineColor","outline","fill","stroke"]),rt=new Set(["color","fill","stroke","backgroundColor","outlineColor","borderColor","caretColor","accentColor","columnRuleColor","textDecorationColor"]),ot=new Set(["transparent","currentcolor","inherit","initial","unset","none","auto","revert","revert-layer",""]),H=/#[0-9a-fA-F]{3,8}\b|\b(?:rgba?|hsla?)\s*\(/,at=new Set(["margin","marginTop","marginRight","marginBottom","marginLeft","marginInline","marginBlock","marginInlineStart","marginInlineEnd","marginBlockStart","marginBlockEnd","padding","paddingTop","paddingRight","paddingBottom","paddingLeft","paddingInline","paddingBlock","paddingInlineStart","paddingInlineEnd","paddingBlockStart","paddingBlockEnd","gap","rowGap","columnGap"]),lt=/^(\d+(?:\.\d+)?)(rem|em|px)$/;function M(e){let t=e.match(/^(increase|decrease|shift)-(\d+)$/);return t?{family:t[1],n:parseInt(t[2],10)}:null}function ht(e){if(e==="inherit"||e==="base"||/^-?\d+$/.test(e))return!0;let t=M(e);return t?t.n<=17:!1}function ut(e){try{let t=e.trim(),s;if(t.startsWith("#")){let r=t;if(r.length===9&&(r=r.slice(0,7)),r.length===5&&(r=r.slice(0,4)),r.length===4&&(r=`#${r[1]}${r[1]}${r[2]}${r[2]}${r[3]}${r[3]}`),r.length!==7)return null;s=A(r)}else if(/^rgba?\s*\(/.test(t))s=P(t);else return null;let i=I(s),n=B(i);return[n[0],n[1],n[2]]}catch(t){return null}}var ct=/#[0-9a-fA-F]{3,8}\b|rgba?\s*\([^)]*\)/;function ft(e){let t=ct.exec(e);return t?t[0]:null}function dt(e){let[t,s,i]=e,n=Math.round((t-50)/10),r=Math.max(-9,Math.min(9,n)),l;Math.abs(r)<=1?l='"base"':r<0?l=`"decrease-${Math.abs(r)}"`:l=`"increase-${r}"`;let c;return s<12?c="neutral":i<30||i>=330?c="error":i<75?c="warning":i<165?c="success":(i<265,c="primary"),`(l) => themeColor(l, ${l}, "${c}") [perceptual LCH L=${Math.round(t)} C=${Math.round(s)} h=${Math.round(i)}\xB0]`}function mt(e,t){let s=lt.exec(t);if(!s)return null;let i=parseFloat(s[1]),n=s[2],r;return n==="rem"||n==="em"?r=Math.round(i*4):r=Math.round(i/4),r<=0?null:`${e}: themeSpacing(${r}) \u2014 themeSpacing(n)=n/4em, so ${r}/4=${r/4}em \u2248 ${t} at default density`}function q(e,t,s,i,n){if(e===!0){for(let r of s)r.path!==i&&n.push(r);return}if(e!=null&&e!==!1){let r=new Set(Array.isArray(e)?e:[String(e)]);for(let l of t)r.has(l.rule)||n.push(l);for(let l of s)l.path===i&&r.has(l.rule)||n.push(l);return}n.push(...t),n.push(...s)}function C(e,t={}){let s=[];if(S(e,"",s,!1,t),t.only!==void 0){if(t.only.length===0)return[];let i=new Set(t.only);return s.filter(n=>i.has(n.rule))}if(t.exclude&&t.exclude.length>0){let i=new Set(t.exclude);return s.filter(n=>!i.has(n.rule))}return s}function S(e,t,s,i,n){var O,N,D;let r=n.runReactive!==!1;if(typeof e=="function"){if(!r)return;let o;try{o=e(()=>{})}catch(h){return}S(o,t,s,!0,n);return}if(Array.isArray(e)){let o=e.filter(a=>y(a)&&_(a));i&&(o.length>1&&o.some(a=>a._key===void 0)&&s.push({rule:"missing-key",severity:"warning",category:"key",path:t||"(list)",message:"Dynamic list child without `_key` \u2014 reordered/keyed lists need a stable `_key` for correct reconcile.",hint:"Add `_key: <stable id>` to each item produced by the reactive function."}),o.length>1&&o.every((a,d)=>a._key===d)&&s.push({rule:"unstable-key",severity:"warning",category:"key",path:t||"(list)",message:"Dynamic list `_key` values are the array index (0, 1, 2, \u2026) \u2014 index keys are unstable across reorders/inserts.",hint:"Key by a stable identity from the data (e.g. `_key: item.id`), not the loop index."}));let h=new Map;for(let a of o){let d=a._key;if(d==null)continue;let v=`${typeof d}:${String(d)}`;h.set(v,((O=h.get(v))!=null?O:0)+1)}for(let[a,d]of h)if(d>1){let v=a.slice(a.indexOf(":")+1);s.push({rule:"duplicate-key",severity:"error",category:"key",path:t||"(list)",message:`Duplicate \`_key\` "${v}" among ${d} siblings \u2014 keys must be unique within a list.`,hint:"Give each sibling a distinct stable `_key` (e.g. a record id, not a constant)."})}e.forEach((a,d)=>{S(a,`${t}[${d}]`,s,!1,n)});return}if(!y(e))return;let l=e,c=_(l),u=c?t?`${t} > ${c}`:c:t||"(root)",f=[];if(!c){let o=Object.keys(l).filter(h=>!st.has(h)&&!h.startsWith("_on")&&!h.startsWith("on")&&!h.startsWith("data")&&!h.startsWith("aria"));o.length===1&&f.push({rule:"unknown-tag",severity:"warning",category:"structure",path:u,message:`"${o[0]}" is not a known HTML/SVG tag \u2014 likely a typo.`,hint:"An element's first key must be a valid tag (div, button, span, \u2026)."}),q(l._doctorDisable,f,[],u,s);return}let m=l[c];if(k.has(c)&&m!==null&&m!==void 0&&f.push({rule:"void-content",severity:"error",category:"structure",path:u,message:`Void tag "${c}" must have null content (got ${Array.isArray(m)?"array":typeof m}).`,hint:`Write { ${c}: null, \u2026 } and put attributes as sibling keys.`}),y(l.style)){let o=l.style;for(let h in o){let a=o[h];if(it.has(h)&&typeof a!="function"&&f.push({rule:"inline-typography",severity:"warning",category:"typography",path:u,message:`Inline \`${h}\` \u2014 avoid inline typography styles.`,hint:"Use a typography patch (paragraph()/heading()/small()/strong()/\u2026) via $ so the theme owns the type scale."}),nt.has(h)&&typeof a=="string"&&H.test(a)){let d=(N=ft(a))!=null?N:a,v=ut(d),G=v?dt(v):"(l) => themeColor(l, tone, colorName)";f.push({rule:"raw-theme-value",severity:"info",category:"theme",path:u,message:`Inline \`${h}\` uses a literal color (${a}).`,hint:`Prefer a theme token \u2014 ${G} \u2014 so theming and dark mode apply.`})}if(rt.has(h)&&typeof a=="string"&&!H.test(a)&&!a.includes("(")&&!a.startsWith("--")&&!ot.has(a.trim().toLowerCase())&&f.push({rule:"raw-theme-value",severity:"info",category:"theme",path:u,message:`Inline \`${h}\` uses a CSS named color ("${a}").`,hint:`CSS named colors like "${a}" bypass theming and dark mode. Prefer (l) => themeColor(l, tone, colorName) \u2014 so the theme context applies.`}),at.has(h)&&typeof a=="string"){let d=mt(h,a);d&&f.push({rule:"raw-spacing-value",severity:"info",category:"theme",path:u,message:`Inline \`${h}: "${a}"\` uses a literal spacing value.`,hint:`Prefer themeSpacing() for theme density: ${d}`})}}}let w=y(l.style)?l.style.backgroundColor:void 0;if(typeof w=="function"&&r){let o;try{o=w(()=>{})}catch(h){}if(typeof o=="string"){let h=o.match(/var\(--[\w-]+-(\d+)\)$/);h&&parseInt(h[1],10)>0&&f.push({rule:"tone-background-inherit",severity:"warning",category:"theme",path:u,message:`\`style.backgroundColor\` uses a fixed tone (resolves to "${o}" at base context) instead of "inherit".`,hint:'backgroundColor should always be (l) => themeColor(l, "inherit"). To shift the surface tone, set dataTone on the container \u2014 it applies to all children uniformly.'})}}let p=l.dataTone;if(typeof p=="string")if(!ht(p))f.push({rule:"unknown-tone",severity:"warning",category:"data-attr",path:u,message:`\`dataTone\` "${p}" is not a valid tone.`,hint:'Use "inherit", "base", a number, or "shift-N"/"increase-N"/"decrease-N" with N \u2264 17 (the ramp has 18 steps). Words like "surface"/"text" are not tones.'});else{let o=M(p);(o==null?void 0:o.family)==="shift"&&o.n>=4&&o.n<=13&&f.push({rule:"middle-surface-anchor",severity:"warning",category:"data-attr",path:u,message:`\`dataTone: "${p}"\` uses a mid-ramp surface anchor (steps 4\u201313). Child tones derived from this surface may clamp and collapse contrast.`,hint:"Prefer edge anchors: shift-0\u20133 for light surfaces, shift-14\u201317 for dark. Mid anchors are only correct for intentionally inverted/highlighted regions."})}let b=l.dataDensity;if(typeof b=="string"&&b!=="inherit"){let o=M(b);!o||o.family==="shift"?f.push({rule:"unknown-density",severity:"warning",category:"data-attr",path:u,message:`\`dataDensity\` "${b}" is not a valid density offset.`,hint:'Use "inherit", "increase-N", or "decrease-N" where N is 0\u20134. "shift-" is not valid for density.'}):o.n>4&&f.push({rule:"unknown-density",severity:"error",category:"data-attr",path:u,message:`\`dataDensity\` "${b}" N=${o.n} is out of range \u2014 the density scale has 5 steps (max offset: 4).`,hint:'Use "increase-N" or "decrease-N" where N \u2264 4. Density factors: [0.75, 1, 1.5, 2, 2.5].'})}let g=l.dataSize;if(typeof g=="string"&&g!=="inherit"){let o=M(g);!o||o.family==="shift"?f.push({rule:"unknown-size",severity:"warning",category:"data-attr",path:u,message:`\`dataSize\` "${g}" is not a valid size offset.`,hint:'Use "inherit", "increase-N", or "decrease-N" where N is 0\u20137. "shift-" is not valid for size.'}):o.n>7&&f.push({rule:"unknown-size",severity:"error",category:"data-attr",path:u,message:`\`dataSize\` "${g}" N=${o.n} is out of range \u2014 the size scale has 8 steps (max offset: 7).`,hint:'Use "increase-N" or "decrease-N" where N \u2264 7.'})}if(n.rules&&n.rules.length>0)for(let o of n.rules){let h;try{h=o.check(l,u,c)}catch(a){continue}for(let a of h)f.push({rule:o.id,severity:(D=a.severity)!=null?D:o.severity,category:o.category,path:u,message:a.message,hint:a.hint})}let L=[];S(m,u,L,!1,n),q(l._doctorDisable,f,L,u,s)}function x(e,t={}){let s=C(e,t),i={error:0,warning:0,info:0,total:s.length};for(let n of s)i[n.severity]+=1;return{ok:i.error===0,issues:s,summary:i}}function W(e){if(e.length===0)return"\u2713 No issues found.";let t=s=>s==="error"?"\u2717":s==="warning"?"\u26A0":"i";return e.map(s=>`${t(s.severity)} [${s.rule}] ${s.path}
2
+ ${s.message}${s.hint?`
3
+ \u2192 ${s.hint}`:""}`).join(`
4
+ `)}function $(e){if(Array.isArray(e))return e.map($);if(y(e)){let t={};for(let s in e)t[s]=$(e[s]);return t}return e}function V(e,t={}){let s=$(e),i=[];return T(s,"",i),{tree:s,applied:i,report:x(s,t)}}function T(e,t,s){if(Array.isArray(e)){for(let[r,l]of e.entries())T(l,`${t}[${r}]`,s);return}if(!y(e))return;let i=_(e);if(!i)return;let n=t?`${t} > ${i}`:i;k.has(i)&&e[i]!==null&&e[i]!==void 0&&(e[i]=null,s.push({rule:"void-content",path:n,message:`Void tag <${i}> cannot have content \u2014 cleared to null.`})),T(e[i],n,s)}return X(pt);})();
5
5
  //# sourceMappingURL=doctor.global.js.map