@theme-registry/refract 0.1.1 → 0.1.2
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 +4 -4
- package/dist/_errors-be768b25.cjs.js.map +1 -1
- package/dist/_errors-d75a5c74.esm.js.map +1 -1
- package/dist/build.cjs.js +1 -1
- package/dist/build.cjs.js.map +1 -1
- package/dist/build.esm.js +1 -1
- package/dist/build.esm.js.map +1 -1
- package/dist/cli.js +69 -24
- package/dist/cli.js.map +1 -1
- package/dist/core/assertRawTheme.d.ts +2 -0
- package/dist/core/errors.d.ts +5 -2
- package/dist/core/index.d.ts +1 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/skills/adapter-scaffold/SKILL.md +2 -2
- package/skills/adapter-usage/SKILL.md +1 -1
- package/skills/colors/SKILL.md +1 -1
- package/skills/layout/SKILL.md +1 -1
- package/skills/theme-authoring/SKILL.md +1 -1
- package/skills/typography/SKILL.md +1 -1
- package/skills/visual-effects/SKILL.md +1 -1
package/dist/core/errors.d.ts
CHANGED
|
@@ -7,12 +7,15 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Scope: authoring/build errors. Pure CLI-tooling failures in `src/build/*` (bad arguments, a missing
|
|
9
9
|
* file, an unknown command) stay plain `Error`s — they're usage errors from `refract <cmd>`, not a
|
|
10
|
-
* problem with the theme an agent is editing.
|
|
10
|
+
* problem with the theme an agent is editing. The one build-layer exception is `REFRACT_E_RAW_SHAPE`:
|
|
11
|
+
* a value handed to `diff` / `validate` (or the MCP server) where a `RawTheme` is required but the
|
|
12
|
+
* value isn't theme-shaped — that IS a theme problem, and a governance tool must fail loud + coded on
|
|
13
|
+
* it (see {@link assertRawTheme}) rather than emit a nonsense "everything removed" diff at exit 0.
|
|
11
14
|
*
|
|
12
15
|
* Dependency-free leaf on purpose, so any module (including the standalone `adapter-kit`) can throw one
|
|
13
16
|
* without pulling in the core graph.
|
|
14
17
|
*/
|
|
15
|
-
export type RefractErrorCode = "REFRACT_E_COLOR_INPUT" | "REFRACT_E_COLOR_TUPLE" | "REFRACT_E_STEPS" | "REFRACT_E_VARIANT" | "REFRACT_E_VARIANT_REF" | "REFRACT_E_CYCLE" | "REFRACT_E_ADJUST" | "REFRACT_E_HARMONY" | "REFRACT_E_VALIDATION" | "REFRACT_E_RECIPE_PROPERTY" | "REFRACT_E_TOKEN_PATH" | "REFRACT_E_BREAKPOINT" | "REFRACT_E_STATE" | "REFRACT_E_CONTAINER" | "REFRACT_E_RESPONSIVE" | "REFRACT_E_MEDIA" | "REFRACT_E_MODE" | "REFRACT_E_PRESET" | "REFRACT_E_EFFECTS" | "REFRACT_E_LAYOUT" | "REFRACT_E_UNITS" | "REFRACT_E_PROPERTY" | "REFRACT_E_REFERENCE" | "REFRACT_E_NAMING" | "REFRACT_E_DTCG_VERSION" | "REFRACT_E_AUDIT";
|
|
18
|
+
export type RefractErrorCode = "REFRACT_E_COLOR_INPUT" | "REFRACT_E_COLOR_TUPLE" | "REFRACT_E_STEPS" | "REFRACT_E_VARIANT" | "REFRACT_E_VARIANT_REF" | "REFRACT_E_CYCLE" | "REFRACT_E_ADJUST" | "REFRACT_E_HARMONY" | "REFRACT_E_VALIDATION" | "REFRACT_E_RECIPE_PROPERTY" | "REFRACT_E_TOKEN_PATH" | "REFRACT_E_BREAKPOINT" | "REFRACT_E_STATE" | "REFRACT_E_CONTAINER" | "REFRACT_E_RESPONSIVE" | "REFRACT_E_MEDIA" | "REFRACT_E_MODE" | "REFRACT_E_PRESET" | "REFRACT_E_EFFECTS" | "REFRACT_E_LAYOUT" | "REFRACT_E_UNITS" | "REFRACT_E_PROPERTY" | "REFRACT_E_REFERENCE" | "REFRACT_E_NAMING" | "REFRACT_E_DTCG_VERSION" | "REFRACT_E_AUDIT" | "REFRACT_E_RAW_SHAPE";
|
|
16
19
|
/**
|
|
17
20
|
* An authoring / build error with a stable {@link RefractErrorCode}. For an aggregate (collect-all)
|
|
18
21
|
* error, `failures` lists each individual message so a caller can report them all at once.
|
package/dist/core/index.d.ts
CHANGED
package/dist/index.cjs.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var e=require("./_errors-be768b25.cjs.js"),r=require("./_createTheme-41c01033.cjs.js"),
|
|
1
|
+
"use strict";var e=require("./_errors-be768b25.cjs.js"),r=require("./_createTheme-41c01033.cjs.js"),t=require("./color-math.cjs.js");const o=e=>{const[r,t]=e.split(":");if(!r||!t)return;const o=t.indexOf(".");return o<0?void 0:{subsystem:r,group:t.slice(0,o),variant:t.slice(o+1)}},s=(e,r)=>{var t,s,n;const i=o(r);if(i)return null===(n=null===(s=null===(t=e.subsystems[i.subsystem])||void 0===t?void 0:t.ruleSets)||void 0===s?void 0:s[i.group])||void 0===n?void 0:n[i.variant]},n=(e,r)=>{for(const[t,o]of Object.entries(r))e[t]={...o}},i=e=>{var r,t,o,s,n,i;return`${null!==(r=e.breakpoint)&&void 0!==r?r:""}|${null!==(t=e.query)&&void 0!==t?t:""}|${null!==(o=e.orientation)&&void 0!==o?o:""}|${null!==(s=e.state)&&void 0!==s?s:""}|${null!==(n=e.container)&&void 0!==n?n:""}|${null!==(i=e.size)&&void 0!==i?i:""}`};function a(e){var r;const t=[];for(const[o,s]of Object.entries(e.subsystems))for(const[e,n]of Object.entries(null!==(r=s.ruleSets)&&void 0!==r?r:{}))for(const r of Object.keys(n))t.push({subsystem:o,group:e,variant:r});return t}function l(e){return{name:e.name,version:e.version,allowedStates:e.allowedStates,bind(r,t){var o,s,n,i;const l=e.bind(r,t),u=null!==(o=l.renderAllRecipes)&&void 0!==o?o:()=>l.join(a(r).map(({subsystem:e,group:r,variant:t})=>l.renderRecipe(e,r,t))),p=null!==(s=l.renderAllVariables)&&void 0!==s?s:()=>l.join(Object.keys(r.subsystems).map(e=>l.renderVariables(e))),c=null!==(n=l.renderAll)&&void 0!==n?n:()=>l.join([p(),u()]),d=null!==(i=l.describeUsage)&&void 0!==i?i:()=>({format:e.name,summary:[`This theme was built with the "${e.name}" refract adapter.`],recipes:a(r).map(({subsystem:e,group:r,variant:t})=>({subsystem:e,group:r,variant:t,name:l.recipeName(e,r,t)}))});return{...l,renderAllRecipes:u,renderAllVariables:p,renderAll:c,describeUsage:d}}}}const u=e=>e<=.04045?e/12.92:Math.pow((e+.055)/1.055,2.4),p=([e,r,t])=>.2126*u(e/255)+.7152*u(r/255)+.0722*u(t/255),c={fail:0,"AA-large":1,AA:2,AAA:3},d=2.4,f=.2126729,v=.7151522,m=.072175,b=.56,R=.57,y=.62,g=.65,h=.022,S=1.414,x=1.14,A=.027,E=1.14,w=.027,T=5e-4,_=.1,k=([e,r,t])=>f*Math.pow(e/255,d)+v*Math.pow(r/255,d)+m*Math.pow(t/255,d),M=(e,r)=>{const t=e=>e>h?e:e+Math.pow(h-e,S),o=t(k(e)),s=t(k(r));if(Math.abs(s-o)<T)return 0;let n;if(s>o){const e=(Math.pow(s,b)-Math.pow(o,R))*x;n=e<_?0:e-A}else{const e=(Math.pow(s,g)-Math.pow(o,y))*E;n=e>-_?0:e+w}return 100*n},C=(e,r)=>{const t=10**r;return Math.round(e*t)/t},P=(e,r)=>{if(void 0!==r.ref)try{return String(e.resolveToken(r.ref))}catch{return}if("string"==typeof r.value)return r.value},$="color",j=["background-color","background"],O=e=>{if(e)for(const r of j)if(e[r])return e[r]},N=(e,r,o,s,n)=>{let i,a;try{void 0!==o&&(i=t.parseColor(o).rgb)}catch{}try{void 0!==s&&(a=t.parseColor(s).rgb)}catch{}if(!i||!a)return{kind:e,label:r,fg:o,bg:s,skipped:i||a?i?"bg not a colour":"fg not a colour":"no derivable fg/bg"};const l=((e,r)=>{const t=p(e),o=p(r);return(Math.max(t,o)+.05)/(Math.min(t,o)+.05)})(i,a),u=((e,r)=>r?e>=4.5?"AAA":e>=3?"AA":"fail":e>=7?"AAA":e>=4.5?"AA":e>=3?"AA-large":"fail")(l,n.largeText),d=c[u]>=c[n.minWcag];return{kind:e,label:r,fg:o,bg:s,wcagRatio:C(l,2),wcagLevel:u,apcaLc:C(M(i,a),1),pass:d}};exports.RefractError=e.RefractError,exports.BREAKPOINT_EPSILON=r.BREAKPOINT_EPSILON,exports.CSS_UNITS=r.CSS_UNITS,exports.DEFAULT_BASE_FONT_SIZE=r.DEFAULT_BASE_FONT_SIZE,exports.DEFAULT_BREAKPOINTS=r.DEFAULT_BREAKPOINTS,exports.DEFAULT_RESPONSIVE_QUERY=r.DEFAULT_RESPONSIVE_QUERY,exports.KNOWN_CSS_PROPERTIES=r.KNOWN_CSS_PROPERTIES,exports.LENGTH_REGISTRY=r.LENGTH_REGISTRY,exports.animationSubsystem=r.animationSubsystem,exports.bakeCrossPropertyDerivations=r.bakeCrossPropertyDerivations,exports.bordersSubsystem=r.bordersSubsystem,exports.buildComponentRuleSetFromInterpreted=r.buildComponentRuleSetFromInterpreted,exports.buildContainerDescriptors=r.buildContainerDescriptors,exports.buildDerivationRegistry=r.buildDerivationRegistry,exports.buildMediaDescriptor=r.buildMediaDescriptor,exports.buildPropertiesModel=r.buildPropertiesModel,exports.buildPropertyModel=r.buildPropertyModel,exports.buildRuleSetFromInterpreted=r.buildRuleSetFromInterpreted,exports.buildRuleSetGroupFromInterpreted=r.buildRuleSetGroupFromInterpreted,exports.buildSubsystemModel=r.buildSubsystemModel,exports.buildThemeModel=r.buildThemeModel,exports.buildTokenMap=r.buildTokenMap,exports.colorsSubsystem=r.colorsSubsystem,exports.componentsSubsystem=r.componentsSubsystem,exports.containerQueryString=r.containerQueryString,exports.createRecipeVariantResolver=r.createRecipeVariantResolver,exports.createTheme=r.createTheme,exports.effectsSubsystem=r.effectsSubsystem,exports.extractComponentReferences=r.extractComponentReferences,exports.formatWidth=r.formatWidth,exports.globalsSubsystem=r.globalsSubsystem,exports.isKnownCssProperty=r.isKnownCssProperty,exports.layoutSubsystem=r.layoutSubsystem,exports.mediaQuery=r.mediaQuery,exports.mediaQueryString=r.mediaQueryString,exports.normalizePropertyValue=r.normalizePropertyValue,exports.normalizeRecipeGroup=r.normalizeRecipeGroup,exports.normalizeResponsiveOverrides=r.normalizeResponsiveOverrides,exports.parseLength=r.parseLength,exports.pathifyProperties=r.pathifyProperties,exports.pathifyRuleSetGroup=r.pathifyRuleSetGroup,exports.resolveLengthRef=r.resolveLengthRef,exports.resolveMediaConfig=r.resolveMediaConfig,exports.resolveModelUnits=r.resolveModelUnits,exports.resolveRoleUnit=r.resolveRoleUnit,exports.resolveToken=r.resolveToken,exports.resolveTokenMap=r.resolveTokenMap,exports.sortBreakpointKeys=r.sortBreakpointKeys,exports.typographySubsystem=r.typographySubsystem,exports.validateNormalizedResponsiveRefs=r.validateNormalizedResponsiveRefs,exports.assertRawTheme=function(r,t){const o=t?` (${t})`:"";if(null===r||"object"!=typeof r||Array.isArray(r)){const t=Array.isArray(r)?"an array":null===r?"null":typeof r;throw new e.RefractError("REFRACT_E_RAW_SHAPE",`Expected a RawTheme object${o}, got ${t}. Pass the raw theme (a module's default export, or a .json raw theme).`)}if(Array.isArray(r.targets))throw new e.RefractError("REFRACT_E_RAW_SHAPE",`Expected a RawTheme object${o}, but got what looks like a defineConfig({ raw, targets }). Pass its \`raw\` (or a module that default-exports the raw theme), not the whole config.`)},exports.audit=(r,t={})=>{var o,s,n,i,a,l,u,p,c,d,f;const v={largeText:null!==(o=t.largeText)&&void 0!==o&&o,minWcag:null!==(s=t.minWcag)&&void 0!==s?s:"AA"},m=null===(n=t.includeRecipes)||void 0===n||n,b=[];if(null===(i=t.includePalettes)||void 0===i||i)for(const e of Object.keys(r.tokens)){const t=/^colors\.([^.]+)\.text$/.exec(e);if(!t)continue;const o=`colors.${t[1]}`;let s,n;try{s=String(r.resolveToken(e))}catch{}try{n=String(r.resolveToken(o))}catch{}b.push(N("palette",o,s,n,v))}if(m)for(const[e,t]of Object.entries(r.model.subsystems))if(t.ruleSets)for(const[o,s]of Object.entries(t.ruleSets))for(const[t,n]of Object.entries(s)){const s=n.declarations[$],i=O(n.declarations),m=`${e}.${o}.${t}`;s&&i&&b.push(N("recipe",m,P(r,s),P(r,i),v));for(const e of null!==(a=n.overrides)&&void 0!==a?a:[]){const t=null!==(u=null===(l=e.declarations)||void 0===l?void 0:l[$])&&void 0!==u?u:s,o=null!==(p=O(e.declarations))&&void 0!==p?p:i;if(!e.declarations||!e.declarations[$]&&!O(e.declarations))continue;if(!t||!o)continue;const n=null!==(f=null!==(d=null!==(c=e.state)&&void 0!==c?c:e.breakpoint)&&void 0!==d?d:e.query)&&void 0!==f?f:"override";b.push(N("recipe",`${m} (${n})`,P(r,t),P(r,o),v))}}const R=b.filter(e=>!e.skipped),y=R.filter(e=>!1===e.pass),g=R.reduce((e,r)=>{var t,o;return void 0===e||(null!==(t=r.wcagRatio)&&void 0!==t?t:1/0)<(null!==(o=e.wcagRatio)&&void 0!==o?o:1/0)?r:e},void 0),h={pairings:b,summary:{total:R.length,passed:R.length-y.length,failed:y.length,skipped:b.length-R.length,worst:g},ok:0===y.length};if(t.strict&&y.length>0){const r=y.map(e=>`${e.label} (${e.wcagRatio}:1, ${e.wcagLevel})`).join(", ");throw new e.RefractError("REFRACT_E_AUDIT",`refract audit: ${y.length} pairing(s) fail WCAG ${v.minWcag} — ${r}. Adjust the colour(s), lower --min-wcag, or drop --strict to report without failing.`,y.map(e=>`${e.label} (${e.wcagRatio}:1, ${e.wcagLevel})`))}return h},exports.createNoopAdapter=function(){return l({name:"noop",version:1,bind:()=>({recipeName:()=>"",renderRecipe:()=>"",renderVariables:()=>"",join:e=>e.join(""),emit:()=>({files:{}})})})},exports.defineAdapter=l,exports.mergeComponentRuleSet=(r,t,o)=>{var a,l,u,p,c,d;const f=null===(u=null===(l=null===(a=r.subsystems.components)||void 0===a?void 0:a.ruleSets)||void 0===l?void 0:l[t])||void 0===u?void 0:u[o];if(!f)throw new e.RefractError("REFRACT_E_REFERENCE",`mergeComponentRuleSet: no component rule-set "${t}.${o}"`);const v=[];for(const t of null!==(p=f.references)&&void 0!==p?p:[]){const o=s(r,t);if(!o)throw new e.RefractError("REFRACT_E_REFERENCE",`mergeComponentRuleSet: unresolved reference "${t}"`);v.push(o)}v.push(f);const m={},b={},R=new Map;for(const e of v){n(m,e.declarations);for(const r of e.overrides)if(r.declarations)if(void 0!==r.breakpoint||void 0!==r.container){const e=i(r);let t=R.get(e);t||(t={...void 0!==r.breakpoint?{breakpoint:r.breakpoint}:{},...void 0!==r.query?{query:r.query}:{},...void 0!==r.orientation?{orientation:r.orientation}:{},...void 0!==r.state?{state:r.state}:{},...void 0!==r.container?{container:r.container}:{},...void 0!==r.size?{size:r.size}:{},declarations:{}},R.set(e,t)),n(t.declarations,r.declarations)}else void 0!==r.state?(null!==(c=b[d=r.state])&&void 0!==c||(b[d]={}),n(b[r.state],r.declarations)):n(m,r.declarations)}const y=[...R.values()],g=new Set,h=[],S=e=>{for(const r of Object.values(e))void 0===r.ref||g.has(r.ref)||(g.add(r.ref),h.push(r.ref))};S(m);for(const e of Object.values(b))S(e);for(const e of y)S(e.declarations);return{base:m,states:b,responsive:y,referencedPaths:h}},exports.parseRuleSetReference=o,exports.ref=e=>({ref:e});
|
|
2
2
|
//# sourceMappingURL=index.cjs.js.map
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/core/model/mergeRuleSet.ts","../src/core/defineAdapter.ts","../src/subsystems/colors/audit.ts","../src/core/noopAdapter.ts","../src/core/ref.ts"],"sourcesContent":["/**\n * Format-neutral component merge (§9c).\n *\n * `mergeComponentRuleSet` flattens one component variant into a single\n * self-contained rule-set: its referenced recipes' declarations + its own `css`\n * delta, unioned. The result is pure Model data — declarations stay as {@link Ref}s\n * carrying `{ ref, value }` — so an adapter renders it as baked values (inline) or\n * `var(--…)` / `theme.…` (referenced) without any format decision leaking in here.\n *\n * This is the ONLY new machinery the `components` emit mode needs, shared by the CSS\n * and future SC adapters. It is **on-demand** (an adapter calls it in `emit()`), never\n * materialized on `ThemeModel` / the runtime `theme`. It does NOT mutate the authored\n * `RuleSet` / declarations — the merged view is freshly derived (Refs shallow-cloned).\n *\n * Precedence (LOCKED, §9): authored **reference order** first (later refs override\n * earlier per property key), then the component's own declarations **last / highest**\n * (`css` delta wins over subsystem recipes). Same rule per condition bucket.\n */\nimport type {\n Orientation,\n Ref,\n ResponsiveQueryKind,\n RuleSet,\n RuleSetOverride,\n ThemeModel,\n} from \"./model\";\nimport { RefractError } from \"../errors\";\n\n/**\n * One flattened conditioned bucket — a distinct `(breakpoint, query, orientation, state, container, size)`\n * key. A **viewport** entry carries `breakpoint`; a **container** entry (§10.5) carries `container` + `size`\n * (and no `breakpoint`). The adapter emits the former as `@media`, the latter as `@container`.\n */\nexport type MergedResponsiveEntry = {\n breakpoint?: string;\n query?: ResponsiveQueryKind;\n orientation?: Orientation;\n state?: string;\n container?: string;\n size?: string;\n declarations: Record<string, Ref>;\n};\n\n/**\n * A component variant flattened into one self-contained rule-set.\n *\n * - `base` — merged no-condition declarations.\n * - `states` — merged declarations keyed by `state` (no breakpoint).\n * - `responsive` — one entry per distinct `(breakpoint, query, orientation, state)` merge key.\n * - `referencedPaths` — every distinct token path (`Ref.ref`) appearing across all buckets,\n * first-appearance order. What non-inline rendering tree-shakes the vars file to.\n */\nexport type MergedRuleSet = {\n base: Record<string, Ref>;\n states: Record<string, Record<string, Ref>>;\n responsive: MergedResponsiveEntry[];\n referencedPaths: string[];\n};\n\n/** The address parts of a component reference (`\"colors:solid.primary\"`). */\nexport type RuleSetReference = { subsystem: string; group: string; variant: string };\n\n/**\n * Parse a component reference (`\"subsystem:group.variant\"`) into its address parts.\n * Format-neutral core twin of the CSS adapter's `parseComponentReference` (which stays\n * for the option-C class-list path). Returns `undefined` on a malformed reference.\n */\nexport const parseRuleSetReference = (reference: string): RuleSetReference | undefined => {\n const [subsystem, rest] = reference.split(\":\");\n if (!subsystem || !rest) return undefined;\n const dot = rest.indexOf(\".\");\n if (dot < 0) return undefined;\n return { subsystem, group: rest.slice(0, dot), variant: rest.slice(dot + 1) };\n};\n\n/** Resolve a reference to its authored `RuleSet`, or `undefined` if it doesn't address one. */\nconst resolveReference = (model: ThemeModel, reference: string): RuleSet | undefined => {\n const parsed = parseRuleSetReference(reference);\n if (!parsed) return undefined;\n return model.subsystems[parsed.subsystem]?.ruleSets?.[parsed.group]?.[parsed.variant];\n};\n\n/** Fold `source` declarations into `target` (later source wins), shallow-cloning each Ref. */\nconst mergeDeclarations = (target: Record<string, Ref>, source: Record<string, Ref>): void => {\n for (const [prop, ref] of Object.entries(source)) target[prop] = { ...ref };\n};\n\n/** Stable string key for a conditioned bucket — `(breakpoint, query, orientation, state, container, size)`. */\nconst responsiveKey = (o: RuleSetOverride): string =>\n `${o.breakpoint ?? \"\"}|${o.query ?? \"\"}|${o.orientation ?? \"\"}|${o.state ?? \"\"}|${o.container ?? \"\"}|${o.size ?? \"\"}`;\n\n/**\n * Flatten one component variant into a self-contained {@link MergedRuleSet}.\n *\n * Reads `model.subsystems.components.ruleSets[group][variant]` — its `references`\n * (resolved in authored order), own base `declarations`, and `overrides` — and unions\n * them under the locked precedence. Throws on a missing component or an unresolved reference.\n */\nexport const mergeComponentRuleSet = (\n model: ThemeModel,\n group: string,\n variant: string,\n): MergedRuleSet => {\n const own = model.subsystems.components?.ruleSets?.[group]?.[variant];\n if (!own) {\n throw new RefractError(\"REFRACT_E_REFERENCE\", `mergeComponentRuleSet: no component rule-set \"${group}.${variant}\"`);\n }\n\n // Sources in precedence order: referenced rule-sets left-to-right, then the component's own last.\n const sources: RuleSet[] = [];\n for (const reference of own.references ?? []) {\n const resolved = resolveReference(model, reference);\n if (!resolved) {\n throw new RefractError(\"REFRACT_E_REFERENCE\", `mergeComponentRuleSet: unresolved reference \"${reference}\"`);\n }\n sources.push(resolved);\n }\n sources.push(own);\n\n const base: Record<string, Ref> = {};\n const states: Record<string, Record<string, Ref>> = {};\n const responsiveByKey = new Map<string, MergedResponsiveEntry>();\n\n for (const source of sources) {\n mergeDeclarations(base, source.declarations);\n\n for (const override of source.overrides) {\n if (!override.declarations) continue;\n // A breakpoint OR container condition → a conditioned bucket (viewport → @media, container →\n // @container). Container overrides MUST route here, not fold into base (§10.5 correctness).\n if (override.breakpoint !== undefined || override.container !== undefined) {\n const key = responsiveKey(override);\n let entry = responsiveByKey.get(key);\n if (!entry) {\n entry = {\n ...(override.breakpoint !== undefined ? { breakpoint: override.breakpoint } : {}),\n ...(override.query !== undefined ? { query: override.query } : {}),\n ...(override.orientation !== undefined ? { orientation: override.orientation } : {}),\n ...(override.state !== undefined ? { state: override.state } : {}),\n ...(override.container !== undefined ? { container: override.container } : {}),\n ...(override.size !== undefined ? { size: override.size } : {}),\n declarations: {},\n };\n responsiveByKey.set(key, entry);\n }\n mergeDeclarations(entry.declarations, override.declarations);\n } else if (override.state !== undefined) {\n (states[override.state] ??= {});\n mergeDeclarations(states[override.state], override.declarations);\n } else {\n // Unconditional override (only variant/target, no breakpoint/state) — folds into base.\n mergeDeclarations(base, override.declarations);\n }\n }\n }\n\n const responsive = [...responsiveByKey.values()];\n\n // referencedPaths — every distinct token path across all buckets, first-appearance order.\n const seen = new Set<string>();\n const referencedPaths: string[] = [];\n const collect = (decls: Record<string, Ref>): void => {\n for (const ref of Object.values(decls)) {\n if (ref.ref !== undefined && !seen.has(ref.ref)) {\n seen.add(ref.ref);\n referencedPaths.push(ref.ref);\n }\n }\n };\n collect(base);\n for (const decls of Object.values(states)) collect(decls);\n for (const entry of responsive) collect(entry.declarations);\n\n return { base, states, responsive, referencedPaths };\n};\n","/**\n * `defineAdapter` — turns an `AdapterSpec` (identity + a `bind` returning the four\n * required primitives) into a full `ThemeAdapter` whose `bind` yields a complete\n * `BoundAdapter` with the DEFAULTED aggregators supplied.\n *\n * The defaults are pure Model walks: the Model enumerates every subsystem and every\n * (group, variant), so core loops it, calls the author's per-unit renderers, and\n * `join`s the results. Model/ctx are already bound, so the aggregators take no args.\n * An author can still override any aggregator (a format whose full document isn't a\n * flat concatenation).\n */\n\nimport type { ThemeModel } from \"./model\";\nimport type {\n AdapterSpec,\n ThemeAdapter,\n BoundAdapter,\n RenderContext,\n UsageDescriptor,\n} from \"./ThemeAdapter\";\n\n/** Every rule-set address in the Model — `(subsystem, group, variant)` triples. */\nfunction eachRuleSet(model: ThemeModel): Array<{ subsystem: string; group: string; variant: string }> {\n const out: Array<{ subsystem: string; group: string; variant: string }> = [];\n for (const [subsystem, sub] of Object.entries(model.subsystems)) {\n for (const [group, ruleSet] of Object.entries(sub.ruleSets ?? {})) {\n for (const variant of Object.keys(ruleSet)) {\n out.push({ subsystem, group, variant });\n }\n }\n }\n return out;\n}\n\n/**\n * Complete an `AdapterSpec` into a `ThemeAdapter`.\n *\n * Wraps the author's `bind` so the returned `BoundAdapter` gains the defaulted\n * aggregators (`renderAllRecipes` / `renderAllVariables` / `renderAll`) built from\n * the required primitives — unless the spec already provides its own override.\n * `name` / `version` pass through unchanged.\n *\n * @param spec identity (`name`/`version`) + a `bind(model, ctx)` returning the\n * required render primitives (and any optional overrides).\n * @returns a full adapter whose `bind(model, ctx)` yields a complete `BoundAdapter`.\n */\nexport function defineAdapter<TUnit>(spec: AdapterSpec<TUnit>): ThemeAdapter<TUnit> {\n return {\n name: spec.name,\n version: spec.version,\n allowedStates: spec.allowedStates,\n bind(model: ThemeModel, ctx: RenderContext): BoundAdapter<TUnit> {\n const b = spec.bind(model, ctx);\n\n const renderAllRecipes =\n b.renderAllRecipes ??\n ((): TUnit =>\n b.join(\n eachRuleSet(model).map(({ subsystem, group, variant }) =>\n b.renderRecipe(subsystem, group, variant),\n ),\n ));\n\n const renderAllVariables =\n b.renderAllVariables ??\n ((): TUnit => b.join(Object.keys(model.subsystems).map(subsystem => b.renderVariables(subsystem))));\n\n const renderAll =\n b.renderAll ?? ((): TUnit => b.join([renderAllVariables(), renderAllRecipes()]));\n\n // Generic self-documentation: the recipe identities are format-correct via `recipeName`; an\n // adapter overrides `describeUsage` to add format-specific import prose to `summary`.\n const describeUsage =\n b.describeUsage ??\n ((): UsageDescriptor => ({\n format: spec.name,\n summary: [`This theme was built with the \"${spec.name}\" refract adapter.`],\n recipes: eachRuleSet(model).map(({ subsystem, group, variant }) => ({\n subsystem,\n group,\n variant,\n name: b.recipeName(subsystem, group, variant),\n })),\n }));\n\n return { ...b, renderAllRecipes, renderAllVariables, renderAll, describeUsage };\n },\n };\n}\n","/**\n * Contrast audit (opt-in) — scores a built theme's colour pairings for **WCAG 2** contrast ratio\n * (the compliance standard) plus an **advisory APCA** Lc reading. It reports; it never mutates the\n * theme and never \"fixes\" a colour. `audit()` returns structured results by default; a caller (or the\n * `refract audit --strict` CLI) can throw on failures.\n *\n * Which pairings: every palette's `base` ↔ `text`, and every recipe's foreground (`color`) ↔\n * background (`background-color` / `background`) across all subsystems' rule-sets (base + state\n * overrides). A side that isn't a derivable colour (`transparent`, a `var()`, a keyword literal) is\n * reported as `skipped`, not a failure.\n *\n * Colour math is inlined here on purpose: `utils.ts` is vendored to consumers (`build/vendor.ts`) and\n * kept dependency-free / minimal, so we don't widen its export surface for a non-vendored sibling. We\n * reuse only the already-exported {@link parseColor}.\n */\nimport type { Theme, Ref } from \"../../core\";\nimport { RefractError } from \"../../core/errors\";\nimport { parseColor, type RGBTuple } from \"./utils\";\n\n// ── WCAG 2.x ──────────────────────────────────────────────────────────────\n// Relative luminance per WCAG 2: linearize each sRGB channel, weight by the luma coefficients.\nconst srgbToLinear = (c: number): number => (c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4));\nconst relLuminance = ([r, g, b]: RGBTuple): number =>\n 0.2126 * srgbToLinear(r / 255) + 0.7152 * srgbToLinear(g / 255) + 0.0722 * srgbToLinear(b / 255);\n\n/** WCAG 2 contrast ratio (1–21) between two sRGB colours; order-independent. */\nconst wcagRatio = (a: RGBTuple, b: RGBTuple): number => {\n const la = relLuminance(a);\n const lb = relLuminance(b);\n const hi = Math.max(la, lb);\n const lo = Math.min(la, lb);\n return (hi + 0.05) / (lo + 0.05);\n};\n\nexport type WcagLevel = \"AAA\" | \"AA\" | \"AA-large\" | \"fail\";\nconst LEVEL_RANK: Record<WcagLevel, number> = { fail: 0, \"AA-large\": 1, AA: 2, AAA: 3 };\n\n/** Map a ratio to a level. For normal text 3–4.5 is \"AA-large\" (passes only at large sizes). */\nconst wcagLevel = (ratio: number, large: boolean): WcagLevel => {\n if (large) return ratio >= 4.5 ? \"AAA\" : ratio >= 3 ? \"AA\" : \"fail\";\n return ratio >= 7 ? \"AAA\" : ratio >= 4.5 ? \"AA\" : ratio >= 3 ? \"AA-large\" : \"fail\";\n};\n\n// ── APCA (advisory) ───────────────────────────────────────────────────────\n// APCA 0.1.9 / formula 0.98G-4g (SAPC). Advisory only — NOT a WCAG substitute — and the draft may\n// still shift, so the constants are pinned here. Returns a signed Lc (polarity-aware).\nconst APCA = {\n mainTRC: 2.4,\n sRco: 0.2126729, sGco: 0.7151522, sBco: 0.072175,\n normBG: 0.56, normTXT: 0.57, revTXT: 0.62, revBG: 0.65,\n blkThrs: 0.022, blkClmp: 1.414,\n scaleBoW: 1.14, loBoWoffset: 0.027,\n scaleWoB: 1.14, loWoBoffset: 0.027,\n deltaYmin: 0.0005, loClip: 0.1,\n} as const;\n\nconst apcaY = ([r, g, b]: RGBTuple): number =>\n APCA.sRco * Math.pow(r / 255, APCA.mainTRC) +\n APCA.sGco * Math.pow(g / 255, APCA.mainTRC) +\n APCA.sBco * Math.pow(b / 255, APCA.mainTRC);\n\n/** Signed APCA lightness contrast (Lc) of `text` over `bg`. Positive = dark-on-light, negative = light-on-dark. */\nconst apcaLc = (text: RGBTuple, bg: RGBTuple): number => {\n const clamp = (y: number): number => (y > APCA.blkThrs ? y : y + Math.pow(APCA.blkThrs - y, APCA.blkClmp));\n const yTxt = clamp(apcaY(text));\n const yBg = clamp(apcaY(bg));\n if (Math.abs(yBg - yTxt) < APCA.deltaYmin) return 0;\n let out: number;\n if (yBg > yTxt) {\n const sapc = (Math.pow(yBg, APCA.normBG) - Math.pow(yTxt, APCA.normTXT)) * APCA.scaleBoW;\n out = sapc < APCA.loClip ? 0 : sapc - APCA.loBoWoffset;\n } else {\n const sapc = (Math.pow(yBg, APCA.revBG) - Math.pow(yTxt, APCA.revTXT)) * APCA.scaleWoB;\n out = sapc > -APCA.loClip ? 0 : sapc + APCA.loWoBoffset;\n }\n return out * 100;\n};\n\n// ── audit ─────────────────────────────────────────────────────────────────\n\nexport type PairingKind = \"palette\" | \"recipe\";\n\nexport interface PairingScore {\n kind: PairingKind;\n /** Human label, e.g. `colors.brand` or `components.buttons.primary (:hover)`. */\n label: string;\n /** Resolved foreground colour string, or `undefined` when it isn't a derivable colour. */\n fg?: string;\n /** Resolved background colour string, or `undefined` when it isn't a derivable colour. */\n bg?: string;\n /** WCAG 2 contrast ratio (1–21, 2 dp). Absent when skipped. */\n wcagRatio?: number;\n /** WCAG level at the configured text size. Absent when skipped. */\n wcagLevel?: WcagLevel;\n /** Advisory APCA Lc (signed, 1 dp). Absent when skipped. */\n apcaLc?: number;\n /** Whether this pairing met the pass bar (`minWcag`). Absent when skipped. */\n pass?: boolean;\n /** Set when a side isn't a derivable colour — then the score fields are absent. */\n skipped?: string;\n}\n\nexport interface AuditOptions {\n /** Throw an aggregated error when any pairing fails, instead of only reporting. Default `false`. */\n strict?: boolean;\n /** Treat the foreground as large text (relaxed WCAG thresholds). Default `false`. */\n largeText?: boolean;\n /** The pass bar. Default `\"AA\"`. `\"AA-large\"` accepts the 3:1 tier. */\n minWcag?: WcagLevel;\n /** Audit component/recipe fg↔bg pairs. Default `true`. */\n includeRecipes?: boolean;\n /** Audit palette base↔text pairs. Default `true`. */\n includePalettes?: boolean;\n}\n\nexport interface AuditResult {\n pairings: PairingScore[];\n summary: {\n total: number;\n passed: number;\n failed: number;\n skipped: number;\n /** The lowest-ratio scored pairing (the worst offender), if any were scored. */\n worst?: PairingScore;\n };\n /** `true` when no scored pairing failed the pass bar. */\n ok: boolean;\n}\n\nconst round = (n: number, dp: number): number => {\n const f = 10 ** dp;\n return Math.round(n * f) / f;\n};\n\n/** Resolve a rule-set declaration `Ref` to a colour string, or `undefined` if it isn't one. */\nconst refToColor = (theme: Theme, ref: Ref): string | undefined => {\n if (ref.ref !== undefined) {\n try {\n return String(theme.resolveToken(ref.ref));\n } catch {\n return undefined;\n }\n }\n if (typeof ref.value === \"string\") return ref.value;\n return undefined;\n};\n\nconst FG_KEY = \"color\";\nconst BG_KEYS = [\"background-color\", \"background\"] as const;\nconst pickBg = (decls: Record<string, Ref> | undefined): Ref | undefined => {\n if (!decls) return undefined;\n for (const k of BG_KEYS) if (decls[k]) return decls[k];\n return undefined;\n};\n\n/** Score one fg/bg pairing (colours already resolved to strings), or a skipped record. */\nconst scorePair = (\n kind: PairingKind,\n label: string,\n fg: string | undefined,\n bg: string | undefined,\n options: Required<Pick<AuditOptions, \"largeText\" | \"minWcag\">>,\n): PairingScore => {\n let fgRgb: RGBTuple | undefined;\n let bgRgb: RGBTuple | undefined;\n try {\n if (fg !== undefined) fgRgb = parseColor(fg).rgb;\n } catch { /* not a derivable colour */ }\n try {\n if (bg !== undefined) bgRgb = parseColor(bg).rgb;\n } catch { /* not a derivable colour */ }\n\n if (!fgRgb || !bgRgb) {\n return { kind, label, fg, bg, skipped: !fgRgb && !bgRgb ? \"no derivable fg/bg\" : !fgRgb ? \"fg not a colour\" : \"bg not a colour\" };\n }\n\n const ratio = wcagRatio(fgRgb, bgRgb);\n const level = wcagLevel(ratio, options.largeText);\n const pass = LEVEL_RANK[level] >= LEVEL_RANK[options.minWcag];\n return {\n kind, label, fg, bg,\n wcagRatio: round(ratio, 2),\n wcagLevel: level,\n apcaLc: round(apcaLc(fgRgb, bgRgb), 1),\n pass,\n };\n};\n\n/**\n * Audit a built theme's colour pairings. Pure — reads `theme.tokens` / `theme.resolveToken` /\n * `theme.model` only. In `strict` mode, throws one aggregated error listing every failing pairing.\n */\nexport const audit = (theme: Theme, options: AuditOptions = {}): AuditResult => {\n const opts = {\n largeText: options.largeText ?? false,\n minWcag: options.minWcag ?? (\"AA\" as WcagLevel),\n };\n const includeRecipes = options.includeRecipes ?? true;\n const includePalettes = options.includePalettes ?? true;\n const pairings: PairingScore[] = [];\n\n // Palettes: base ↔ text. A palette advertises a pairing by having a `colors.<name>.text` token.\n if (includePalettes) {\n for (const path of Object.keys(theme.tokens)) {\n const m = /^colors\\.([^.]+)\\.text$/.exec(path);\n if (!m) continue;\n const base = `colors.${m[1]}`;\n let fg: string | undefined, bg: string | undefined;\n try { fg = String(theme.resolveToken(path)); } catch { /* skip */ }\n try { bg = String(theme.resolveToken(base)); } catch { /* skip */ }\n pairings.push(scorePair(\"palette\", base, fg, bg, opts));\n }\n }\n\n // Recipes: every subsystem's rule-sets — the base declarations + each state/breakpoint override.\n if (includeRecipes) {\n for (const [subsystem, subModel] of Object.entries(theme.model.subsystems)) {\n if (!subModel.ruleSets) continue;\n for (const [group, ruleSetGroup] of Object.entries(subModel.ruleSets)) {\n for (const [variant, ruleSet] of Object.entries(ruleSetGroup)) {\n const baseFg = ruleSet.declarations[FG_KEY];\n const baseBg = pickBg(ruleSet.declarations);\n const label = `${subsystem}.${group}.${variant}`;\n if (baseFg && baseBg) {\n pairings.push(scorePair(\"recipe\", label, refToColor(theme, baseFg), refToColor(theme, baseBg), opts));\n }\n // Overrides (e.g. :hover) can swap bg or fg — score the effective pairing at that condition.\n for (const override of ruleSet.overrides ?? []) {\n const oFg = override.declarations?.[FG_KEY] ?? baseFg;\n const oBg = pickBg(override.declarations) ?? baseBg;\n if (!override.declarations || (!override.declarations[FG_KEY] && !pickBg(override.declarations))) continue;\n if (!oFg || !oBg) continue;\n const cond = override.state ?? override.breakpoint ?? override.query ?? \"override\";\n pairings.push(scorePair(\"recipe\", `${label} (${cond})`, refToColor(theme, oFg), refToColor(theme, oBg), opts));\n }\n }\n }\n }\n }\n\n const scored = pairings.filter(p => !p.skipped);\n const failed = scored.filter(p => p.pass === false);\n const worst = scored.reduce<PairingScore | undefined>(\n (w, p) => (w === undefined || (p.wcagRatio ?? Infinity) < (w.wcagRatio ?? Infinity) ? p : w),\n undefined,\n );\n const result: AuditResult = {\n pairings,\n summary: {\n total: scored.length,\n passed: scored.length - failed.length,\n failed: failed.length,\n skipped: pairings.length - scored.length,\n worst,\n },\n ok: failed.length === 0,\n };\n\n if (options.strict && failed.length > 0) {\n const list = failed.map(p => `${p.label} (${p.wcagRatio}:1, ${p.wcagLevel})`).join(\", \");\n throw new RefractError(\n \"REFRACT_E_AUDIT\",\n `refract audit: ${failed.length} pairing(s) fail WCAG ${opts.minWcag} — ${list}. ` +\n `Adjust the colour(s), lower --min-wcag, or drop --strict to report without failing.`,\n failed.map(p => `${p.label} (${p.wcagRatio}:1, ${p.wcagLevel})`),\n );\n }\n\n return result;\n};\n","/**\n * `createNoopAdapter` — the trivial, built-in null adapter (monorepo split, friction 2).\n *\n * `createTheme` requires an `adapter`, but some consumers of the built `Theme` never touch\n * adapter-produced strings — they read only the format-neutral `theme.tokens` / `theme.resolveToken`\n * / `theme.model` (the DTCG export is the canonical example: `toDTCG` walks the flat token map and the\n * breakpoints, never a rendered rule). Those callers need *a* valid adapter purely to satisfy the\n * contract; the output is discarded.\n *\n * Before the split the CLI's `tokens` command reached for `createCssAdapter` as that throwaway builder\n * — which forced a core→adapter dependency (`src/build` importing `src/adapters/css`). The monorepo\n * guiding rule is that the dependency arrow points ONLY into core, so core now ships its own null\n * object: `createNoopAdapter()` emits nothing (empty strings, an empty `emit()`), lets `createTheme`\n * build the Model + token map exactly as any adapter would, and keeps `src/build` free of every\n * adapter package.\n *\n * It's a `ThemeAdapter` like any other (built through {@link defineAdapter}, so it gets the defaulted\n * aggregators for free), just with render primitives that produce empty output.\n */\n\nimport { defineAdapter } from \"./defineAdapter\";\nimport type { ThemeAdapter } from \"./ThemeAdapter\";\n\n/**\n * A no-op adapter: every render primitive returns an empty string and `emit()` writes no files. Use it\n * whenever a `Theme` is needed only for its format-neutral data (`tokens` / `resolveToken` / `model`)\n * and the rendered output is irrelevant — e.g. the `refract tokens` DTCG export.\n */\nexport function createNoopAdapter(): ThemeAdapter<string> {\n return defineAdapter<string>({\n name: \"noop\",\n version: 1,\n bind: () => ({\n recipeName: () => \"\",\n renderRecipe: () => \"\",\n renderVariables: () => \"\",\n join: parts => parts.join(\"\"),\n emit: () => ({ files: {} }),\n }),\n });\n}\n","/**\n * `ref(path)` — author a token **reference** inside a `css` delta or a globals element rule.\n *\n * Inside a `css` block (and globals element declarations) a bare string is a **literal** CSS value —\n * `display: \"flex\"` emits `flex`. To emit a token reference instead, wrap the token path in `ref()`:\n * `color: ref(\"colors.brand.text\")` → `var(--…)`. The JSON-safe equivalent is the plain object form\n * `{ ref: \"colors.brand.text\" }`; both produce the same Model reference, so a `theme.raw.json` needs no\n * function. (Top-level recipe composition fields — `colors: \"solid.brand\"` — are unaffected: a bare\n * string there is always a reference.)\n */\nexport const ref = (path: string): { ref: string } => ({ ref: path });\n"],"names":["parseRuleSetReference","reference","subsystem","rest","split","dot","indexOf","group","slice","variant","resolveReference","model","parsed","_c","_a","subsystems","ruleSets","_b","mergeDeclarations","target","source","prop","ref","Object","entries","responsiveKey","o","_d","_e","_f","breakpoint","query","orientation","state","container","size","eachRuleSet","out","sub","ruleSet","keys","push","defineAdapter","spec","name","version","allowedStates","bind","ctx","b","renderAllRecipes","join","map","renderRecipe","renderAllVariables","renderVariables","renderAll","describeUsage","format","summary","recipes","recipeName","srgbToLinear","c","Math","pow","relLuminance","r","g","LEVEL_RANK","fail","AA","AAA","APCA","apcaY","apcaLc","text","bg","clamp","y","yTxt","yBg","abs","sapc","round","n","dp","f","refToColor","theme","undefined","String","resolveToken","value","FG_KEY","BG_KEYS","pickBg","decls","k","scorePair","kind","label","fg","options","fgRgb","bgRgb","parseColor","rgb","skipped","ratio","a","la","lb","max","min","wcagRatio","level","large","wcagLevel","largeText","pass","minWcag","opts","includeRecipes","pairings","includePalettes","path","tokens","m","exec","base","subModel","ruleSetGroup","baseFg","declarations","baseBg","override","overrides","oFg","_g","oBg","_h","cond","_l","_j","_k","scored","filter","p","failed","worst","reduce","w","Infinity","result","total","length","passed","ok","strict","list","RefractError","parts","emit","files","own","components","sources","references","resolved","states","responsiveByKey","Map","key","entry","get","set","responsive","values","seen","Set","referencedPaths","collect","has","add"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/core/model/mergeRuleSet.ts","../src/core/defineAdapter.ts","../src/subsystems/colors/audit.ts","../src/core/assertRawTheme.ts","../src/core/noopAdapter.ts","../src/core/ref.ts"],"sourcesContent":["/**\n * Format-neutral component merge (§9c).\n *\n * `mergeComponentRuleSet` flattens one component variant into a single\n * self-contained rule-set: its referenced recipes' declarations + its own `css`\n * delta, unioned. The result is pure Model data — declarations stay as {@link Ref}s\n * carrying `{ ref, value }` — so an adapter renders it as baked values (inline) or\n * `var(--…)` / `theme.…` (referenced) without any format decision leaking in here.\n *\n * This is the ONLY new machinery the `components` emit mode needs, shared by the CSS\n * and future SC adapters. It is **on-demand** (an adapter calls it in `emit()`), never\n * materialized on `ThemeModel` / the runtime `theme`. It does NOT mutate the authored\n * `RuleSet` / declarations — the merged view is freshly derived (Refs shallow-cloned).\n *\n * Precedence (LOCKED, §9): authored **reference order** first (later refs override\n * earlier per property key), then the component's own declarations **last / highest**\n * (`css` delta wins over subsystem recipes). Same rule per condition bucket.\n */\nimport type {\n Orientation,\n Ref,\n ResponsiveQueryKind,\n RuleSet,\n RuleSetOverride,\n ThemeModel,\n} from \"./model\";\nimport { RefractError } from \"../errors\";\n\n/**\n * One flattened conditioned bucket — a distinct `(breakpoint, query, orientation, state, container, size)`\n * key. A **viewport** entry carries `breakpoint`; a **container** entry (§10.5) carries `container` + `size`\n * (and no `breakpoint`). The adapter emits the former as `@media`, the latter as `@container`.\n */\nexport type MergedResponsiveEntry = {\n breakpoint?: string;\n query?: ResponsiveQueryKind;\n orientation?: Orientation;\n state?: string;\n container?: string;\n size?: string;\n declarations: Record<string, Ref>;\n};\n\n/**\n * A component variant flattened into one self-contained rule-set.\n *\n * - `base` — merged no-condition declarations.\n * - `states` — merged declarations keyed by `state` (no breakpoint).\n * - `responsive` — one entry per distinct `(breakpoint, query, orientation, state)` merge key.\n * - `referencedPaths` — every distinct token path (`Ref.ref`) appearing across all buckets,\n * first-appearance order. What non-inline rendering tree-shakes the vars file to.\n */\nexport type MergedRuleSet = {\n base: Record<string, Ref>;\n states: Record<string, Record<string, Ref>>;\n responsive: MergedResponsiveEntry[];\n referencedPaths: string[];\n};\n\n/** The address parts of a component reference (`\"colors:solid.primary\"`). */\nexport type RuleSetReference = { subsystem: string; group: string; variant: string };\n\n/**\n * Parse a component reference (`\"subsystem:group.variant\"`) into its address parts.\n * Format-neutral core twin of the CSS adapter's `parseComponentReference` (which stays\n * for the option-C class-list path). Returns `undefined` on a malformed reference.\n */\nexport const parseRuleSetReference = (reference: string): RuleSetReference | undefined => {\n const [subsystem, rest] = reference.split(\":\");\n if (!subsystem || !rest) return undefined;\n const dot = rest.indexOf(\".\");\n if (dot < 0) return undefined;\n return { subsystem, group: rest.slice(0, dot), variant: rest.slice(dot + 1) };\n};\n\n/** Resolve a reference to its authored `RuleSet`, or `undefined` if it doesn't address one. */\nconst resolveReference = (model: ThemeModel, reference: string): RuleSet | undefined => {\n const parsed = parseRuleSetReference(reference);\n if (!parsed) return undefined;\n return model.subsystems[parsed.subsystem]?.ruleSets?.[parsed.group]?.[parsed.variant];\n};\n\n/** Fold `source` declarations into `target` (later source wins), shallow-cloning each Ref. */\nconst mergeDeclarations = (target: Record<string, Ref>, source: Record<string, Ref>): void => {\n for (const [prop, ref] of Object.entries(source)) target[prop] = { ...ref };\n};\n\n/** Stable string key for a conditioned bucket — `(breakpoint, query, orientation, state, container, size)`. */\nconst responsiveKey = (o: RuleSetOverride): string =>\n `${o.breakpoint ?? \"\"}|${o.query ?? \"\"}|${o.orientation ?? \"\"}|${o.state ?? \"\"}|${o.container ?? \"\"}|${o.size ?? \"\"}`;\n\n/**\n * Flatten one component variant into a self-contained {@link MergedRuleSet}.\n *\n * Reads `model.subsystems.components.ruleSets[group][variant]` — its `references`\n * (resolved in authored order), own base `declarations`, and `overrides` — and unions\n * them under the locked precedence. Throws on a missing component or an unresolved reference.\n */\nexport const mergeComponentRuleSet = (\n model: ThemeModel,\n group: string,\n variant: string,\n): MergedRuleSet => {\n const own = model.subsystems.components?.ruleSets?.[group]?.[variant];\n if (!own) {\n throw new RefractError(\"REFRACT_E_REFERENCE\", `mergeComponentRuleSet: no component rule-set \"${group}.${variant}\"`);\n }\n\n // Sources in precedence order: referenced rule-sets left-to-right, then the component's own last.\n const sources: RuleSet[] = [];\n for (const reference of own.references ?? []) {\n const resolved = resolveReference(model, reference);\n if (!resolved) {\n throw new RefractError(\"REFRACT_E_REFERENCE\", `mergeComponentRuleSet: unresolved reference \"${reference}\"`);\n }\n sources.push(resolved);\n }\n sources.push(own);\n\n const base: Record<string, Ref> = {};\n const states: Record<string, Record<string, Ref>> = {};\n const responsiveByKey = new Map<string, MergedResponsiveEntry>();\n\n for (const source of sources) {\n mergeDeclarations(base, source.declarations);\n\n for (const override of source.overrides) {\n if (!override.declarations) continue;\n // A breakpoint OR container condition → a conditioned bucket (viewport → @media, container →\n // @container). Container overrides MUST route here, not fold into base (§10.5 correctness).\n if (override.breakpoint !== undefined || override.container !== undefined) {\n const key = responsiveKey(override);\n let entry = responsiveByKey.get(key);\n if (!entry) {\n entry = {\n ...(override.breakpoint !== undefined ? { breakpoint: override.breakpoint } : {}),\n ...(override.query !== undefined ? { query: override.query } : {}),\n ...(override.orientation !== undefined ? { orientation: override.orientation } : {}),\n ...(override.state !== undefined ? { state: override.state } : {}),\n ...(override.container !== undefined ? { container: override.container } : {}),\n ...(override.size !== undefined ? { size: override.size } : {}),\n declarations: {},\n };\n responsiveByKey.set(key, entry);\n }\n mergeDeclarations(entry.declarations, override.declarations);\n } else if (override.state !== undefined) {\n (states[override.state] ??= {});\n mergeDeclarations(states[override.state], override.declarations);\n } else {\n // Unconditional override (only variant/target, no breakpoint/state) — folds into base.\n mergeDeclarations(base, override.declarations);\n }\n }\n }\n\n const responsive = [...responsiveByKey.values()];\n\n // referencedPaths — every distinct token path across all buckets, first-appearance order.\n const seen = new Set<string>();\n const referencedPaths: string[] = [];\n const collect = (decls: Record<string, Ref>): void => {\n for (const ref of Object.values(decls)) {\n if (ref.ref !== undefined && !seen.has(ref.ref)) {\n seen.add(ref.ref);\n referencedPaths.push(ref.ref);\n }\n }\n };\n collect(base);\n for (const decls of Object.values(states)) collect(decls);\n for (const entry of responsive) collect(entry.declarations);\n\n return { base, states, responsive, referencedPaths };\n};\n","/**\n * `defineAdapter` — turns an `AdapterSpec` (identity + a `bind` returning the four\n * required primitives) into a full `ThemeAdapter` whose `bind` yields a complete\n * `BoundAdapter` with the DEFAULTED aggregators supplied.\n *\n * The defaults are pure Model walks: the Model enumerates every subsystem and every\n * (group, variant), so core loops it, calls the author's per-unit renderers, and\n * `join`s the results. Model/ctx are already bound, so the aggregators take no args.\n * An author can still override any aggregator (a format whose full document isn't a\n * flat concatenation).\n */\n\nimport type { ThemeModel } from \"./model\";\nimport type {\n AdapterSpec,\n ThemeAdapter,\n BoundAdapter,\n RenderContext,\n UsageDescriptor,\n} from \"./ThemeAdapter\";\n\n/** Every rule-set address in the Model — `(subsystem, group, variant)` triples. */\nfunction eachRuleSet(model: ThemeModel): Array<{ subsystem: string; group: string; variant: string }> {\n const out: Array<{ subsystem: string; group: string; variant: string }> = [];\n for (const [subsystem, sub] of Object.entries(model.subsystems)) {\n for (const [group, ruleSet] of Object.entries(sub.ruleSets ?? {})) {\n for (const variant of Object.keys(ruleSet)) {\n out.push({ subsystem, group, variant });\n }\n }\n }\n return out;\n}\n\n/**\n * Complete an `AdapterSpec` into a `ThemeAdapter`.\n *\n * Wraps the author's `bind` so the returned `BoundAdapter` gains the defaulted\n * aggregators (`renderAllRecipes` / `renderAllVariables` / `renderAll`) built from\n * the required primitives — unless the spec already provides its own override.\n * `name` / `version` pass through unchanged.\n *\n * @param spec identity (`name`/`version`) + a `bind(model, ctx)` returning the\n * required render primitives (and any optional overrides).\n * @returns a full adapter whose `bind(model, ctx)` yields a complete `BoundAdapter`.\n */\nexport function defineAdapter<TUnit>(spec: AdapterSpec<TUnit>): ThemeAdapter<TUnit> {\n return {\n name: spec.name,\n version: spec.version,\n allowedStates: spec.allowedStates,\n bind(model: ThemeModel, ctx: RenderContext): BoundAdapter<TUnit> {\n const b = spec.bind(model, ctx);\n\n const renderAllRecipes =\n b.renderAllRecipes ??\n ((): TUnit =>\n b.join(\n eachRuleSet(model).map(({ subsystem, group, variant }) =>\n b.renderRecipe(subsystem, group, variant),\n ),\n ));\n\n const renderAllVariables =\n b.renderAllVariables ??\n ((): TUnit => b.join(Object.keys(model.subsystems).map(subsystem => b.renderVariables(subsystem))));\n\n const renderAll =\n b.renderAll ?? ((): TUnit => b.join([renderAllVariables(), renderAllRecipes()]));\n\n // Generic self-documentation: the recipe identities are format-correct via `recipeName`; an\n // adapter overrides `describeUsage` to add format-specific import prose to `summary`.\n const describeUsage =\n b.describeUsage ??\n ((): UsageDescriptor => ({\n format: spec.name,\n summary: [`This theme was built with the \"${spec.name}\" refract adapter.`],\n recipes: eachRuleSet(model).map(({ subsystem, group, variant }) => ({\n subsystem,\n group,\n variant,\n name: b.recipeName(subsystem, group, variant),\n })),\n }));\n\n return { ...b, renderAllRecipes, renderAllVariables, renderAll, describeUsage };\n },\n };\n}\n","/**\n * Contrast audit (opt-in) — scores a built theme's colour pairings for **WCAG 2** contrast ratio\n * (the compliance standard) plus an **advisory APCA** Lc reading. It reports; it never mutates the\n * theme and never \"fixes\" a colour. `audit()` returns structured results by default; a caller (or the\n * `refract audit --strict` CLI) can throw on failures.\n *\n * Which pairings: every palette's `base` ↔ `text`, and every recipe's foreground (`color`) ↔\n * background (`background-color` / `background`) across all subsystems' rule-sets (base + state\n * overrides). A side that isn't a derivable colour (`transparent`, a `var()`, a keyword literal) is\n * reported as `skipped`, not a failure.\n *\n * Colour math is inlined here on purpose: `utils.ts` is vendored to consumers (`build/vendor.ts`) and\n * kept dependency-free / minimal, so we don't widen its export surface for a non-vendored sibling. We\n * reuse only the already-exported {@link parseColor}.\n */\nimport type { Theme, Ref } from \"../../core\";\nimport { RefractError } from \"../../core/errors\";\nimport { parseColor, type RGBTuple } from \"./utils\";\n\n// ── WCAG 2.x ──────────────────────────────────────────────────────────────\n// Relative luminance per WCAG 2: linearize each sRGB channel, weight by the luma coefficients.\nconst srgbToLinear = (c: number): number => (c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4));\nconst relLuminance = ([r, g, b]: RGBTuple): number =>\n 0.2126 * srgbToLinear(r / 255) + 0.7152 * srgbToLinear(g / 255) + 0.0722 * srgbToLinear(b / 255);\n\n/** WCAG 2 contrast ratio (1–21) between two sRGB colours; order-independent. */\nconst wcagRatio = (a: RGBTuple, b: RGBTuple): number => {\n const la = relLuminance(a);\n const lb = relLuminance(b);\n const hi = Math.max(la, lb);\n const lo = Math.min(la, lb);\n return (hi + 0.05) / (lo + 0.05);\n};\n\nexport type WcagLevel = \"AAA\" | \"AA\" | \"AA-large\" | \"fail\";\nconst LEVEL_RANK: Record<WcagLevel, number> = { fail: 0, \"AA-large\": 1, AA: 2, AAA: 3 };\n\n/** Map a ratio to a level. For normal text 3–4.5 is \"AA-large\" (passes only at large sizes). */\nconst wcagLevel = (ratio: number, large: boolean): WcagLevel => {\n if (large) return ratio >= 4.5 ? \"AAA\" : ratio >= 3 ? \"AA\" : \"fail\";\n return ratio >= 7 ? \"AAA\" : ratio >= 4.5 ? \"AA\" : ratio >= 3 ? \"AA-large\" : \"fail\";\n};\n\n// ── APCA (advisory) ───────────────────────────────────────────────────────\n// APCA 0.1.9 / formula 0.98G-4g (SAPC). Advisory only — NOT a WCAG substitute — and the draft may\n// still shift, so the constants are pinned here. Returns a signed Lc (polarity-aware).\nconst APCA = {\n mainTRC: 2.4,\n sRco: 0.2126729, sGco: 0.7151522, sBco: 0.072175,\n normBG: 0.56, normTXT: 0.57, revTXT: 0.62, revBG: 0.65,\n blkThrs: 0.022, blkClmp: 1.414,\n scaleBoW: 1.14, loBoWoffset: 0.027,\n scaleWoB: 1.14, loWoBoffset: 0.027,\n deltaYmin: 0.0005, loClip: 0.1,\n} as const;\n\nconst apcaY = ([r, g, b]: RGBTuple): number =>\n APCA.sRco * Math.pow(r / 255, APCA.mainTRC) +\n APCA.sGco * Math.pow(g / 255, APCA.mainTRC) +\n APCA.sBco * Math.pow(b / 255, APCA.mainTRC);\n\n/** Signed APCA lightness contrast (Lc) of `text` over `bg`. Positive = dark-on-light, negative = light-on-dark. */\nconst apcaLc = (text: RGBTuple, bg: RGBTuple): number => {\n const clamp = (y: number): number => (y > APCA.blkThrs ? y : y + Math.pow(APCA.blkThrs - y, APCA.blkClmp));\n const yTxt = clamp(apcaY(text));\n const yBg = clamp(apcaY(bg));\n if (Math.abs(yBg - yTxt) < APCA.deltaYmin) return 0;\n let out: number;\n if (yBg > yTxt) {\n const sapc = (Math.pow(yBg, APCA.normBG) - Math.pow(yTxt, APCA.normTXT)) * APCA.scaleBoW;\n out = sapc < APCA.loClip ? 0 : sapc - APCA.loBoWoffset;\n } else {\n const sapc = (Math.pow(yBg, APCA.revBG) - Math.pow(yTxt, APCA.revTXT)) * APCA.scaleWoB;\n out = sapc > -APCA.loClip ? 0 : sapc + APCA.loWoBoffset;\n }\n return out * 100;\n};\n\n// ── audit ─────────────────────────────────────────────────────────────────\n\nexport type PairingKind = \"palette\" | \"recipe\";\n\nexport interface PairingScore {\n kind: PairingKind;\n /** Human label, e.g. `colors.brand` or `components.buttons.primary (:hover)`. */\n label: string;\n /** Resolved foreground colour string, or `undefined` when it isn't a derivable colour. */\n fg?: string;\n /** Resolved background colour string, or `undefined` when it isn't a derivable colour. */\n bg?: string;\n /** WCAG 2 contrast ratio (1–21, 2 dp). Absent when skipped. */\n wcagRatio?: number;\n /** WCAG level at the configured text size. Absent when skipped. */\n wcagLevel?: WcagLevel;\n /** Advisory APCA Lc (signed, 1 dp). Absent when skipped. */\n apcaLc?: number;\n /** Whether this pairing met the pass bar (`minWcag`). Absent when skipped. */\n pass?: boolean;\n /** Set when a side isn't a derivable colour — then the score fields are absent. */\n skipped?: string;\n}\n\nexport interface AuditOptions {\n /** Throw an aggregated error when any pairing fails, instead of only reporting. Default `false`. */\n strict?: boolean;\n /** Treat the foreground as large text (relaxed WCAG thresholds). Default `false`. */\n largeText?: boolean;\n /** The pass bar. Default `\"AA\"`. `\"AA-large\"` accepts the 3:1 tier. */\n minWcag?: WcagLevel;\n /** Audit component/recipe fg↔bg pairs. Default `true`. */\n includeRecipes?: boolean;\n /** Audit palette base↔text pairs. Default `true`. */\n includePalettes?: boolean;\n}\n\nexport interface AuditResult {\n pairings: PairingScore[];\n summary: {\n total: number;\n passed: number;\n failed: number;\n skipped: number;\n /** The lowest-ratio scored pairing (the worst offender), if any were scored. */\n worst?: PairingScore;\n };\n /** `true` when no scored pairing failed the pass bar. */\n ok: boolean;\n}\n\nconst round = (n: number, dp: number): number => {\n const f = 10 ** dp;\n return Math.round(n * f) / f;\n};\n\n/** Resolve a rule-set declaration `Ref` to a colour string, or `undefined` if it isn't one. */\nconst refToColor = (theme: Theme, ref: Ref): string | undefined => {\n if (ref.ref !== undefined) {\n try {\n return String(theme.resolveToken(ref.ref));\n } catch {\n return undefined;\n }\n }\n if (typeof ref.value === \"string\") return ref.value;\n return undefined;\n};\n\nconst FG_KEY = \"color\";\nconst BG_KEYS = [\"background-color\", \"background\"] as const;\nconst pickBg = (decls: Record<string, Ref> | undefined): Ref | undefined => {\n if (!decls) return undefined;\n for (const k of BG_KEYS) if (decls[k]) return decls[k];\n return undefined;\n};\n\n/** Score one fg/bg pairing (colours already resolved to strings), or a skipped record. */\nconst scorePair = (\n kind: PairingKind,\n label: string,\n fg: string | undefined,\n bg: string | undefined,\n options: Required<Pick<AuditOptions, \"largeText\" | \"minWcag\">>,\n): PairingScore => {\n let fgRgb: RGBTuple | undefined;\n let bgRgb: RGBTuple | undefined;\n try {\n if (fg !== undefined) fgRgb = parseColor(fg).rgb;\n } catch { /* not a derivable colour */ }\n try {\n if (bg !== undefined) bgRgb = parseColor(bg).rgb;\n } catch { /* not a derivable colour */ }\n\n if (!fgRgb || !bgRgb) {\n return { kind, label, fg, bg, skipped: !fgRgb && !bgRgb ? \"no derivable fg/bg\" : !fgRgb ? \"fg not a colour\" : \"bg not a colour\" };\n }\n\n const ratio = wcagRatio(fgRgb, bgRgb);\n const level = wcagLevel(ratio, options.largeText);\n const pass = LEVEL_RANK[level] >= LEVEL_RANK[options.minWcag];\n return {\n kind, label, fg, bg,\n wcagRatio: round(ratio, 2),\n wcagLevel: level,\n apcaLc: round(apcaLc(fgRgb, bgRgb), 1),\n pass,\n };\n};\n\n/**\n * Audit a built theme's colour pairings. Pure — reads `theme.tokens` / `theme.resolveToken` /\n * `theme.model` only. In `strict` mode, throws one aggregated error listing every failing pairing.\n */\nexport const audit = (theme: Theme, options: AuditOptions = {}): AuditResult => {\n const opts = {\n largeText: options.largeText ?? false,\n minWcag: options.minWcag ?? (\"AA\" as WcagLevel),\n };\n const includeRecipes = options.includeRecipes ?? true;\n const includePalettes = options.includePalettes ?? true;\n const pairings: PairingScore[] = [];\n\n // Palettes: base ↔ text. A palette advertises a pairing by having a `colors.<name>.text` token.\n if (includePalettes) {\n for (const path of Object.keys(theme.tokens)) {\n const m = /^colors\\.([^.]+)\\.text$/.exec(path);\n if (!m) continue;\n const base = `colors.${m[1]}`;\n let fg: string | undefined, bg: string | undefined;\n try { fg = String(theme.resolveToken(path)); } catch { /* skip */ }\n try { bg = String(theme.resolveToken(base)); } catch { /* skip */ }\n pairings.push(scorePair(\"palette\", base, fg, bg, opts));\n }\n }\n\n // Recipes: every subsystem's rule-sets — the base declarations + each state/breakpoint override.\n if (includeRecipes) {\n for (const [subsystem, subModel] of Object.entries(theme.model.subsystems)) {\n if (!subModel.ruleSets) continue;\n for (const [group, ruleSetGroup] of Object.entries(subModel.ruleSets)) {\n for (const [variant, ruleSet] of Object.entries(ruleSetGroup)) {\n const baseFg = ruleSet.declarations[FG_KEY];\n const baseBg = pickBg(ruleSet.declarations);\n const label = `${subsystem}.${group}.${variant}`;\n if (baseFg && baseBg) {\n pairings.push(scorePair(\"recipe\", label, refToColor(theme, baseFg), refToColor(theme, baseBg), opts));\n }\n // Overrides (e.g. :hover) can swap bg or fg — score the effective pairing at that condition.\n for (const override of ruleSet.overrides ?? []) {\n const oFg = override.declarations?.[FG_KEY] ?? baseFg;\n const oBg = pickBg(override.declarations) ?? baseBg;\n if (!override.declarations || (!override.declarations[FG_KEY] && !pickBg(override.declarations))) continue;\n if (!oFg || !oBg) continue;\n const cond = override.state ?? override.breakpoint ?? override.query ?? \"override\";\n pairings.push(scorePair(\"recipe\", `${label} (${cond})`, refToColor(theme, oFg), refToColor(theme, oBg), opts));\n }\n }\n }\n }\n }\n\n const scored = pairings.filter(p => !p.skipped);\n const failed = scored.filter(p => p.pass === false);\n const worst = scored.reduce<PairingScore | undefined>(\n (w, p) => (w === undefined || (p.wcagRatio ?? Infinity) < (w.wcagRatio ?? Infinity) ? p : w),\n undefined,\n );\n const result: AuditResult = {\n pairings,\n summary: {\n total: scored.length,\n passed: scored.length - failed.length,\n failed: failed.length,\n skipped: pairings.length - scored.length,\n worst,\n },\n ok: failed.length === 0,\n };\n\n if (options.strict && failed.length > 0) {\n const list = failed.map(p => `${p.label} (${p.wcagRatio}:1, ${p.wcagLevel})`).join(\", \");\n throw new RefractError(\n \"REFRACT_E_AUDIT\",\n `refract audit: ${failed.length} pairing(s) fail WCAG ${opts.minWcag} — ${list}. ` +\n `Adjust the colour(s), lower --min-wcag, or drop --strict to report without failing.`,\n failed.map(p => `${p.label} (${p.wcagRatio}:1, ${p.wcagLevel})`),\n );\n }\n\n return result;\n};\n","/**\n * Fail-loud shape guard for a value that is *supposed* to be a {@link RawTheme}.\n *\n * `createTheme` accepts a bare object, and an empty `{}` is a valid (empty) theme — so a value of the\n * *wrong* shape doesn't necessarily throw during a build. That's the trap `refract diff` fell into: hand\n * it a `defineConfig({ raw, targets })` where it wanted the raw theme and it built the config as an\n * (effectively empty) theme, then reported a nonsense \"every token removed\" diff and exited 0. A\n * governance tool must not quietly mis-report. This guard is the loud, coded gate for that class of\n * mistake — used by `diff` (and available to `validate` / the MCP server) before anything is compared.\n *\n * It is deliberately narrow: it rejects only values that cannot be a RawTheme (non-objects, arrays,\n * `null`) or that are affirmatively something else (a `defineConfig`, spotted by its `targets` array).\n * A bare `{}` still passes — an empty theme is legitimately empty.\n */\nimport { RefractError } from \"./errors\";\nimport type { RawTheme } from \"./rawTheme\";\n\nexport function assertRawTheme(value: unknown, source?: string): asserts value is RawTheme {\n const at = source ? ` (${source})` : \"\";\n\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n const got = Array.isArray(value) ? \"an array\" : value === null ? \"null\" : typeof value;\n throw new RefractError(\n \"REFRACT_E_RAW_SHAPE\",\n `Expected a RawTheme object${at}, got ${got}. Pass the raw theme (a module's default export, or a .json raw theme).`,\n );\n }\n\n // The documented mistake: a defineConfig({ raw, targets }) passed where the bare RawTheme was wanted.\n // A RawTheme never has a top-level `targets`; a config always does.\n if (Array.isArray((value as { targets?: unknown }).targets)) {\n throw new RefractError(\n \"REFRACT_E_RAW_SHAPE\",\n `Expected a RawTheme object${at}, but got what looks like a defineConfig({ raw, targets }). Pass its \\`raw\\` (or a module that default-exports the raw theme), not the whole config.`,\n );\n }\n}\n","/**\n * `createNoopAdapter` — the trivial, built-in null adapter (monorepo split, friction 2).\n *\n * `createTheme` requires an `adapter`, but some consumers of the built `Theme` never touch\n * adapter-produced strings — they read only the format-neutral `theme.tokens` / `theme.resolveToken`\n * / `theme.model` (the DTCG export is the canonical example: `toDTCG` walks the flat token map and the\n * breakpoints, never a rendered rule). Those callers need *a* valid adapter purely to satisfy the\n * contract; the output is discarded.\n *\n * Before the split the CLI's `tokens` command reached for `createCssAdapter` as that throwaway builder\n * — which forced a core→adapter dependency (`src/build` importing `src/adapters/css`). The monorepo\n * guiding rule is that the dependency arrow points ONLY into core, so core now ships its own null\n * object: `createNoopAdapter()` emits nothing (empty strings, an empty `emit()`), lets `createTheme`\n * build the Model + token map exactly as any adapter would, and keeps `src/build` free of every\n * adapter package.\n *\n * It's a `ThemeAdapter` like any other (built through {@link defineAdapter}, so it gets the defaulted\n * aggregators for free), just with render primitives that produce empty output.\n */\n\nimport { defineAdapter } from \"./defineAdapter\";\nimport type { ThemeAdapter } from \"./ThemeAdapter\";\n\n/**\n * A no-op adapter: every render primitive returns an empty string and `emit()` writes no files. Use it\n * whenever a `Theme` is needed only for its format-neutral data (`tokens` / `resolveToken` / `model`)\n * and the rendered output is irrelevant — e.g. the `refract tokens` DTCG export.\n */\nexport function createNoopAdapter(): ThemeAdapter<string> {\n return defineAdapter<string>({\n name: \"noop\",\n version: 1,\n bind: () => ({\n recipeName: () => \"\",\n renderRecipe: () => \"\",\n renderVariables: () => \"\",\n join: parts => parts.join(\"\"),\n emit: () => ({ files: {} }),\n }),\n });\n}\n","/**\n * `ref(path)` — author a token **reference** inside a `css` delta or a globals element rule.\n *\n * Inside a `css` block (and globals element declarations) a bare string is a **literal** CSS value —\n * `display: \"flex\"` emits `flex`. To emit a token reference instead, wrap the token path in `ref()`:\n * `color: ref(\"colors.brand.text\")` → `var(--…)`. The JSON-safe equivalent is the plain object form\n * `{ ref: \"colors.brand.text\" }`; both produce the same Model reference, so a `theme.raw.json` needs no\n * function. (Top-level recipe composition fields — `colors: \"solid.brand\"` — are unaffected: a bare\n * string there is always a reference.)\n */\nexport const ref = (path: string): { ref: string } => ({ ref: path });\n"],"names":["parseRuleSetReference","reference","subsystem","rest","split","dot","indexOf","group","slice","variant","resolveReference","model","parsed","_c","_a","subsystems","ruleSets","_b","mergeDeclarations","target","source","prop","ref","Object","entries","responsiveKey","o","_d","_e","_f","breakpoint","query","orientation","state","container","size","eachRuleSet","out","sub","ruleSet","keys","push","defineAdapter","spec","name","version","allowedStates","bind","ctx","b","renderAllRecipes","join","map","renderRecipe","renderAllVariables","renderVariables","renderAll","describeUsage","format","summary","recipes","recipeName","srgbToLinear","c","Math","pow","relLuminance","r","g","LEVEL_RANK","fail","AA","AAA","APCA","apcaY","apcaLc","text","bg","clamp","y","yTxt","yBg","abs","sapc","round","n","dp","f","refToColor","theme","undefined","String","resolveToken","value","FG_KEY","BG_KEYS","pickBg","decls","k","scorePair","kind","label","fg","options","fgRgb","bgRgb","parseColor","rgb","skipped","ratio","a","la","lb","max","min","wcagRatio","level","large","wcagLevel","largeText","pass","minWcag","at","Array","isArray","got","RefractError","targets","opts","includeRecipes","pairings","includePalettes","path","tokens","m","exec","base","subModel","ruleSetGroup","baseFg","declarations","baseBg","override","overrides","oFg","_g","oBg","_h","cond","_l","_j","_k","scored","filter","p","failed","worst","reduce","w","Infinity","result","total","length","passed","ok","strict","list","parts","emit","files","own","components","sources","references","resolved","states","responsiveByKey","Map","key","entry","get","set","responsive","values","seen","Set","referencedPaths","collect","has","add"],"mappings":"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"}
|
package/dist/index.esm.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{R as $}from"./_errors-d75a5c74.esm.js";export{B as BREAKPOINT_EPSILON,C as CSS_UNITS,v as DEFAULT_BASE_FONT_SIZE,D as DEFAULT_BREAKPOINTS,A as DEFAULT_RESPONSIVE_QUERY,K as KNOWN_CSS_PROPERTIES,L as LENGTH_REGISTRY,U as animationSubsystem,N as bakeCrossPropertyDerivations,T as bordersSubsystem,g as buildComponentRuleSetFromInterpreted,t as buildContainerDescriptors,I as buildDerivationRegistry,l as buildMediaDescriptor,a as buildPropertiesModel,b as buildPropertyModel,c as buildRuleSetFromInterpreted,d as buildRuleSetGroupFromInterpreted,h as buildSubsystemModel,j as buildThemeModel,k as buildTokenMap,P as colorsSubsystem,V as componentsSubsystem,q as containerQueryString,H as createRecipeVariantResolver,O as createTheme,S as effectsSubsystem,f as extractComponentReferences,m as formatWidth,W as globalsSubsystem,i as isKnownCssProperty,R as layoutSubsystem,o as mediaQuery,n as mediaQueryString,z as normalizePropertyValue,G as normalizeRecipeGroup,E as normalizeResponsiveOverrides,u as parseLength,e as pathifyProperties,p as pathifyRuleSetGroup,x as resolveLengthRef,r as resolveMediaConfig,y as resolveModelUnits,w as resolveRoleUnit,J as resolveToken,M as resolveTokenMap,s as sortBreakpointKeys,Q as typographySubsystem,F as validateNormalizedResponsiveRefs}from"./_createTheme-255ff48e.esm.js";import{parseColor as _}from"./color-math.esm.js";const Y=e=>{const[o
|
|
1
|
+
import{R as $}from"./_errors-d75a5c74.esm.js";export{B as BREAKPOINT_EPSILON,C as CSS_UNITS,v as DEFAULT_BASE_FONT_SIZE,D as DEFAULT_BREAKPOINTS,A as DEFAULT_RESPONSIVE_QUERY,K as KNOWN_CSS_PROPERTIES,L as LENGTH_REGISTRY,U as animationSubsystem,N as bakeCrossPropertyDerivations,T as bordersSubsystem,g as buildComponentRuleSetFromInterpreted,t as buildContainerDescriptors,I as buildDerivationRegistry,l as buildMediaDescriptor,a as buildPropertiesModel,b as buildPropertyModel,c as buildRuleSetFromInterpreted,d as buildRuleSetGroupFromInterpreted,h as buildSubsystemModel,j as buildThemeModel,k as buildTokenMap,P as colorsSubsystem,V as componentsSubsystem,q as containerQueryString,H as createRecipeVariantResolver,O as createTheme,S as effectsSubsystem,f as extractComponentReferences,m as formatWidth,W as globalsSubsystem,i as isKnownCssProperty,R as layoutSubsystem,o as mediaQuery,n as mediaQueryString,z as normalizePropertyValue,G as normalizeRecipeGroup,E as normalizeResponsiveOverrides,u as parseLength,e as pathifyProperties,p as pathifyRuleSetGroup,x as resolveLengthRef,r as resolveMediaConfig,y as resolveModelUnits,w as resolveRoleUnit,J as resolveToken,M as resolveTokenMap,s as sortBreakpointKeys,Q as typographySubsystem,F as validateNormalizedResponsiveRefs}from"./_createTheme-255ff48e.esm.js";import{parseColor as _}from"./color-math.esm.js";const Y=e=>{const[t,o]=e.split(":");if(!t||!o)return;const r=o.indexOf(".");return r<0?void 0:{subsystem:t,group:o.slice(0,r),variant:o.slice(r+1)}},Z=(e,t)=>{var o,r,s;const a=Y(t);if(a)return null===(s=null===(r=null===(o=e.subsystems[a.subsystem])||void 0===o?void 0:o.ruleSets)||void 0===r?void 0:r[a.group])||void 0===s?void 0:s[a.variant]},X=(e,t)=>{for(const[o,r]of Object.entries(t))e[o]={...r}},ee=e=>{var t,o,r,s,a,n;return`${null!==(t=e.breakpoint)&&void 0!==t?t:""}|${null!==(o=e.query)&&void 0!==o?o:""}|${null!==(r=e.orientation)&&void 0!==r?r:""}|${null!==(s=e.state)&&void 0!==s?s:""}|${null!==(a=e.container)&&void 0!==a?a:""}|${null!==(n=e.size)&&void 0!==n?n:""}`},te=(e,t,o)=>{var r,s,a,n,i,l;const c=null===(a=null===(s=null===(r=e.subsystems.components)||void 0===r?void 0:r.ruleSets)||void 0===s?void 0:s[t])||void 0===a?void 0:a[o];if(!c)throw new $("REFRACT_E_REFERENCE",`mergeComponentRuleSet: no component rule-set "${t}.${o}"`);const u=[];for(const t of null!==(n=c.references)&&void 0!==n?n:[]){const o=Z(e,t);if(!o)throw new $("REFRACT_E_REFERENCE",`mergeComponentRuleSet: unresolved reference "${t}"`);u.push(o)}u.push(c);const d={},p={},f=new Map;for(const e of u){X(d,e.declarations);for(const t of e.overrides)if(t.declarations)if(void 0!==t.breakpoint||void 0!==t.container){const e=ee(t);let o=f.get(e);o||(o={...void 0!==t.breakpoint?{breakpoint:t.breakpoint}:{},...void 0!==t.query?{query:t.query}:{},...void 0!==t.orientation?{orientation:t.orientation}:{},...void 0!==t.state?{state:t.state}:{},...void 0!==t.container?{container:t.container}:{},...void 0!==t.size?{size:t.size}:{},declarations:{}},f.set(e,o)),X(o.declarations,t.declarations)}else void 0!==t.state?(null!==(i=p[l=t.state])&&void 0!==i||(p[l]={}),X(p[t.state],t.declarations)):X(d,t.declarations)}const v=[...f.values()],m=new Set,b=[],g=e=>{for(const t of Object.values(e))void 0===t.ref||m.has(t.ref)||(m.add(t.ref),b.push(t.ref))};g(d);for(const e of Object.values(p))g(e);for(const e of v)g(e.declarations);return{base:d,states:p,responsive:v,referencedPaths:b}},oe=e=>({ref:e});function re(e,t){const o=t?` (${t})`:"";if(null===e||"object"!=typeof e||Array.isArray(e)){const t=Array.isArray(e)?"an array":null===e?"null":typeof e;throw new $("REFRACT_E_RAW_SHAPE",`Expected a RawTheme object${o}, got ${t}. Pass the raw theme (a module's default export, or a .json raw theme).`)}if(Array.isArray(e.targets))throw new $("REFRACT_E_RAW_SHAPE",`Expected a RawTheme object${o}, but got what looks like a defineConfig({ raw, targets }). Pass its \`raw\` (or a module that default-exports the raw theme), not the whole config.`)}function se(e){var t;const o=[];for(const[r,s]of Object.entries(e.subsystems))for(const[e,a]of Object.entries(null!==(t=s.ruleSets)&&void 0!==t?t:{}))for(const t of Object.keys(a))o.push({subsystem:r,group:e,variant:t});return o}function ae(e){return{name:e.name,version:e.version,allowedStates:e.allowedStates,bind(t,o){var r,s,a,n;const i=e.bind(t,o),l=null!==(r=i.renderAllRecipes)&&void 0!==r?r:()=>i.join(se(t).map(({subsystem:e,group:t,variant:o})=>i.renderRecipe(e,t,o))),c=null!==(s=i.renderAllVariables)&&void 0!==s?s:()=>i.join(Object.keys(t.subsystems).map(e=>i.renderVariables(e))),u=null!==(a=i.renderAll)&&void 0!==a?a:()=>i.join([c(),l()]),d=null!==(n=i.describeUsage)&&void 0!==n?n:()=>({format:e.name,summary:[`This theme was built with the "${e.name}" refract adapter.`],recipes:se(t).map(({subsystem:e,group:t,variant:o})=>({subsystem:e,group:t,variant:o,name:i.recipeName(e,t,o)}))});return{...i,renderAllRecipes:l,renderAllVariables:c,renderAll:u,describeUsage:d}}}}function ne(){return ae({name:"noop",version:1,bind:()=>({recipeName:()=>"",renderRecipe:()=>"",renderVariables:()=>"",join:e=>e.join(""),emit:()=>({files:{}})})})}const ie=e=>e<=.04045?e/12.92:Math.pow((e+.055)/1.055,2.4),le=([e,t,o])=>.2126*ie(e/255)+.7152*ie(t/255)+.0722*ie(o/255),ce={fail:0,"AA-large":1,AA:2,AAA:3},ue=2.4,de=.2126729,pe=.7151522,fe=.072175,ve=.56,me=.57,be=.62,ge=.65,he=.022,ye=1.414,Re=1.14,Ae=.027,we=1.14,Se=.027,Ee=5e-4,Te=.1,$e=([e,t,o])=>de*Math.pow(e/255,ue)+pe*Math.pow(t/255,ue)+fe*Math.pow(o/255,ue),ke=(e,t)=>{const o=e=>e>he?e:e+Math.pow(he-e,ye),r=o($e(e)),s=o($e(t));if(Math.abs(s-r)<Ee)return 0;let a;if(s>r){const e=(Math.pow(s,ve)-Math.pow(r,me))*Re;a=e<Te?0:e-Ae}else{const e=(Math.pow(s,ge)-Math.pow(r,be))*we;a=e>-Te?0:e+Se}return 100*a},je=(e,t)=>{const o=10**t;return Math.round(e*o)/o},_e=(e,t)=>{if(void 0!==t.ref)try{return String(e.resolveToken(t.ref))}catch{return}if("string"==typeof t.value)return t.value},Me="color",Oe=["background-color","background"],Ce=e=>{if(e)for(const t of Oe)if(e[t])return e[t]},Pe=(e,t,o,r,s)=>{let a,n;try{void 0!==o&&(a=_(o).rgb)}catch{}try{void 0!==r&&(n=_(r).rgb)}catch{}if(!a||!n)return{kind:e,label:t,fg:o,bg:r,skipped:a||n?a?"bg not a colour":"fg not a colour":"no derivable fg/bg"};const i=((e,t)=>{const o=le(e),r=le(t);return(Math.max(o,r)+.05)/(Math.min(o,r)+.05)})(a,n),l=((e,t)=>t?e>=4.5?"AAA":e>=3?"AA":"fail":e>=7?"AAA":e>=4.5?"AA":e>=3?"AA-large":"fail")(i,s.largeText),c=ce[l]>=ce[s.minWcag];return{kind:e,label:t,fg:o,bg:r,wcagRatio:je(i,2),wcagLevel:l,apcaLc:je(ke(a,n),1),pass:c}},xe=(e,t={})=>{var o,r,s,a,n,i,l,c,u,d,p;const f={largeText:null!==(o=t.largeText)&&void 0!==o&&o,minWcag:null!==(r=t.minWcag)&&void 0!==r?r:"AA"},v=null===(s=t.includeRecipes)||void 0===s||s,m=[];if(null===(a=t.includePalettes)||void 0===a||a)for(const t of Object.keys(e.tokens)){const o=/^colors\.([^.]+)\.text$/.exec(t);if(!o)continue;const r=`colors.${o[1]}`;let s,a;try{s=String(e.resolveToken(t))}catch{}try{a=String(e.resolveToken(r))}catch{}m.push(Pe("palette",r,s,a,f))}if(v)for(const[t,o]of Object.entries(e.model.subsystems))if(o.ruleSets)for(const[r,s]of Object.entries(o.ruleSets))for(const[o,a]of Object.entries(s)){const s=a.declarations[Me],v=Ce(a.declarations),b=`${t}.${r}.${o}`;s&&v&&m.push(Pe("recipe",b,_e(e,s),_e(e,v),f));for(const t of null!==(n=a.overrides)&&void 0!==n?n:[]){const o=null!==(l=null===(i=t.declarations)||void 0===i?void 0:i[Me])&&void 0!==l?l:s,r=null!==(c=Ce(t.declarations))&&void 0!==c?c:v;if(!t.declarations||!t.declarations[Me]&&!Ce(t.declarations))continue;if(!o||!r)continue;const a=null!==(p=null!==(d=null!==(u=t.state)&&void 0!==u?u:t.breakpoint)&&void 0!==d?d:t.query)&&void 0!==p?p:"override";m.push(Pe("recipe",`${b} (${a})`,_e(e,o),_e(e,r),f))}}const b=m.filter(e=>!e.skipped),g=b.filter(e=>!1===e.pass),h=b.reduce((e,t)=>{var o,r;return void 0===e||(null!==(o=t.wcagRatio)&&void 0!==o?o:1/0)<(null!==(r=e.wcagRatio)&&void 0!==r?r:1/0)?t:e},void 0),y={pairings:m,summary:{total:b.length,passed:b.length-g.length,failed:g.length,skipped:m.length-b.length,worst:h},ok:0===g.length};if(t.strict&&g.length>0){const e=g.map(e=>`${e.label} (${e.wcagRatio}:1, ${e.wcagLevel})`).join(", ");throw new $("REFRACT_E_AUDIT",`refract audit: ${g.length} pairing(s) fail WCAG ${f.minWcag} — ${e}. Adjust the colour(s), lower --min-wcag, or drop --strict to report without failing.`,g.map(e=>`${e.label} (${e.wcagRatio}:1, ${e.wcagLevel})`))}return y};export{$ as RefractError,re as assertRawTheme,xe as audit,ne as createNoopAdapter,ae as defineAdapter,te as mergeComponentRuleSet,Y as parseRuleSetReference,oe as ref};
|
|
2
2
|
//# sourceMappingURL=index.esm.js.map
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/core/model/mergeRuleSet.ts","../src/core/ref.ts","../src/core/defineAdapter.ts","../src/core/noopAdapter.ts","../src/subsystems/colors/audit.ts"],"sourcesContent":["/**\n * Format-neutral component merge (§9c).\n *\n * `mergeComponentRuleSet` flattens one component variant into a single\n * self-contained rule-set: its referenced recipes' declarations + its own `css`\n * delta, unioned. The result is pure Model data — declarations stay as {@link Ref}s\n * carrying `{ ref, value }` — so an adapter renders it as baked values (inline) or\n * `var(--…)` / `theme.…` (referenced) without any format decision leaking in here.\n *\n * This is the ONLY new machinery the `components` emit mode needs, shared by the CSS\n * and future SC adapters. It is **on-demand** (an adapter calls it in `emit()`), never\n * materialized on `ThemeModel` / the runtime `theme`. It does NOT mutate the authored\n * `RuleSet` / declarations — the merged view is freshly derived (Refs shallow-cloned).\n *\n * Precedence (LOCKED, §9): authored **reference order** first (later refs override\n * earlier per property key), then the component's own declarations **last / highest**\n * (`css` delta wins over subsystem recipes). Same rule per condition bucket.\n */\nimport type {\n Orientation,\n Ref,\n ResponsiveQueryKind,\n RuleSet,\n RuleSetOverride,\n ThemeModel,\n} from \"./model\";\nimport { RefractError } from \"../errors\";\n\n/**\n * One flattened conditioned bucket — a distinct `(breakpoint, query, orientation, state, container, size)`\n * key. A **viewport** entry carries `breakpoint`; a **container** entry (§10.5) carries `container` + `size`\n * (and no `breakpoint`). The adapter emits the former as `@media`, the latter as `@container`.\n */\nexport type MergedResponsiveEntry = {\n breakpoint?: string;\n query?: ResponsiveQueryKind;\n orientation?: Orientation;\n state?: string;\n container?: string;\n size?: string;\n declarations: Record<string, Ref>;\n};\n\n/**\n * A component variant flattened into one self-contained rule-set.\n *\n * - `base` — merged no-condition declarations.\n * - `states` — merged declarations keyed by `state` (no breakpoint).\n * - `responsive` — one entry per distinct `(breakpoint, query, orientation, state)` merge key.\n * - `referencedPaths` — every distinct token path (`Ref.ref`) appearing across all buckets,\n * first-appearance order. What non-inline rendering tree-shakes the vars file to.\n */\nexport type MergedRuleSet = {\n base: Record<string, Ref>;\n states: Record<string, Record<string, Ref>>;\n responsive: MergedResponsiveEntry[];\n referencedPaths: string[];\n};\n\n/** The address parts of a component reference (`\"colors:solid.primary\"`). */\nexport type RuleSetReference = { subsystem: string; group: string; variant: string };\n\n/**\n * Parse a component reference (`\"subsystem:group.variant\"`) into its address parts.\n * Format-neutral core twin of the CSS adapter's `parseComponentReference` (which stays\n * for the option-C class-list path). Returns `undefined` on a malformed reference.\n */\nexport const parseRuleSetReference = (reference: string): RuleSetReference | undefined => {\n const [subsystem, rest] = reference.split(\":\");\n if (!subsystem || !rest) return undefined;\n const dot = rest.indexOf(\".\");\n if (dot < 0) return undefined;\n return { subsystem, group: rest.slice(0, dot), variant: rest.slice(dot + 1) };\n};\n\n/** Resolve a reference to its authored `RuleSet`, or `undefined` if it doesn't address one. */\nconst resolveReference = (model: ThemeModel, reference: string): RuleSet | undefined => {\n const parsed = parseRuleSetReference(reference);\n if (!parsed) return undefined;\n return model.subsystems[parsed.subsystem]?.ruleSets?.[parsed.group]?.[parsed.variant];\n};\n\n/** Fold `source` declarations into `target` (later source wins), shallow-cloning each Ref. */\nconst mergeDeclarations = (target: Record<string, Ref>, source: Record<string, Ref>): void => {\n for (const [prop, ref] of Object.entries(source)) target[prop] = { ...ref };\n};\n\n/** Stable string key for a conditioned bucket — `(breakpoint, query, orientation, state, container, size)`. */\nconst responsiveKey = (o: RuleSetOverride): string =>\n `${o.breakpoint ?? \"\"}|${o.query ?? \"\"}|${o.orientation ?? \"\"}|${o.state ?? \"\"}|${o.container ?? \"\"}|${o.size ?? \"\"}`;\n\n/**\n * Flatten one component variant into a self-contained {@link MergedRuleSet}.\n *\n * Reads `model.subsystems.components.ruleSets[group][variant]` — its `references`\n * (resolved in authored order), own base `declarations`, and `overrides` — and unions\n * them under the locked precedence. Throws on a missing component or an unresolved reference.\n */\nexport const mergeComponentRuleSet = (\n model: ThemeModel,\n group: string,\n variant: string,\n): MergedRuleSet => {\n const own = model.subsystems.components?.ruleSets?.[group]?.[variant];\n if (!own) {\n throw new RefractError(\"REFRACT_E_REFERENCE\", `mergeComponentRuleSet: no component rule-set \"${group}.${variant}\"`);\n }\n\n // Sources in precedence order: referenced rule-sets left-to-right, then the component's own last.\n const sources: RuleSet[] = [];\n for (const reference of own.references ?? []) {\n const resolved = resolveReference(model, reference);\n if (!resolved) {\n throw new RefractError(\"REFRACT_E_REFERENCE\", `mergeComponentRuleSet: unresolved reference \"${reference}\"`);\n }\n sources.push(resolved);\n }\n sources.push(own);\n\n const base: Record<string, Ref> = {};\n const states: Record<string, Record<string, Ref>> = {};\n const responsiveByKey = new Map<string, MergedResponsiveEntry>();\n\n for (const source of sources) {\n mergeDeclarations(base, source.declarations);\n\n for (const override of source.overrides) {\n if (!override.declarations) continue;\n // A breakpoint OR container condition → a conditioned bucket (viewport → @media, container →\n // @container). Container overrides MUST route here, not fold into base (§10.5 correctness).\n if (override.breakpoint !== undefined || override.container !== undefined) {\n const key = responsiveKey(override);\n let entry = responsiveByKey.get(key);\n if (!entry) {\n entry = {\n ...(override.breakpoint !== undefined ? { breakpoint: override.breakpoint } : {}),\n ...(override.query !== undefined ? { query: override.query } : {}),\n ...(override.orientation !== undefined ? { orientation: override.orientation } : {}),\n ...(override.state !== undefined ? { state: override.state } : {}),\n ...(override.container !== undefined ? { container: override.container } : {}),\n ...(override.size !== undefined ? { size: override.size } : {}),\n declarations: {},\n };\n responsiveByKey.set(key, entry);\n }\n mergeDeclarations(entry.declarations, override.declarations);\n } else if (override.state !== undefined) {\n (states[override.state] ??= {});\n mergeDeclarations(states[override.state], override.declarations);\n } else {\n // Unconditional override (only variant/target, no breakpoint/state) — folds into base.\n mergeDeclarations(base, override.declarations);\n }\n }\n }\n\n const responsive = [...responsiveByKey.values()];\n\n // referencedPaths — every distinct token path across all buckets, first-appearance order.\n const seen = new Set<string>();\n const referencedPaths: string[] = [];\n const collect = (decls: Record<string, Ref>): void => {\n for (const ref of Object.values(decls)) {\n if (ref.ref !== undefined && !seen.has(ref.ref)) {\n seen.add(ref.ref);\n referencedPaths.push(ref.ref);\n }\n }\n };\n collect(base);\n for (const decls of Object.values(states)) collect(decls);\n for (const entry of responsive) collect(entry.declarations);\n\n return { base, states, responsive, referencedPaths };\n};\n","/**\n * `ref(path)` — author a token **reference** inside a `css` delta or a globals element rule.\n *\n * Inside a `css` block (and globals element declarations) a bare string is a **literal** CSS value —\n * `display: \"flex\"` emits `flex`. To emit a token reference instead, wrap the token path in `ref()`:\n * `color: ref(\"colors.brand.text\")` → `var(--…)`. The JSON-safe equivalent is the plain object form\n * `{ ref: \"colors.brand.text\" }`; both produce the same Model reference, so a `theme.raw.json` needs no\n * function. (Top-level recipe composition fields — `colors: \"solid.brand\"` — are unaffected: a bare\n * string there is always a reference.)\n */\nexport const ref = (path: string): { ref: string } => ({ ref: path });\n","/**\n * `defineAdapter` — turns an `AdapterSpec` (identity + a `bind` returning the four\n * required primitives) into a full `ThemeAdapter` whose `bind` yields a complete\n * `BoundAdapter` with the DEFAULTED aggregators supplied.\n *\n * The defaults are pure Model walks: the Model enumerates every subsystem and every\n * (group, variant), so core loops it, calls the author's per-unit renderers, and\n * `join`s the results. Model/ctx are already bound, so the aggregators take no args.\n * An author can still override any aggregator (a format whose full document isn't a\n * flat concatenation).\n */\n\nimport type { ThemeModel } from \"./model\";\nimport type {\n AdapterSpec,\n ThemeAdapter,\n BoundAdapter,\n RenderContext,\n UsageDescriptor,\n} from \"./ThemeAdapter\";\n\n/** Every rule-set address in the Model — `(subsystem, group, variant)` triples. */\nfunction eachRuleSet(model: ThemeModel): Array<{ subsystem: string; group: string; variant: string }> {\n const out: Array<{ subsystem: string; group: string; variant: string }> = [];\n for (const [subsystem, sub] of Object.entries(model.subsystems)) {\n for (const [group, ruleSet] of Object.entries(sub.ruleSets ?? {})) {\n for (const variant of Object.keys(ruleSet)) {\n out.push({ subsystem, group, variant });\n }\n }\n }\n return out;\n}\n\n/**\n * Complete an `AdapterSpec` into a `ThemeAdapter`.\n *\n * Wraps the author's `bind` so the returned `BoundAdapter` gains the defaulted\n * aggregators (`renderAllRecipes` / `renderAllVariables` / `renderAll`) built from\n * the required primitives — unless the spec already provides its own override.\n * `name` / `version` pass through unchanged.\n *\n * @param spec identity (`name`/`version`) + a `bind(model, ctx)` returning the\n * required render primitives (and any optional overrides).\n * @returns a full adapter whose `bind(model, ctx)` yields a complete `BoundAdapter`.\n */\nexport function defineAdapter<TUnit>(spec: AdapterSpec<TUnit>): ThemeAdapter<TUnit> {\n return {\n name: spec.name,\n version: spec.version,\n allowedStates: spec.allowedStates,\n bind(model: ThemeModel, ctx: RenderContext): BoundAdapter<TUnit> {\n const b = spec.bind(model, ctx);\n\n const renderAllRecipes =\n b.renderAllRecipes ??\n ((): TUnit =>\n b.join(\n eachRuleSet(model).map(({ subsystem, group, variant }) =>\n b.renderRecipe(subsystem, group, variant),\n ),\n ));\n\n const renderAllVariables =\n b.renderAllVariables ??\n ((): TUnit => b.join(Object.keys(model.subsystems).map(subsystem => b.renderVariables(subsystem))));\n\n const renderAll =\n b.renderAll ?? ((): TUnit => b.join([renderAllVariables(), renderAllRecipes()]));\n\n // Generic self-documentation: the recipe identities are format-correct via `recipeName`; an\n // adapter overrides `describeUsage` to add format-specific import prose to `summary`.\n const describeUsage =\n b.describeUsage ??\n ((): UsageDescriptor => ({\n format: spec.name,\n summary: [`This theme was built with the \"${spec.name}\" refract adapter.`],\n recipes: eachRuleSet(model).map(({ subsystem, group, variant }) => ({\n subsystem,\n group,\n variant,\n name: b.recipeName(subsystem, group, variant),\n })),\n }));\n\n return { ...b, renderAllRecipes, renderAllVariables, renderAll, describeUsage };\n },\n };\n}\n","/**\n * `createNoopAdapter` — the trivial, built-in null adapter (monorepo split, friction 2).\n *\n * `createTheme` requires an `adapter`, but some consumers of the built `Theme` never touch\n * adapter-produced strings — they read only the format-neutral `theme.tokens` / `theme.resolveToken`\n * / `theme.model` (the DTCG export is the canonical example: `toDTCG` walks the flat token map and the\n * breakpoints, never a rendered rule). Those callers need *a* valid adapter purely to satisfy the\n * contract; the output is discarded.\n *\n * Before the split the CLI's `tokens` command reached for `createCssAdapter` as that throwaway builder\n * — which forced a core→adapter dependency (`src/build` importing `src/adapters/css`). The monorepo\n * guiding rule is that the dependency arrow points ONLY into core, so core now ships its own null\n * object: `createNoopAdapter()` emits nothing (empty strings, an empty `emit()`), lets `createTheme`\n * build the Model + token map exactly as any adapter would, and keeps `src/build` free of every\n * adapter package.\n *\n * It's a `ThemeAdapter` like any other (built through {@link defineAdapter}, so it gets the defaulted\n * aggregators for free), just with render primitives that produce empty output.\n */\n\nimport { defineAdapter } from \"./defineAdapter\";\nimport type { ThemeAdapter } from \"./ThemeAdapter\";\n\n/**\n * A no-op adapter: every render primitive returns an empty string and `emit()` writes no files. Use it\n * whenever a `Theme` is needed only for its format-neutral data (`tokens` / `resolveToken` / `model`)\n * and the rendered output is irrelevant — e.g. the `refract tokens` DTCG export.\n */\nexport function createNoopAdapter(): ThemeAdapter<string> {\n return defineAdapter<string>({\n name: \"noop\",\n version: 1,\n bind: () => ({\n recipeName: () => \"\",\n renderRecipe: () => \"\",\n renderVariables: () => \"\",\n join: parts => parts.join(\"\"),\n emit: () => ({ files: {} }),\n }),\n });\n}\n","/**\n * Contrast audit (opt-in) — scores a built theme's colour pairings for **WCAG 2** contrast ratio\n * (the compliance standard) plus an **advisory APCA** Lc reading. It reports; it never mutates the\n * theme and never \"fixes\" a colour. `audit()` returns structured results by default; a caller (or the\n * `refract audit --strict` CLI) can throw on failures.\n *\n * Which pairings: every palette's `base` ↔ `text`, and every recipe's foreground (`color`) ↔\n * background (`background-color` / `background`) across all subsystems' rule-sets (base + state\n * overrides). A side that isn't a derivable colour (`transparent`, a `var()`, a keyword literal) is\n * reported as `skipped`, not a failure.\n *\n * Colour math is inlined here on purpose: `utils.ts` is vendored to consumers (`build/vendor.ts`) and\n * kept dependency-free / minimal, so we don't widen its export surface for a non-vendored sibling. We\n * reuse only the already-exported {@link parseColor}.\n */\nimport type { Theme, Ref } from \"../../core\";\nimport { RefractError } from \"../../core/errors\";\nimport { parseColor, type RGBTuple } from \"./utils\";\n\n// ── WCAG 2.x ──────────────────────────────────────────────────────────────\n// Relative luminance per WCAG 2: linearize each sRGB channel, weight by the luma coefficients.\nconst srgbToLinear = (c: number): number => (c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4));\nconst relLuminance = ([r, g, b]: RGBTuple): number =>\n 0.2126 * srgbToLinear(r / 255) + 0.7152 * srgbToLinear(g / 255) + 0.0722 * srgbToLinear(b / 255);\n\n/** WCAG 2 contrast ratio (1–21) between two sRGB colours; order-independent. */\nconst wcagRatio = (a: RGBTuple, b: RGBTuple): number => {\n const la = relLuminance(a);\n const lb = relLuminance(b);\n const hi = Math.max(la, lb);\n const lo = Math.min(la, lb);\n return (hi + 0.05) / (lo + 0.05);\n};\n\nexport type WcagLevel = \"AAA\" | \"AA\" | \"AA-large\" | \"fail\";\nconst LEVEL_RANK: Record<WcagLevel, number> = { fail: 0, \"AA-large\": 1, AA: 2, AAA: 3 };\n\n/** Map a ratio to a level. For normal text 3–4.5 is \"AA-large\" (passes only at large sizes). */\nconst wcagLevel = (ratio: number, large: boolean): WcagLevel => {\n if (large) return ratio >= 4.5 ? \"AAA\" : ratio >= 3 ? \"AA\" : \"fail\";\n return ratio >= 7 ? \"AAA\" : ratio >= 4.5 ? \"AA\" : ratio >= 3 ? \"AA-large\" : \"fail\";\n};\n\n// ── APCA (advisory) ───────────────────────────────────────────────────────\n// APCA 0.1.9 / formula 0.98G-4g (SAPC). Advisory only — NOT a WCAG substitute — and the draft may\n// still shift, so the constants are pinned here. Returns a signed Lc (polarity-aware).\nconst APCA = {\n mainTRC: 2.4,\n sRco: 0.2126729, sGco: 0.7151522, sBco: 0.072175,\n normBG: 0.56, normTXT: 0.57, revTXT: 0.62, revBG: 0.65,\n blkThrs: 0.022, blkClmp: 1.414,\n scaleBoW: 1.14, loBoWoffset: 0.027,\n scaleWoB: 1.14, loWoBoffset: 0.027,\n deltaYmin: 0.0005, loClip: 0.1,\n} as const;\n\nconst apcaY = ([r, g, b]: RGBTuple): number =>\n APCA.sRco * Math.pow(r / 255, APCA.mainTRC) +\n APCA.sGco * Math.pow(g / 255, APCA.mainTRC) +\n APCA.sBco * Math.pow(b / 255, APCA.mainTRC);\n\n/** Signed APCA lightness contrast (Lc) of `text` over `bg`. Positive = dark-on-light, negative = light-on-dark. */\nconst apcaLc = (text: RGBTuple, bg: RGBTuple): number => {\n const clamp = (y: number): number => (y > APCA.blkThrs ? y : y + Math.pow(APCA.blkThrs - y, APCA.blkClmp));\n const yTxt = clamp(apcaY(text));\n const yBg = clamp(apcaY(bg));\n if (Math.abs(yBg - yTxt) < APCA.deltaYmin) return 0;\n let out: number;\n if (yBg > yTxt) {\n const sapc = (Math.pow(yBg, APCA.normBG) - Math.pow(yTxt, APCA.normTXT)) * APCA.scaleBoW;\n out = sapc < APCA.loClip ? 0 : sapc - APCA.loBoWoffset;\n } else {\n const sapc = (Math.pow(yBg, APCA.revBG) - Math.pow(yTxt, APCA.revTXT)) * APCA.scaleWoB;\n out = sapc > -APCA.loClip ? 0 : sapc + APCA.loWoBoffset;\n }\n return out * 100;\n};\n\n// ── audit ─────────────────────────────────────────────────────────────────\n\nexport type PairingKind = \"palette\" | \"recipe\";\n\nexport interface PairingScore {\n kind: PairingKind;\n /** Human label, e.g. `colors.brand` or `components.buttons.primary (:hover)`. */\n label: string;\n /** Resolved foreground colour string, or `undefined` when it isn't a derivable colour. */\n fg?: string;\n /** Resolved background colour string, or `undefined` when it isn't a derivable colour. */\n bg?: string;\n /** WCAG 2 contrast ratio (1–21, 2 dp). Absent when skipped. */\n wcagRatio?: number;\n /** WCAG level at the configured text size. Absent when skipped. */\n wcagLevel?: WcagLevel;\n /** Advisory APCA Lc (signed, 1 dp). Absent when skipped. */\n apcaLc?: number;\n /** Whether this pairing met the pass bar (`minWcag`). Absent when skipped. */\n pass?: boolean;\n /** Set when a side isn't a derivable colour — then the score fields are absent. */\n skipped?: string;\n}\n\nexport interface AuditOptions {\n /** Throw an aggregated error when any pairing fails, instead of only reporting. Default `false`. */\n strict?: boolean;\n /** Treat the foreground as large text (relaxed WCAG thresholds). Default `false`. */\n largeText?: boolean;\n /** The pass bar. Default `\"AA\"`. `\"AA-large\"` accepts the 3:1 tier. */\n minWcag?: WcagLevel;\n /** Audit component/recipe fg↔bg pairs. Default `true`. */\n includeRecipes?: boolean;\n /** Audit palette base↔text pairs. Default `true`. */\n includePalettes?: boolean;\n}\n\nexport interface AuditResult {\n pairings: PairingScore[];\n summary: {\n total: number;\n passed: number;\n failed: number;\n skipped: number;\n /** The lowest-ratio scored pairing (the worst offender), if any were scored. */\n worst?: PairingScore;\n };\n /** `true` when no scored pairing failed the pass bar. */\n ok: boolean;\n}\n\nconst round = (n: number, dp: number): number => {\n const f = 10 ** dp;\n return Math.round(n * f) / f;\n};\n\n/** Resolve a rule-set declaration `Ref` to a colour string, or `undefined` if it isn't one. */\nconst refToColor = (theme: Theme, ref: Ref): string | undefined => {\n if (ref.ref !== undefined) {\n try {\n return String(theme.resolveToken(ref.ref));\n } catch {\n return undefined;\n }\n }\n if (typeof ref.value === \"string\") return ref.value;\n return undefined;\n};\n\nconst FG_KEY = \"color\";\nconst BG_KEYS = [\"background-color\", \"background\"] as const;\nconst pickBg = (decls: Record<string, Ref> | undefined): Ref | undefined => {\n if (!decls) return undefined;\n for (const k of BG_KEYS) if (decls[k]) return decls[k];\n return undefined;\n};\n\n/** Score one fg/bg pairing (colours already resolved to strings), or a skipped record. */\nconst scorePair = (\n kind: PairingKind,\n label: string,\n fg: string | undefined,\n bg: string | undefined,\n options: Required<Pick<AuditOptions, \"largeText\" | \"minWcag\">>,\n): PairingScore => {\n let fgRgb: RGBTuple | undefined;\n let bgRgb: RGBTuple | undefined;\n try {\n if (fg !== undefined) fgRgb = parseColor(fg).rgb;\n } catch { /* not a derivable colour */ }\n try {\n if (bg !== undefined) bgRgb = parseColor(bg).rgb;\n } catch { /* not a derivable colour */ }\n\n if (!fgRgb || !bgRgb) {\n return { kind, label, fg, bg, skipped: !fgRgb && !bgRgb ? \"no derivable fg/bg\" : !fgRgb ? \"fg not a colour\" : \"bg not a colour\" };\n }\n\n const ratio = wcagRatio(fgRgb, bgRgb);\n const level = wcagLevel(ratio, options.largeText);\n const pass = LEVEL_RANK[level] >= LEVEL_RANK[options.minWcag];\n return {\n kind, label, fg, bg,\n wcagRatio: round(ratio, 2),\n wcagLevel: level,\n apcaLc: round(apcaLc(fgRgb, bgRgb), 1),\n pass,\n };\n};\n\n/**\n * Audit a built theme's colour pairings. Pure — reads `theme.tokens` / `theme.resolveToken` /\n * `theme.model` only. In `strict` mode, throws one aggregated error listing every failing pairing.\n */\nexport const audit = (theme: Theme, options: AuditOptions = {}): AuditResult => {\n const opts = {\n largeText: options.largeText ?? false,\n minWcag: options.minWcag ?? (\"AA\" as WcagLevel),\n };\n const includeRecipes = options.includeRecipes ?? true;\n const includePalettes = options.includePalettes ?? true;\n const pairings: PairingScore[] = [];\n\n // Palettes: base ↔ text. A palette advertises a pairing by having a `colors.<name>.text` token.\n if (includePalettes) {\n for (const path of Object.keys(theme.tokens)) {\n const m = /^colors\\.([^.]+)\\.text$/.exec(path);\n if (!m) continue;\n const base = `colors.${m[1]}`;\n let fg: string | undefined, bg: string | undefined;\n try { fg = String(theme.resolveToken(path)); } catch { /* skip */ }\n try { bg = String(theme.resolveToken(base)); } catch { /* skip */ }\n pairings.push(scorePair(\"palette\", base, fg, bg, opts));\n }\n }\n\n // Recipes: every subsystem's rule-sets — the base declarations + each state/breakpoint override.\n if (includeRecipes) {\n for (const [subsystem, subModel] of Object.entries(theme.model.subsystems)) {\n if (!subModel.ruleSets) continue;\n for (const [group, ruleSetGroup] of Object.entries(subModel.ruleSets)) {\n for (const [variant, ruleSet] of Object.entries(ruleSetGroup)) {\n const baseFg = ruleSet.declarations[FG_KEY];\n const baseBg = pickBg(ruleSet.declarations);\n const label = `${subsystem}.${group}.${variant}`;\n if (baseFg && baseBg) {\n pairings.push(scorePair(\"recipe\", label, refToColor(theme, baseFg), refToColor(theme, baseBg), opts));\n }\n // Overrides (e.g. :hover) can swap bg or fg — score the effective pairing at that condition.\n for (const override of ruleSet.overrides ?? []) {\n const oFg = override.declarations?.[FG_KEY] ?? baseFg;\n const oBg = pickBg(override.declarations) ?? baseBg;\n if (!override.declarations || (!override.declarations[FG_KEY] && !pickBg(override.declarations))) continue;\n if (!oFg || !oBg) continue;\n const cond = override.state ?? override.breakpoint ?? override.query ?? \"override\";\n pairings.push(scorePair(\"recipe\", `${label} (${cond})`, refToColor(theme, oFg), refToColor(theme, oBg), opts));\n }\n }\n }\n }\n }\n\n const scored = pairings.filter(p => !p.skipped);\n const failed = scored.filter(p => p.pass === false);\n const worst = scored.reduce<PairingScore | undefined>(\n (w, p) => (w === undefined || (p.wcagRatio ?? Infinity) < (w.wcagRatio ?? Infinity) ? p : w),\n undefined,\n );\n const result: AuditResult = {\n pairings,\n summary: {\n total: scored.length,\n passed: scored.length - failed.length,\n failed: failed.length,\n skipped: pairings.length - scored.length,\n worst,\n },\n ok: failed.length === 0,\n };\n\n if (options.strict && failed.length > 0) {\n const list = failed.map(p => `${p.label} (${p.wcagRatio}:1, ${p.wcagLevel})`).join(\", \");\n throw new RefractError(\n \"REFRACT_E_AUDIT\",\n `refract audit: ${failed.length} pairing(s) fail WCAG ${opts.minWcag} — ${list}. ` +\n `Adjust the colour(s), lower --min-wcag, or drop --strict to report without failing.`,\n failed.map(p => `${p.label} (${p.wcagRatio}:1, ${p.wcagLevel})`),\n );\n }\n\n return result;\n};\n"],"names":["parseRuleSetReference","reference","subsystem","rest","split","dot","indexOf","group","slice","variant","resolveReference","model","parsed","_c","_a","subsystems","ruleSets","_b","mergeDeclarations","target","source","prop","ref","Object","entries","responsiveKey","o","_d","_e","_f","breakpoint","query","orientation","state","container","size","mergeComponentRuleSet","own","components","RefractError","sources","references","resolved","push","base","states","responsiveByKey","Map","declarations","override","overrides","undefined","key","entry","get","set","responsive","values","seen","Set","referencedPaths","collect","decls","has","add","path","eachRuleSet","out","sub","ruleSet","keys","defineAdapter","spec","name","version","allowedStates","bind","ctx","b","renderAllRecipes","join","map","renderRecipe","renderAllVariables","renderVariables","renderAll","describeUsage","format","summary","recipes","recipeName","createNoopAdapter","parts","emit","files","srgbToLinear","c","Math","pow","relLuminance","r","g","LEVEL_RANK","fail","AA","AAA","APCA","apcaY","apcaLc","text","bg","clamp","y","yTxt","yBg","abs","sapc","round","n","dp","f","refToColor","theme","String","resolveToken","value","FG_KEY","BG_KEYS","pickBg","k","scorePair","kind","label","fg","options","fgRgb","bgRgb","parseColor","rgb","skipped","ratio","a","la","lb","max","min","wcagRatio","level","large","wcagLevel","largeText","pass","minWcag","audit","opts","includeRecipes","pairings","includePalettes","tokens","m","exec","subModel","ruleSetGroup","baseFg","baseBg","oFg","_g","oBg","_h","cond","_l","_j","_k","scored","filter","p","failed","worst","reduce","w","Infinity","result","total","length","passed","ok","strict","list"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/core/model/mergeRuleSet.ts","../src/core/ref.ts","../src/core/assertRawTheme.ts","../src/core/defineAdapter.ts","../src/core/noopAdapter.ts","../src/subsystems/colors/audit.ts"],"sourcesContent":["/**\n * Format-neutral component merge (§9c).\n *\n * `mergeComponentRuleSet` flattens one component variant into a single\n * self-contained rule-set: its referenced recipes' declarations + its own `css`\n * delta, unioned. The result is pure Model data — declarations stay as {@link Ref}s\n * carrying `{ ref, value }` — so an adapter renders it as baked values (inline) or\n * `var(--…)` / `theme.…` (referenced) without any format decision leaking in here.\n *\n * This is the ONLY new machinery the `components` emit mode needs, shared by the CSS\n * and future SC adapters. It is **on-demand** (an adapter calls it in `emit()`), never\n * materialized on `ThemeModel` / the runtime `theme`. It does NOT mutate the authored\n * `RuleSet` / declarations — the merged view is freshly derived (Refs shallow-cloned).\n *\n * Precedence (LOCKED, §9): authored **reference order** first (later refs override\n * earlier per property key), then the component's own declarations **last / highest**\n * (`css` delta wins over subsystem recipes). Same rule per condition bucket.\n */\nimport type {\n Orientation,\n Ref,\n ResponsiveQueryKind,\n RuleSet,\n RuleSetOverride,\n ThemeModel,\n} from \"./model\";\nimport { RefractError } from \"../errors\";\n\n/**\n * One flattened conditioned bucket — a distinct `(breakpoint, query, orientation, state, container, size)`\n * key. A **viewport** entry carries `breakpoint`; a **container** entry (§10.5) carries `container` + `size`\n * (and no `breakpoint`). The adapter emits the former as `@media`, the latter as `@container`.\n */\nexport type MergedResponsiveEntry = {\n breakpoint?: string;\n query?: ResponsiveQueryKind;\n orientation?: Orientation;\n state?: string;\n container?: string;\n size?: string;\n declarations: Record<string, Ref>;\n};\n\n/**\n * A component variant flattened into one self-contained rule-set.\n *\n * - `base` — merged no-condition declarations.\n * - `states` — merged declarations keyed by `state` (no breakpoint).\n * - `responsive` — one entry per distinct `(breakpoint, query, orientation, state)` merge key.\n * - `referencedPaths` — every distinct token path (`Ref.ref`) appearing across all buckets,\n * first-appearance order. What non-inline rendering tree-shakes the vars file to.\n */\nexport type MergedRuleSet = {\n base: Record<string, Ref>;\n states: Record<string, Record<string, Ref>>;\n responsive: MergedResponsiveEntry[];\n referencedPaths: string[];\n};\n\n/** The address parts of a component reference (`\"colors:solid.primary\"`). */\nexport type RuleSetReference = { subsystem: string; group: string; variant: string };\n\n/**\n * Parse a component reference (`\"subsystem:group.variant\"`) into its address parts.\n * Format-neutral core twin of the CSS adapter's `parseComponentReference` (which stays\n * for the option-C class-list path). Returns `undefined` on a malformed reference.\n */\nexport const parseRuleSetReference = (reference: string): RuleSetReference | undefined => {\n const [subsystem, rest] = reference.split(\":\");\n if (!subsystem || !rest) return undefined;\n const dot = rest.indexOf(\".\");\n if (dot < 0) return undefined;\n return { subsystem, group: rest.slice(0, dot), variant: rest.slice(dot + 1) };\n};\n\n/** Resolve a reference to its authored `RuleSet`, or `undefined` if it doesn't address one. */\nconst resolveReference = (model: ThemeModel, reference: string): RuleSet | undefined => {\n const parsed = parseRuleSetReference(reference);\n if (!parsed) return undefined;\n return model.subsystems[parsed.subsystem]?.ruleSets?.[parsed.group]?.[parsed.variant];\n};\n\n/** Fold `source` declarations into `target` (later source wins), shallow-cloning each Ref. */\nconst mergeDeclarations = (target: Record<string, Ref>, source: Record<string, Ref>): void => {\n for (const [prop, ref] of Object.entries(source)) target[prop] = { ...ref };\n};\n\n/** Stable string key for a conditioned bucket — `(breakpoint, query, orientation, state, container, size)`. */\nconst responsiveKey = (o: RuleSetOverride): string =>\n `${o.breakpoint ?? \"\"}|${o.query ?? \"\"}|${o.orientation ?? \"\"}|${o.state ?? \"\"}|${o.container ?? \"\"}|${o.size ?? \"\"}`;\n\n/**\n * Flatten one component variant into a self-contained {@link MergedRuleSet}.\n *\n * Reads `model.subsystems.components.ruleSets[group][variant]` — its `references`\n * (resolved in authored order), own base `declarations`, and `overrides` — and unions\n * them under the locked precedence. Throws on a missing component or an unresolved reference.\n */\nexport const mergeComponentRuleSet = (\n model: ThemeModel,\n group: string,\n variant: string,\n): MergedRuleSet => {\n const own = model.subsystems.components?.ruleSets?.[group]?.[variant];\n if (!own) {\n throw new RefractError(\"REFRACT_E_REFERENCE\", `mergeComponentRuleSet: no component rule-set \"${group}.${variant}\"`);\n }\n\n // Sources in precedence order: referenced rule-sets left-to-right, then the component's own last.\n const sources: RuleSet[] = [];\n for (const reference of own.references ?? []) {\n const resolved = resolveReference(model, reference);\n if (!resolved) {\n throw new RefractError(\"REFRACT_E_REFERENCE\", `mergeComponentRuleSet: unresolved reference \"${reference}\"`);\n }\n sources.push(resolved);\n }\n sources.push(own);\n\n const base: Record<string, Ref> = {};\n const states: Record<string, Record<string, Ref>> = {};\n const responsiveByKey = new Map<string, MergedResponsiveEntry>();\n\n for (const source of sources) {\n mergeDeclarations(base, source.declarations);\n\n for (const override of source.overrides) {\n if (!override.declarations) continue;\n // A breakpoint OR container condition → a conditioned bucket (viewport → @media, container →\n // @container). Container overrides MUST route here, not fold into base (§10.5 correctness).\n if (override.breakpoint !== undefined || override.container !== undefined) {\n const key = responsiveKey(override);\n let entry = responsiveByKey.get(key);\n if (!entry) {\n entry = {\n ...(override.breakpoint !== undefined ? { breakpoint: override.breakpoint } : {}),\n ...(override.query !== undefined ? { query: override.query } : {}),\n ...(override.orientation !== undefined ? { orientation: override.orientation } : {}),\n ...(override.state !== undefined ? { state: override.state } : {}),\n ...(override.container !== undefined ? { container: override.container } : {}),\n ...(override.size !== undefined ? { size: override.size } : {}),\n declarations: {},\n };\n responsiveByKey.set(key, entry);\n }\n mergeDeclarations(entry.declarations, override.declarations);\n } else if (override.state !== undefined) {\n (states[override.state] ??= {});\n mergeDeclarations(states[override.state], override.declarations);\n } else {\n // Unconditional override (only variant/target, no breakpoint/state) — folds into base.\n mergeDeclarations(base, override.declarations);\n }\n }\n }\n\n const responsive = [...responsiveByKey.values()];\n\n // referencedPaths — every distinct token path across all buckets, first-appearance order.\n const seen = new Set<string>();\n const referencedPaths: string[] = [];\n const collect = (decls: Record<string, Ref>): void => {\n for (const ref of Object.values(decls)) {\n if (ref.ref !== undefined && !seen.has(ref.ref)) {\n seen.add(ref.ref);\n referencedPaths.push(ref.ref);\n }\n }\n };\n collect(base);\n for (const decls of Object.values(states)) collect(decls);\n for (const entry of responsive) collect(entry.declarations);\n\n return { base, states, responsive, referencedPaths };\n};\n","/**\n * `ref(path)` — author a token **reference** inside a `css` delta or a globals element rule.\n *\n * Inside a `css` block (and globals element declarations) a bare string is a **literal** CSS value —\n * `display: \"flex\"` emits `flex`. To emit a token reference instead, wrap the token path in `ref()`:\n * `color: ref(\"colors.brand.text\")` → `var(--…)`. The JSON-safe equivalent is the plain object form\n * `{ ref: \"colors.brand.text\" }`; both produce the same Model reference, so a `theme.raw.json` needs no\n * function. (Top-level recipe composition fields — `colors: \"solid.brand\"` — are unaffected: a bare\n * string there is always a reference.)\n */\nexport const ref = (path: string): { ref: string } => ({ ref: path });\n","/**\n * Fail-loud shape guard for a value that is *supposed* to be a {@link RawTheme}.\n *\n * `createTheme` accepts a bare object, and an empty `{}` is a valid (empty) theme — so a value of the\n * *wrong* shape doesn't necessarily throw during a build. That's the trap `refract diff` fell into: hand\n * it a `defineConfig({ raw, targets })` where it wanted the raw theme and it built the config as an\n * (effectively empty) theme, then reported a nonsense \"every token removed\" diff and exited 0. A\n * governance tool must not quietly mis-report. This guard is the loud, coded gate for that class of\n * mistake — used by `diff` (and available to `validate` / the MCP server) before anything is compared.\n *\n * It is deliberately narrow: it rejects only values that cannot be a RawTheme (non-objects, arrays,\n * `null`) or that are affirmatively something else (a `defineConfig`, spotted by its `targets` array).\n * A bare `{}` still passes — an empty theme is legitimately empty.\n */\nimport { RefractError } from \"./errors\";\nimport type { RawTheme } from \"./rawTheme\";\n\nexport function assertRawTheme(value: unknown, source?: string): asserts value is RawTheme {\n const at = source ? ` (${source})` : \"\";\n\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n const got = Array.isArray(value) ? \"an array\" : value === null ? \"null\" : typeof value;\n throw new RefractError(\n \"REFRACT_E_RAW_SHAPE\",\n `Expected a RawTheme object${at}, got ${got}. Pass the raw theme (a module's default export, or a .json raw theme).`,\n );\n }\n\n // The documented mistake: a defineConfig({ raw, targets }) passed where the bare RawTheme was wanted.\n // A RawTheme never has a top-level `targets`; a config always does.\n if (Array.isArray((value as { targets?: unknown }).targets)) {\n throw new RefractError(\n \"REFRACT_E_RAW_SHAPE\",\n `Expected a RawTheme object${at}, but got what looks like a defineConfig({ raw, targets }). Pass its \\`raw\\` (or a module that default-exports the raw theme), not the whole config.`,\n );\n }\n}\n","/**\n * `defineAdapter` — turns an `AdapterSpec` (identity + a `bind` returning the four\n * required primitives) into a full `ThemeAdapter` whose `bind` yields a complete\n * `BoundAdapter` with the DEFAULTED aggregators supplied.\n *\n * The defaults are pure Model walks: the Model enumerates every subsystem and every\n * (group, variant), so core loops it, calls the author's per-unit renderers, and\n * `join`s the results. Model/ctx are already bound, so the aggregators take no args.\n * An author can still override any aggregator (a format whose full document isn't a\n * flat concatenation).\n */\n\nimport type { ThemeModel } from \"./model\";\nimport type {\n AdapterSpec,\n ThemeAdapter,\n BoundAdapter,\n RenderContext,\n UsageDescriptor,\n} from \"./ThemeAdapter\";\n\n/** Every rule-set address in the Model — `(subsystem, group, variant)` triples. */\nfunction eachRuleSet(model: ThemeModel): Array<{ subsystem: string; group: string; variant: string }> {\n const out: Array<{ subsystem: string; group: string; variant: string }> = [];\n for (const [subsystem, sub] of Object.entries(model.subsystems)) {\n for (const [group, ruleSet] of Object.entries(sub.ruleSets ?? {})) {\n for (const variant of Object.keys(ruleSet)) {\n out.push({ subsystem, group, variant });\n }\n }\n }\n return out;\n}\n\n/**\n * Complete an `AdapterSpec` into a `ThemeAdapter`.\n *\n * Wraps the author's `bind` so the returned `BoundAdapter` gains the defaulted\n * aggregators (`renderAllRecipes` / `renderAllVariables` / `renderAll`) built from\n * the required primitives — unless the spec already provides its own override.\n * `name` / `version` pass through unchanged.\n *\n * @param spec identity (`name`/`version`) + a `bind(model, ctx)` returning the\n * required render primitives (and any optional overrides).\n * @returns a full adapter whose `bind(model, ctx)` yields a complete `BoundAdapter`.\n */\nexport function defineAdapter<TUnit>(spec: AdapterSpec<TUnit>): ThemeAdapter<TUnit> {\n return {\n name: spec.name,\n version: spec.version,\n allowedStates: spec.allowedStates,\n bind(model: ThemeModel, ctx: RenderContext): BoundAdapter<TUnit> {\n const b = spec.bind(model, ctx);\n\n const renderAllRecipes =\n b.renderAllRecipes ??\n ((): TUnit =>\n b.join(\n eachRuleSet(model).map(({ subsystem, group, variant }) =>\n b.renderRecipe(subsystem, group, variant),\n ),\n ));\n\n const renderAllVariables =\n b.renderAllVariables ??\n ((): TUnit => b.join(Object.keys(model.subsystems).map(subsystem => b.renderVariables(subsystem))));\n\n const renderAll =\n b.renderAll ?? ((): TUnit => b.join([renderAllVariables(), renderAllRecipes()]));\n\n // Generic self-documentation: the recipe identities are format-correct via `recipeName`; an\n // adapter overrides `describeUsage` to add format-specific import prose to `summary`.\n const describeUsage =\n b.describeUsage ??\n ((): UsageDescriptor => ({\n format: spec.name,\n summary: [`This theme was built with the \"${spec.name}\" refract adapter.`],\n recipes: eachRuleSet(model).map(({ subsystem, group, variant }) => ({\n subsystem,\n group,\n variant,\n name: b.recipeName(subsystem, group, variant),\n })),\n }));\n\n return { ...b, renderAllRecipes, renderAllVariables, renderAll, describeUsage };\n },\n };\n}\n","/**\n * `createNoopAdapter` — the trivial, built-in null adapter (monorepo split, friction 2).\n *\n * `createTheme` requires an `adapter`, but some consumers of the built `Theme` never touch\n * adapter-produced strings — they read only the format-neutral `theme.tokens` / `theme.resolveToken`\n * / `theme.model` (the DTCG export is the canonical example: `toDTCG` walks the flat token map and the\n * breakpoints, never a rendered rule). Those callers need *a* valid adapter purely to satisfy the\n * contract; the output is discarded.\n *\n * Before the split the CLI's `tokens` command reached for `createCssAdapter` as that throwaway builder\n * — which forced a core→adapter dependency (`src/build` importing `src/adapters/css`). The monorepo\n * guiding rule is that the dependency arrow points ONLY into core, so core now ships its own null\n * object: `createNoopAdapter()` emits nothing (empty strings, an empty `emit()`), lets `createTheme`\n * build the Model + token map exactly as any adapter would, and keeps `src/build` free of every\n * adapter package.\n *\n * It's a `ThemeAdapter` like any other (built through {@link defineAdapter}, so it gets the defaulted\n * aggregators for free), just with render primitives that produce empty output.\n */\n\nimport { defineAdapter } from \"./defineAdapter\";\nimport type { ThemeAdapter } from \"./ThemeAdapter\";\n\n/**\n * A no-op adapter: every render primitive returns an empty string and `emit()` writes no files. Use it\n * whenever a `Theme` is needed only for its format-neutral data (`tokens` / `resolveToken` / `model`)\n * and the rendered output is irrelevant — e.g. the `refract tokens` DTCG export.\n */\nexport function createNoopAdapter(): ThemeAdapter<string> {\n return defineAdapter<string>({\n name: \"noop\",\n version: 1,\n bind: () => ({\n recipeName: () => \"\",\n renderRecipe: () => \"\",\n renderVariables: () => \"\",\n join: parts => parts.join(\"\"),\n emit: () => ({ files: {} }),\n }),\n });\n}\n","/**\n * Contrast audit (opt-in) — scores a built theme's colour pairings for **WCAG 2** contrast ratio\n * (the compliance standard) plus an **advisory APCA** Lc reading. It reports; it never mutates the\n * theme and never \"fixes\" a colour. `audit()` returns structured results by default; a caller (or the\n * `refract audit --strict` CLI) can throw on failures.\n *\n * Which pairings: every palette's `base` ↔ `text`, and every recipe's foreground (`color`) ↔\n * background (`background-color` / `background`) across all subsystems' rule-sets (base + state\n * overrides). A side that isn't a derivable colour (`transparent`, a `var()`, a keyword literal) is\n * reported as `skipped`, not a failure.\n *\n * Colour math is inlined here on purpose: `utils.ts` is vendored to consumers (`build/vendor.ts`) and\n * kept dependency-free / minimal, so we don't widen its export surface for a non-vendored sibling. We\n * reuse only the already-exported {@link parseColor}.\n */\nimport type { Theme, Ref } from \"../../core\";\nimport { RefractError } from \"../../core/errors\";\nimport { parseColor, type RGBTuple } from \"./utils\";\n\n// ── WCAG 2.x ──────────────────────────────────────────────────────────────\n// Relative luminance per WCAG 2: linearize each sRGB channel, weight by the luma coefficients.\nconst srgbToLinear = (c: number): number => (c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4));\nconst relLuminance = ([r, g, b]: RGBTuple): number =>\n 0.2126 * srgbToLinear(r / 255) + 0.7152 * srgbToLinear(g / 255) + 0.0722 * srgbToLinear(b / 255);\n\n/** WCAG 2 contrast ratio (1–21) between two sRGB colours; order-independent. */\nconst wcagRatio = (a: RGBTuple, b: RGBTuple): number => {\n const la = relLuminance(a);\n const lb = relLuminance(b);\n const hi = Math.max(la, lb);\n const lo = Math.min(la, lb);\n return (hi + 0.05) / (lo + 0.05);\n};\n\nexport type WcagLevel = \"AAA\" | \"AA\" | \"AA-large\" | \"fail\";\nconst LEVEL_RANK: Record<WcagLevel, number> = { fail: 0, \"AA-large\": 1, AA: 2, AAA: 3 };\n\n/** Map a ratio to a level. For normal text 3–4.5 is \"AA-large\" (passes only at large sizes). */\nconst wcagLevel = (ratio: number, large: boolean): WcagLevel => {\n if (large) return ratio >= 4.5 ? \"AAA\" : ratio >= 3 ? \"AA\" : \"fail\";\n return ratio >= 7 ? \"AAA\" : ratio >= 4.5 ? \"AA\" : ratio >= 3 ? \"AA-large\" : \"fail\";\n};\n\n// ── APCA (advisory) ───────────────────────────────────────────────────────\n// APCA 0.1.9 / formula 0.98G-4g (SAPC). Advisory only — NOT a WCAG substitute — and the draft may\n// still shift, so the constants are pinned here. Returns a signed Lc (polarity-aware).\nconst APCA = {\n mainTRC: 2.4,\n sRco: 0.2126729, sGco: 0.7151522, sBco: 0.072175,\n normBG: 0.56, normTXT: 0.57, revTXT: 0.62, revBG: 0.65,\n blkThrs: 0.022, blkClmp: 1.414,\n scaleBoW: 1.14, loBoWoffset: 0.027,\n scaleWoB: 1.14, loWoBoffset: 0.027,\n deltaYmin: 0.0005, loClip: 0.1,\n} as const;\n\nconst apcaY = ([r, g, b]: RGBTuple): number =>\n APCA.sRco * Math.pow(r / 255, APCA.mainTRC) +\n APCA.sGco * Math.pow(g / 255, APCA.mainTRC) +\n APCA.sBco * Math.pow(b / 255, APCA.mainTRC);\n\n/** Signed APCA lightness contrast (Lc) of `text` over `bg`. Positive = dark-on-light, negative = light-on-dark. */\nconst apcaLc = (text: RGBTuple, bg: RGBTuple): number => {\n const clamp = (y: number): number => (y > APCA.blkThrs ? y : y + Math.pow(APCA.blkThrs - y, APCA.blkClmp));\n const yTxt = clamp(apcaY(text));\n const yBg = clamp(apcaY(bg));\n if (Math.abs(yBg - yTxt) < APCA.deltaYmin) return 0;\n let out: number;\n if (yBg > yTxt) {\n const sapc = (Math.pow(yBg, APCA.normBG) - Math.pow(yTxt, APCA.normTXT)) * APCA.scaleBoW;\n out = sapc < APCA.loClip ? 0 : sapc - APCA.loBoWoffset;\n } else {\n const sapc = (Math.pow(yBg, APCA.revBG) - Math.pow(yTxt, APCA.revTXT)) * APCA.scaleWoB;\n out = sapc > -APCA.loClip ? 0 : sapc + APCA.loWoBoffset;\n }\n return out * 100;\n};\n\n// ── audit ─────────────────────────────────────────────────────────────────\n\nexport type PairingKind = \"palette\" | \"recipe\";\n\nexport interface PairingScore {\n kind: PairingKind;\n /** Human label, e.g. `colors.brand` or `components.buttons.primary (:hover)`. */\n label: string;\n /** Resolved foreground colour string, or `undefined` when it isn't a derivable colour. */\n fg?: string;\n /** Resolved background colour string, or `undefined` when it isn't a derivable colour. */\n bg?: string;\n /** WCAG 2 contrast ratio (1–21, 2 dp). Absent when skipped. */\n wcagRatio?: number;\n /** WCAG level at the configured text size. Absent when skipped. */\n wcagLevel?: WcagLevel;\n /** Advisory APCA Lc (signed, 1 dp). Absent when skipped. */\n apcaLc?: number;\n /** Whether this pairing met the pass bar (`minWcag`). Absent when skipped. */\n pass?: boolean;\n /** Set when a side isn't a derivable colour — then the score fields are absent. */\n skipped?: string;\n}\n\nexport interface AuditOptions {\n /** Throw an aggregated error when any pairing fails, instead of only reporting. Default `false`. */\n strict?: boolean;\n /** Treat the foreground as large text (relaxed WCAG thresholds). Default `false`. */\n largeText?: boolean;\n /** The pass bar. Default `\"AA\"`. `\"AA-large\"` accepts the 3:1 tier. */\n minWcag?: WcagLevel;\n /** Audit component/recipe fg↔bg pairs. Default `true`. */\n includeRecipes?: boolean;\n /** Audit palette base↔text pairs. Default `true`. */\n includePalettes?: boolean;\n}\n\nexport interface AuditResult {\n pairings: PairingScore[];\n summary: {\n total: number;\n passed: number;\n failed: number;\n skipped: number;\n /** The lowest-ratio scored pairing (the worst offender), if any were scored. */\n worst?: PairingScore;\n };\n /** `true` when no scored pairing failed the pass bar. */\n ok: boolean;\n}\n\nconst round = (n: number, dp: number): number => {\n const f = 10 ** dp;\n return Math.round(n * f) / f;\n};\n\n/** Resolve a rule-set declaration `Ref` to a colour string, or `undefined` if it isn't one. */\nconst refToColor = (theme: Theme, ref: Ref): string | undefined => {\n if (ref.ref !== undefined) {\n try {\n return String(theme.resolveToken(ref.ref));\n } catch {\n return undefined;\n }\n }\n if (typeof ref.value === \"string\") return ref.value;\n return undefined;\n};\n\nconst FG_KEY = \"color\";\nconst BG_KEYS = [\"background-color\", \"background\"] as const;\nconst pickBg = (decls: Record<string, Ref> | undefined): Ref | undefined => {\n if (!decls) return undefined;\n for (const k of BG_KEYS) if (decls[k]) return decls[k];\n return undefined;\n};\n\n/** Score one fg/bg pairing (colours already resolved to strings), or a skipped record. */\nconst scorePair = (\n kind: PairingKind,\n label: string,\n fg: string | undefined,\n bg: string | undefined,\n options: Required<Pick<AuditOptions, \"largeText\" | \"minWcag\">>,\n): PairingScore => {\n let fgRgb: RGBTuple | undefined;\n let bgRgb: RGBTuple | undefined;\n try {\n if (fg !== undefined) fgRgb = parseColor(fg).rgb;\n } catch { /* not a derivable colour */ }\n try {\n if (bg !== undefined) bgRgb = parseColor(bg).rgb;\n } catch { /* not a derivable colour */ }\n\n if (!fgRgb || !bgRgb) {\n return { kind, label, fg, bg, skipped: !fgRgb && !bgRgb ? \"no derivable fg/bg\" : !fgRgb ? \"fg not a colour\" : \"bg not a colour\" };\n }\n\n const ratio = wcagRatio(fgRgb, bgRgb);\n const level = wcagLevel(ratio, options.largeText);\n const pass = LEVEL_RANK[level] >= LEVEL_RANK[options.minWcag];\n return {\n kind, label, fg, bg,\n wcagRatio: round(ratio, 2),\n wcagLevel: level,\n apcaLc: round(apcaLc(fgRgb, bgRgb), 1),\n pass,\n };\n};\n\n/**\n * Audit a built theme's colour pairings. Pure — reads `theme.tokens` / `theme.resolveToken` /\n * `theme.model` only. In `strict` mode, throws one aggregated error listing every failing pairing.\n */\nexport const audit = (theme: Theme, options: AuditOptions = {}): AuditResult => {\n const opts = {\n largeText: options.largeText ?? false,\n minWcag: options.minWcag ?? (\"AA\" as WcagLevel),\n };\n const includeRecipes = options.includeRecipes ?? true;\n const includePalettes = options.includePalettes ?? true;\n const pairings: PairingScore[] = [];\n\n // Palettes: base ↔ text. A palette advertises a pairing by having a `colors.<name>.text` token.\n if (includePalettes) {\n for (const path of Object.keys(theme.tokens)) {\n const m = /^colors\\.([^.]+)\\.text$/.exec(path);\n if (!m) continue;\n const base = `colors.${m[1]}`;\n let fg: string | undefined, bg: string | undefined;\n try { fg = String(theme.resolveToken(path)); } catch { /* skip */ }\n try { bg = String(theme.resolveToken(base)); } catch { /* skip */ }\n pairings.push(scorePair(\"palette\", base, fg, bg, opts));\n }\n }\n\n // Recipes: every subsystem's rule-sets — the base declarations + each state/breakpoint override.\n if (includeRecipes) {\n for (const [subsystem, subModel] of Object.entries(theme.model.subsystems)) {\n if (!subModel.ruleSets) continue;\n for (const [group, ruleSetGroup] of Object.entries(subModel.ruleSets)) {\n for (const [variant, ruleSet] of Object.entries(ruleSetGroup)) {\n const baseFg = ruleSet.declarations[FG_KEY];\n const baseBg = pickBg(ruleSet.declarations);\n const label = `${subsystem}.${group}.${variant}`;\n if (baseFg && baseBg) {\n pairings.push(scorePair(\"recipe\", label, refToColor(theme, baseFg), refToColor(theme, baseBg), opts));\n }\n // Overrides (e.g. :hover) can swap bg or fg — score the effective pairing at that condition.\n for (const override of ruleSet.overrides ?? []) {\n const oFg = override.declarations?.[FG_KEY] ?? baseFg;\n const oBg = pickBg(override.declarations) ?? baseBg;\n if (!override.declarations || (!override.declarations[FG_KEY] && !pickBg(override.declarations))) continue;\n if (!oFg || !oBg) continue;\n const cond = override.state ?? override.breakpoint ?? override.query ?? \"override\";\n pairings.push(scorePair(\"recipe\", `${label} (${cond})`, refToColor(theme, oFg), refToColor(theme, oBg), opts));\n }\n }\n }\n }\n }\n\n const scored = pairings.filter(p => !p.skipped);\n const failed = scored.filter(p => p.pass === false);\n const worst = scored.reduce<PairingScore | undefined>(\n (w, p) => (w === undefined || (p.wcagRatio ?? Infinity) < (w.wcagRatio ?? Infinity) ? p : w),\n undefined,\n );\n const result: AuditResult = {\n pairings,\n summary: {\n total: scored.length,\n passed: scored.length - failed.length,\n failed: failed.length,\n skipped: pairings.length - scored.length,\n worst,\n },\n ok: failed.length === 0,\n };\n\n if (options.strict && failed.length > 0) {\n const list = failed.map(p => `${p.label} (${p.wcagRatio}:1, ${p.wcagLevel})`).join(\", \");\n throw new RefractError(\n \"REFRACT_E_AUDIT\",\n `refract audit: ${failed.length} pairing(s) fail WCAG ${opts.minWcag} — ${list}. ` +\n `Adjust the colour(s), lower --min-wcag, or drop --strict to report without failing.`,\n failed.map(p => `${p.label} (${p.wcagRatio}:1, ${p.wcagLevel})`),\n );\n }\n\n return result;\n};\n"],"names":["parseRuleSetReference","reference","subsystem","rest","split","dot","indexOf","group","slice","variant","resolveReference","model","parsed","_c","_a","subsystems","ruleSets","_b","mergeDeclarations","target","source","prop","ref","Object","entries","responsiveKey","o","_d","_e","_f","breakpoint","query","orientation","state","container","size","mergeComponentRuleSet","own","components","RefractError","sources","references","resolved","push","base","states","responsiveByKey","Map","declarations","override","overrides","undefined","key","entry","get","set","responsive","values","seen","Set","referencedPaths","collect","decls","has","add","path","assertRawTheme","value","at","Array","isArray","got","targets","eachRuleSet","out","sub","ruleSet","keys","defineAdapter","spec","name","version","allowedStates","bind","ctx","b","renderAllRecipes","join","map","renderRecipe","renderAllVariables","renderVariables","renderAll","describeUsage","format","summary","recipes","recipeName","createNoopAdapter","parts","emit","files","srgbToLinear","c","Math","pow","relLuminance","r","g","LEVEL_RANK","fail","AA","AAA","APCA","apcaY","apcaLc","text","bg","clamp","y","yTxt","yBg","abs","sapc","round","n","dp","f","refToColor","theme","String","resolveToken","FG_KEY","BG_KEYS","pickBg","k","scorePair","kind","label","fg","options","fgRgb","bgRgb","parseColor","rgb","skipped","ratio","a","la","lb","max","min","wcagRatio","level","large","wcagLevel","largeText","pass","minWcag","audit","opts","includeRecipes","pairings","includePalettes","tokens","m","exec","subModel","ruleSetGroup","baseFg","baseBg","oFg","_g","oBg","_h","cond","_l","_j","_k","scored","filter","p","failed","worst","reduce","w","Infinity","result","total","length","passed","ok","strict","list"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theme-registry/refract",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "The framework-agnostic, format-neutral theme compiler core — build a ThemeModel from a RawTheme, then lower it with any adapter package (CSS, SCSS, JSON, styled-components).",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Petyo Stoyanov",
|
|
@@ -10,7 +10,7 @@ refract's adapter contract is public and stable, so if the shipped adapters (CSS
|
|
|
10
10
|
styled-components, JSON — see **adapter-usage**) don't target your format, you can write one **in
|
|
11
11
|
your own project** — a small standalone npm package or just a local module. You depend only on the
|
|
12
12
|
published `@theme-registry/refract`; you do **not** fork or clone the refract repo. Full contract
|
|
13
|
-
reference: `docs/extending.md
|
|
13
|
+
reference: [`docs/extending.md`](https://github.com/theme-registry/refract/blob/main/docs/extending.md).
|
|
14
14
|
|
|
15
15
|
## The contract
|
|
16
16
|
|
|
@@ -79,7 +79,7 @@ Use it like any adapter: `createTheme(raw, { adapter: createMyAdapter() })`.
|
|
|
79
79
|
- Never import from a relative core path — always the published specifiers
|
|
80
80
|
(`@theme-registry/refract`, `/adapter-kit`, `/color-math`).
|
|
81
81
|
- Adapters are **not** subsystems; you don't register anything on core.
|
|
82
|
-
- Read `docs/extending.md` for the full `ThemeModel` walk and the `emit()` file contract.
|
|
82
|
+
- Read [`docs/extending.md`](https://github.com/theme-registry/refract/blob/main/docs/extending.md) for the full `ThemeModel` walk and the `emit()` file contract.
|
|
83
83
|
|
|
84
84
|
*(Contributing an adapter back into the refract monorepo itself is a different, internal workflow —
|
|
85
85
|
that's the repo's own `adapter-scaffold` contributor skill, not this one.)*
|
|
@@ -70,6 +70,6 @@ Options are passed when constructing the adapter, never as CLI flags. The common
|
|
|
70
70
|
`scheme: "media" | "attribute" | "both"` (dark realization), `helpers: ["color-math"]`,
|
|
71
71
|
`naming`.
|
|
72
72
|
- **SCSS** — `prefix`, `inline`, `indent`, `layer` (same as CSS). **JSON** — minimal; see
|
|
73
|
-
`docs/css-adapter.md` and `docs/authoring.md` for the full tables.
|
|
73
|
+
[`docs/css-adapter.md`](https://github.com/theme-registry/refract/blob/main/docs/css-adapter.md) and [`docs/authoring.md`](https://github.com/theme-registry/refract/blob/main/docs/authoring.md) for the full tables.
|
|
74
74
|
|
|
75
75
|
Cross-format concerns — emit modes, dark-mode strategy, the CLI — live in **build-config**.
|