@ -7,6 +7,8 @@
* node -- import tsx / esm scripts / theming - census . ts -- only tabs
* node -- import tsx / esm scripts / theming - census . ts -- report # docs / audit / theming /
* node -- import tsx / esm scripts / theming - census . ts -- names # naming grammar ( D - TH . 6 )
* node -- import tsx / esm scripts / theming - census . ts -- residue [ out . tsv ]
* # privates still to adjudicate
*
* WHY . The recipe contract already says every recipe declares its knobs in
* ` lib/recipes/base.ts ` ( recipe - contract § 1 , theming § 6 ) , and the R - 4 . x guards
@ -38,11 +40,19 @@
* structural — EVERY knob of a component whose 0 % is its NATURE and not its
* debt , because it has no contract to write : the signed list is
* ` STRUCTURAL_COMPONENTS ` below .
* Reach = public / ( public + private + global + literal ) . ` system ` , ` exception `
* and ` structural ` are reported but excluded from the ratio on purpose : the
* first is themeable at the system level by design ( recipe - contract § 2 ) , the
* second is a deviation the canon already accepted in writing ( § 3 ) , and the
* third has nothing a theme could name in the first place .
* bridge — ` var(--_{c}-palette-{slot}) ` : the private the THM - 2 palette
* forward WRITES . The recipe reads the mechanism of the
* per - instance palette , not a name of its own .
* channel — ` var(--_{c}-x, fallback) ` where NOBODY declares ` --_{c}-x ` :
* soma or the wrapper writes it per INSTANCE ( a % , a measured
* rect , the size a prop asks for ) . A theme must not reach it .
* Reach = public / ( public + private + global + literal ) . ` system ` ,
* ` exception ` , ` structural ` , ` bridge ` and ` channel ` are reported but excluded
* from the ratio on purpose : the first is themeable at the system level by
* design ( recipe - contract § 2 ) , the second is a deviation the canon already
* accepted in writing ( § 3 ) , the third has nothing a theme could name in the
* first place , and the last two are the two shapes of private the doctrine of
* this axis already adjudicated as NOT debt ( see ` PALETTE_BRIDGE ` below ) .
*
* REPORT . ` --report ` writes the audit under ` docs/audit/theming/ ` : a root
* ` README.md ` with the whole - catalogue view , and one ` {c}.md ` per component
@ -108,7 +118,9 @@ export type KnobClass =
| 'global'
| 'literal'
| 'exception'
| 'structural' ;
| 'structural'
| 'bridge'
| 'channel' ;
export interface Knob {
file : string ;
@ -142,7 +154,11 @@ export interface CensusRow {
exception : number ;
/** Knobs of a component whose 0 % is its nature — `STRUCTURAL_COMPONENTS`. */
structural : number ;
/** public / (public + private + global + literal) — the other three out. */
/** Knobs reading the private the THM-2 palette forward writes — `PALETTE_BRIDGE`. */
bridge : number ;
/** Knobs reading a private nobody declares: soma / the wrapper writes it per instance. */
channel : number ;
/** public / (public + private + global + literal) — the other five out. */
reach : number ;
contractKeys : number ;
hasSize : boolean ;
@ -256,6 +272,70 @@ const STRUCTURAL_COMPONENTS = new Map<string, string>([
]
] ) ;
/ * *
* The two shapes of private this axis ' doctrine already adjudicated as NOT
* debt — read off the EMITTER ' S OUTPUT , never guessed from the name .
*
* The anchor is ` src/uix/eidos/generated/base.css ` : ` generated-css.test.ts `
* keeps it byte - identical to ` renderStaticCss() ` , and ` recipe-css-contract `
* already reads it to assert that every palette recipe emits its forward . So
* the question asked here is « what does the generator WRITE » , not « what does
* this name look like » — and that difference is the whole point : adjudicating
* by name is the blindness this same axis was burned by .
*
* ` bridge ` — the THM - 2 forward ( ` renderRecipePaletteForward ` +
* ` isPaletteSlotToken ` , render - css . ts ) writes ` --_{c}-palette-{slot} ` under
* the presence guard ` [data-{c}]:where([data-color], [data-color-custom]) ` ,
* with the component ' s OWN host default as the fallback . A recipe reading it
* consumes the MECHANISM of the per - instance palette , and it is reachable
* TWICE : through the shared ` --palette-* ` layer and through the component ' s
* own tone tokens ( ` --card-neutral-track ` ) — both public . A public on top
* would let a theme PIN it and kill the ` color= ` of every instance in
* silence ; that is written , measured , in the § 5 verdicts of ` card ` ,
* ` tags-input ` and ` avatar ` .
* The test is the forward LINE , not a name shaped like one : only
* ` --_{c}-palette-{slot}: var(--palette-{slot}, …) ` counts , so a
* ` --_c-palette-shadow ` nobody forwards stays residue ( same discipline as
* ` isPaletteSlotToken ` , which matches the slot const and not a loose regex ) .
*
* ` channel ` — the value channel : a private the recipe READS and NOBODY
* declares , neither the component ' s CSS nor the generator . Soma or the
* wrapper writes it per INSTANCE ( ` --_progress-value-pct ` ,
* ` --_dialog-content-width-override ` , ` --_chronos-event-accent ` ) . A theme
* must not reach it : pinning it breaks the behaviour , which is why ` tabs `
* refused its § 4.1 proposal in writing . Measured 2026 - 08 - 25 : all 29 names in
* this class have a writer in a wrapper ( ` *.svelte ` ) or in soma .
*
* Both leave the ratio ' s DENOMINATOR , exactly like ` system ` and ` structural ` ;
* their knobs are still counted and still listed . A private that is NEITHER
* stays ` private ` : the RESIDUE this signature deliberately leaves to be
* adjudicated key by key ( ` --residue ` ) .
* /
const GENERATED_CSS = readFileSync ( resolve ( 'src/uix/eidos/generated/base.css' ) , 'utf8' ) . replace (
/\r\n/g ,
'\n'
) ;
/** `--_{c}-palette-{slot}` AS THE FORWARD EMITS IT — the bridge, verbatim. */
const PALETTE_BRIDGE = new Set (
[
. . . GENERATED_CSS . matchAll (
/(--_[a-z0-9-]+-palette-([a-z-]+))\s*:\s*var\(\s*--palette-\2\s*[,)]/g
)
] . map ( ( m ) = > m [ 1 ] )
) ;
/ * *
* Every private the GENERATOR declares — recipe keys , palette forwards and the
* gradient - finish ramp ( ` --_{c}-fill-finish ` ) . A private in here is written by
* the build , so it is NOT a runtime channel however undeclared the CSS leaves
* it : without this test the four gradient - finish knobs read as « written by
* soma » , which is the wrong reason for the right answer .
* /
const GENERATED_PRIVATES = new Set (
[ . . . GENERATED_CSS . matchAll ( /(?<=^\s*|;\s*)(--_[a-z0-9-]+)\s*:/gm ) ] . map ( ( m ) = > m [ 1 ] )
) ;
function classify (
value : string ,
pubNeedle : string ,
@ -343,6 +423,8 @@ export function scanComponent(dir: string): Scan | null {
literal : 0 ,
exception : 0 ,
structural : 0 ,
bridge : 0 ,
channel : 0 ,
reach : 0 ,
contractKeys : contractKeysFor ( dir ) ,
hasSize : false
@ -477,8 +559,32 @@ export function scanComponent(dir: string): Scan | null {
k . klass = 'public' ;
}
// ── Third pass: the palette BRIDGE and the value CHANNEL ──
// The two shapes of private the doctrine adjudicated as not-debt, decided by
// what the GENERATOR writes (see `PALETTE_BRIDGE`). `every`, not `some`: a
// knob mixing a bridge with anything else stays residue, because the
// anything else is precisely what still needs adjudicating. A FOREIGN
// private (another component's `--_x-…`) can be a bridge — the forward is
// the same mechanism wherever it is emitted — but never a channel: this
// component's CSS is not where it would be declared.
const own = '--_' + dir + '-' ;
for ( const k of knobs ) {
if ( k . klass !== 'private' ) continue ;
const refs = [ . . . k . value . matchAll ( /var\(\s*(--_[a-z0-9-]+)/g ) ] . map ( ( m ) = > m [ 1 ] ) ;
if ( refs . length === 0 ) continue ;
const klass : KnobClass | null = refs . every ( ( r ) = > PALETTE_BRIDGE . has ( r ) )
? 'bridge'
: refs . every ( ( r ) = > r . startsWith ( own ) && ! declBySource . has ( r ) && ! GENERATED_PRIVATES . has ( r ) )
? 'channel'
: null ;
if ( klass === null ) continue ;
row . private -- ;
row [ klass ] ++ ;
k . klass = klass ;
}
const themeable = row . public + row . private + row . global + row . literal ;
row . knobs = themeable + row . system + row . structural ;
row . knobs = themeable + row . system + row . structural + row . bridge + row . channel ;
row . reach = themeable === 0 ? 1 : row.public / themeable ;
const declared = new Set ( privates . map ( ( p ) = > p . name ) ) ;
const privatesFromContract = [ . . . usedPrivates ]
@ -671,6 +777,106 @@ function reportDebt(only?: string, asJson = false) {
console . log ( ' the ledger matches the CSS exactly.' ) ;
}
// ─── `--residue`: the privates that are NEITHER bridge NOR channel ───────────
/ * *
* What the two mechanical signatures deliberately did NOT decide .
*
* The bridge and the channel are adjudicated by measurement ; everything else
* that reads a private without deriving from a public is a per - KEY question —
* a switch whose branches are the identity of a variant ( ` toolbar ` ) , a
* conmutador the TSC feeds ( ` avatar ` ) , a private that reads a raw global in
* one branch ( ` proof-of-human ` ) . Each row carries the knob AND where every
* private it reads is declared , with the class of each declaration , because
* that is the whole material the adjudication needs .
*
* It is a REPORT , not a gate : the per - key ratchet for this class is the piece
* this file does not yet have ( the hole named in the header of
* ` theming-census-debt.ts ` and in recipe - contract § 4 ) .
* /
export interface ResidueRow {
component : string ;
file : string ;
line : number ;
selector : string ;
prop : string ;
value : string ;
/** One entry per private read: `--_x → file:line class | file:line class`. */
sources : string [ ] ;
}
export function residue ( only? : string ) : ResidueRow [ ] {
const out : ResidueRow [ ] = [ ] ;
for ( const dir of [ . . . readdirSync ( ROOT ) ] . sort ( ) ) {
if ( only && dir !== only ) continue ;
const scan = scanComponent ( dir ) ;
if ( ! scan ) continue ;
for ( const k of scan . knobs ) {
if ( k . klass !== 'private' ) continue ;
const refs = [ . . . new Set ( [ . . . k . value . matchAll ( /var\(\s*(--_[a-z0-9-]+)/g ) ] . map ( ( m ) = > m [ 1 ] ) ) ] ;
out . push ( {
component : dir ,
file : k.file ,
line : k.line ,
selector : k.selector ,
prop : k.prop ,
value : k.value ,
sources : refs.map ( ( r ) = > {
const decls = scan . privates . filter ( ( p ) = > p . name === r ) ;
if ( decls . length > 0 )
return r + ' → ' + decls . map ( ( d ) = > ` ${ d . file } : ${ d . line } ${ d . source } ` ) . join ( ' | ' ) ;
return r + ' → ' + ( GENERATED_PRIVATES . has ( r ) ? 'generated/base.css' : 'undeclared' ) ;
} )
} ) ;
}
}
return out ;
}
function reportResidue ( only? : string , out? : string , asJson = false ) {
const rows = residue ( only ) ;
if ( asJson ) {
process . stdout . write ( JSON . stringify ( rows , null , '\t' ) + '\n' ) ;
return ;
}
const per = new Map < string , number > ( ) ;
for ( const r of rows ) per . set ( r . component , ( per . get ( r . component ) ? ? 0 ) + 1 ) ;
const tsv =
[ 'component' , 'file:line' , 'selector' , 'property' , 'value' , 'sources' ] . join ( '\t' ) +
'\n' +
rows
. map ( ( r ) = >
[
r . component ,
` ${ r . file } : ${ r . line } ` ,
r . selector ,
r . prop ,
r . value ,
r . sources . join ( ' ;; ' )
] . join ( '\t' )
)
. join ( '\n' ) +
'\n' ;
console . log (
` theming-census --residue — ${ rows . length } private knob(s) in ${ per . size } component(s): ` +
'neither the palette bridge nor a value channel, so each one is a decision.'
) ;
console . log (
' worst: ' +
[ . . . per . entries ( ) ]
. sort ( ( a , b ) = > b [ 1 ] - a [ 1 ] )
. slice ( 0 , 12 )
. map ( ( [ c , n ] ) = > ` ${ c } : ${ n } ` )
. join ( ' ' )
) ;
if ( out ) {
writeFileSync ( resolve ( out ) , tsv , 'utf8' ) ;
console . log ( ` wrote ${ out } ` ) ;
return ;
}
process . stdout . write ( '\n' + tsv ) ;
}
// ─── The proposal — derived from doctrine, never invented ────────────────────
/ * *
@ -1007,8 +1213,18 @@ function proposalSection(scan: Scan): string {
const c = scan . row . component ;
// `structural` out with `public` and `system`: proposing a token for a knob
// whose §5 verdict says there is no contract to write would be inventing debt.
// `bridge` and `channel` out for the same reason, one floor down: a public
// over the palette forward or over a value channel is a token a theme could
// PIN, and pinning it kills the per-instance `color=` / the behaviour. The
// sheets of `card`, `tags-input` and `tabs` had to refuse exactly that
// proposal by hand — the classifier must not keep making it.
const targets = scan . knobs . filter (
( k ) = > k . klass !== 'public' && k . klass !== 'system' && k . klass !== 'structural'
( k ) = >
k . klass !== 'public' &&
k . klass !== 'system' &&
k . klass !== 'structural' &&
k . klass !== 'bridge' &&
k . klass !== 'channel'
) ;
if ( targets . length === 0 )
return STRUCTURAL_COMPONENTS . has ( c )
@ -1256,7 +1472,7 @@ function sheet(scan: Scan, today: string, verdict: string): string {
? 'ESTRUCTURAL: sin denominador que medir, y eso es la respuesta'
: ` ${ row . public } de ${ themeable } knobs por token público `
}
- * * Knobs de apariencia * * : $ { row . knobs } — p ú blico $ { row . public } · privado $ { row . private } · global $ { row . global } · literal $ { row . literal } · sistema $ { row . system } · excepci ó n $ { row . exception } · estructural $ { row . structural } _ ( los tres ú ltimos , fuera del ratio ) _
- * * Knobs de apariencia * * : $ { row . knobs } — p ú blico $ { row . public } · privado $ { row . private } · global $ { row . global } · literal $ { row . literal } · sistema $ { row . system } · excepci ó n $ { row . exception } · estructural $ { row . structural } · puente $ { row . bridge } · canal $ { row . channel } _ ( los cinco ú ltimos , fuera del ratio ) _
- * * Contrato hoy * * ( \ ` lib/recipes/base.ts \` ): ${ contractLine }
- * * Eje \ ` size \` **: ${ row . hasSize ? 'sí' : 'no' } · **ficheros**: ${ list ( scan . files ) }
@ -1266,7 +1482,11 @@ function sheet(scan: Scan, today: string, verdict: string): string {
$ { knobTable ( by ( 'global' ) , c ) }
# # # 1.2 A trav é s de un privado ( $ { by ( 'private' ) . length } )
$ {
row . bridge + row . channel > 0
? '\nSólo el **residuo**: el puente de paleta (§2-ter) y el canal de valor\n(§2-quater) salen aparte, porque no son deuda ni tienen nombre que acuñar.\n'
: ''
}
$ { knobTable ( by ( 'private' ) , c ) }
# # # 1.3 Literales ( $ { by ( 'literal' ) . length } )
@ -1295,6 +1515,33 @@ lean, **no** para acuñarlos.
$ { knobTable ( by ( 'structural' ) , c ) } `
: ''
} $ {
row . bridge > 0
? `
# # 2 - ter . Puente de paleta THM - 2 ( $ { row . bridge } ) — fuera del ratio
La receta lee \ ` var(--_ ${ c } -palette-{slot}) \` , que **lo escribe el forward** de la
cascada de paleta bajo \ ` [data- ${ c } ]:where([data-color], [data-color-custom]) \`
( \ ` renderRecipePaletteForward \` , firma B′ ). Es el MECANISMO de la paleta por
instancia , y se alcanza * * dos veces * * : por la capa compartida \ ` --palette-* \` y
por los tonos p ú blicos del propio componente . * * No se acu ñ a * * : un p ú blico
encima dejar í a que un tema lo fijara y matara en silencio el \ ` color= \` de cada
instancia ( veredictos § 5 de \ ` card \` , \` tags-input \` , \` avatar \` ).
$ { knobTable ( by ( 'bridge' ) , c ) } `
: ''
} $ {
row . channel > 0
? `
# # 2 - quater . Canal de valor ( $ { row . channel } ) — fuera del ratio
La receta lee un privado que * * nadie declara * * — ni su CSS ni el generador : lo
escribe soma o el envoltorio * * por instancia * * ( un % , un rect medido , la talla
que pide una prop ) . Un tema no debe alcanzarlo : fijarlo rompe el
comportamiento , y por eso \ ` tabs \` rechazó por escrito esa misma propuesta.
$ { knobTable ( by ( 'channel' ) , c ) } `
: ''
}
# # 3 . Privados de la receta — ¿ de d ó nde sale su valor ?
@ -1331,6 +1578,8 @@ function rootReadme(scans: Scan[], empties: EmptyScan[], today: string, verdict:
const noContract = rows
. filter ( ( r ) = > r . contractKeys === 0 && ! STRUCTURAL_COMPONENTS . has ( r . component ) )
. map ( ( r ) = > r . component ) ;
const bridgeRows = rows . filter ( ( r ) = > r . bridge > 0 ) . sort ( ( a , b ) = > b . bridge - a . bridge ) ;
const channelRows = rows . filter ( ( r ) = > r . channel > 0 ) . sort ( ( a , b ) = > b . channel - a . channel ) ;
const worst = [ . . . rows ]
. map ( ( r ) = > ( { c : r.component , out : r.private + r . global + r . literal , r } ) )
. sort ( ( a , b ) = > b . out - a . out )
@ -1349,7 +1598,7 @@ function rootReadme(scans: Scan[], empties: EmptyScan[], today: string, verdict:
- * * Medido * * : $ { today } · * * $ { rows . length } recetas * * con CSS + * * $ { empties . length } componentes sin receta * * = $ { rows . length + empties . length } fichas , el á rbol entero de \ ` eidos/components/ \`
- * * La pregunta * * : ¿ cu á nto de la apariencia de cada componente puede cambiar un tema * * sin tocar el sistema ni la receta * * ?
- * * Alcance global * * : * * $ { pct ( sum ( 'public' ) , themeable ) } * * — $ { sum ( 'public' ) } de $ { themeable } knobs pasan por un token p ú blico del componente
- * * Reparto * * : p ú blico $ { sum ( 'public' ) } · privado $ { sum ( 'private' ) } · global $ { sum ( 'global' ) } · literal $ { sum ( 'literal' ) } · sistema transversal $ { sum ( 'system' ) } · excepci ó n firmada $ { sum ( 'exception' ) } · estructural $ { sum ( 'structural' ) } _ ( los tres ú ltimos , fuera del ratio ) _
- * * Reparto * * : p ú blico $ { sum ( 'public' ) } · privado $ { sum ( 'private' ) } · global $ { sum ( 'global' ) } · literal $ { sum ( 'literal' ) } · sistema transversal $ { sum ( 'system' ) } · excepci ó n firmada $ { sum ( 'exception' ) } · estructural $ { sum ( 'structural' ) } · puente de paleta $ { sum ( 'bridge' ) } · canal de valor $ { sum ( 'channel' ) } _ ( los cinco ú ltimos , fuera del ratio ) _
- * * Sin token p ú blico propio * * : $ { noContract . length } · * * alcance < 20 % * * : $ { rows . filter ( ( r ) = > r . reach < 0.2 ) . length } · * * alcance 100 % * * : $ { rows . filter ( ( r ) = > r . reach === 1 && r . public > 0 ) . length } · * * con eje \ ` size \` **: ${ rows . filter ( ( r ) = > r . hasSize ) . length } · **estructurales**: ${ structural . length }
# # C ó mo se lee
@ -1363,11 +1612,17 @@ function rootReadme(scans: Scan[], empties: EmptyScan[], today: string, verdict:
| \ ` system \` | sistemas transversales que la receta CONSUME por contrato (capa de estado, anillo de foco, planos de depth, motion, bandas z, opacidad, shape, floating-gap) | sí, **a nivel de sistema**, por diseño (recipe-contract §2) — fuera del ratio |
| \ ` exception \` | un literal con su anotación \` /* literal: <razón> */ \` en la propia declaración | no hace falta: es la válvula de recipe-contract §3, una desviación ya firmada — fuera del ratio |
| \ ` structural \` | **todos** los knobs de un componente cuyo 0 % es su NATURALEZA y no su deuda: no hay contrato que escribir (lista firmada abajo) | no hace falta: no hay superficie que un tema pueda nombrar — fuera del ratio, y su fila lee \` strct \` , no \` 0 % \` |
| \ ` bridge \` | \` var(--_{c}-palette-{slot}) \` : el privado que **escribe el forward** de la cascada de paleta (THM-2) | sí, **por la paleta** — y también por los tonos públicos del componente; acuñar encima mataría el \` color= \` por instancia — fuera del ratio |
| \ ` channel \` | \` var(--_{c}-x, fallback) \` que **nadie declara**: lo escribe soma o el envoltorio por INSTANCIA (un %, un rect medido, la talla de una prop) | **no debe**: fijarlo desde un tema rompe el comportamiento — fuera del ratio |
* * Alcance * * = \ ` public / (public + private + global + literal) \` . \` system \` ,
\ ` exception \` y \` structural \` quedan fuera del denominador: el primero es
tematizable a nivel de sistema por dise ñ o , el segundo es una desviaci ó n que el
canon ya acept ó por escrito , y el tercero no tiene nada que un tema pueda nombrar .
\ ` exception \` , \` structural \` , \` bridge \` y \` channel \` quedan fuera del denominador: el
primero es tematizable a nivel de sistema por dise ñ o , el segundo es una
desviaci ó n que el canon ya acept ó por escrito , el tercero no tiene nada que un
tema pueda nombrar , y los dos ú ltimos son las dos formas de privado que la
doctrina de este eje ya adjudic ó como NO deuda — el mecanismo de la paleta y el
valor de runtime . Lo que queda en \ ` private \` es el **residuo**: se adjudica clave
por clave ( \ ` theming-census.ts --residue \` ).
* * L í mites de la medida * * ( regex sobre el CSS ; sobre - reporta , nunca infra - reporta ) :
una declaraci ó n con varios tokens se clasifica por la primera clase que casa
@ -1389,6 +1644,28 @@ sólo salen del **denominador**, igual que \`system\`. La lista firmada vive en
$ { structural . map ( ( r ) = > ` - [ \` ${ r . component } \` ](./ ${ r . component } .md) ( ${ r . structural } ): ${ STRUCTURAL_COMPONENTS . get ( r . component ) } ` ) . join ( '\n' ) }
# # Puente de paleta ( $ { sum ( 'bridge' ) } knobs ) y canal de valor ( $ { sum ( 'channel' ) } ) — privados que NO son deuda
Las dos formas de privado que la doctrina de este eje ya adjudic ó , y que ahora
se distinguen * * mec á nicamente * * — medidas contra el emisor , no adivinadas por el
nombre . La fuente es la SALIDA del generador ( \ ` src/uix/eidos/generated/base.css \` ,
que \ ` generated-css.test.ts \` mantiene idéntica a \` renderStaticCss() \` ):
- * * puente * * — el nombre aparece en la CSS generada como la l í nea del forward
\ ` --_{c}-palette-{slot}: var(--palette-{slot}, …) \` . Un nombre con forma de
puente que nadie reenv í a * * no cuenta * * .
- * * canal * * — el privado no lo declara nadie : ni la CSS del componente ni el
generador . Lo escribe soma o el envoltorio por instancia .
* * Puente * * ( $ { bridgeRows . length } ) : $ { bridgeRows . map ( ( r ) = > ` [ \` ${ r . component } \` ](./ ${ r . component } .md) ${ r . bridge } ` ) . join ( ' · ' ) }
* * Canal * * ( $ { channelRows . length } ) : $ { channelRows . map ( ( r ) = > ` [ \` ${ r . component } \` ](./ ${ r . component } .md) ${ r . channel } ` ) . join ( ' · ' ) }
Lo que NO cae en ninguna de las dos es el * * residuo * * ( $ { sum ( 'private' ) } knobs en $ { rows . filter ( ( r ) = > r . private > 0 ) . length } componentes ) :
conmutadores por variante , privados que leen un global en una rama , escaleras
por talla sin p ú blico detr á s . Se adjudican clave a clave — \ ` theming-census.ts
-- residue \ ` los vuelca con las fuentes de cada declaración.
# # Qu é NO propone una ficha
La propuesta deriva nombres de la doctrina ; * * no la contradice * * . Por eso una
@ -1438,12 +1715,12 @@ ${noContract.map((c) => `[\`${c}\`](./${c}.md)`).join(' · ')}
La columna « contrato » cuenta las claves * * p ú blicas * * del bloque del componente .
| componente | alcance | knobs | p ú blico | privado | global | literal | sistema | estructural | contrato | size |
| -- - | -- - : | -- - : | -- - : | -- - : | -- - : | -- - : | -- - : | -- - : | -- - : | :- : |
| componente | alcance | knobs | p ú blico | privado | global | literal | sistema | estructural | puente | canal | contrato | size |
| -- - | -- - : | -- - : | -- - : | -- - : | -- - : | -- - : | -- - : | -- - : | -- - : | --- : | -- - : | :- : |
$ { sorted
. map (
( r ) = >
` | [ ${ r . component } ](./ ${ r . component } .md) | ${ reachOf ( r ) } | ${ r . knobs } | ${ r . public } | ${ r . private } | ${ r . global } | ${ r . literal } | ${ r . system } | ${ r . structural } | ${ r . contractKeys} | ${ r . hasSize ? 'y' : '– ' } | `
` | [ ${ r . component } ](./ ${ r . component } .md) | ${ reachOf ( r ) } | ${ r . knobs } | ${ r . public } | ${ r . private } | ${ r . global } | ${ r . literal } | ${ r . system } | ${ r . structural } | ${ r . bridge} | ${ r . channel } | ${ r . contractKeys} | ${ r . hasSize ? 'y' : '– ' } | `
)
. join ( '\n' ) }
@ -1892,6 +2169,11 @@ function main() {
else reportDebt ( only , args . includes ( '--json' ) ) ;
return ;
}
if ( args . includes ( '--residue' ) ) {
const next = args [ args . indexOf ( '--residue' ) + 1 ] ;
reportResidue ( only , next && ! next . startsWith ( '--' ) ? next : undefined , args . includes ( '--json' ) ) ;
return ;
}
if ( args . includes ( '--report' ) ) {
writeReport ( ) ;
return ;
@ -1905,7 +2187,7 @@ function main() {
const themeable = sum ( 'public' ) + sum ( 'private' ) + sum ( 'global' ) + sum ( 'literal' ) ;
console . log ( ` theming-census — ${ rows . length } component recipe(s) ` ) ;
console . log (
` appearance knobs ${ sum ( 'knobs' ) } · public ${ sum ( 'public' ) } ( ${ pct ( sum ( 'public' ) , themeable ) } reach) · private ${ sum ( 'private' ) } · global ${ sum ( 'global' ) } · literal ${ sum ( 'literal' ) } · system ${ sum ( 'system' ) } · exception ${ sum ( 'exception' ) } · structural ${ sum ( 'structural' ) } `
` appearance knobs ${ sum ( 'knobs' ) } · public ${ sum ( 'public' ) } ( ${ pct ( sum ( 'public' ) , themeable ) } reach) · private ${ sum ( 'private' ) } · global ${ sum ( 'global' ) } · literal ${ sum ( 'literal' ) } · system ${ sum ( 'system' ) } · exception ${ sum ( 'exception' ) } · structural ${ sum ( 'structural' ) } · bridge ${ sum ( 'bridge' ) } · channel ${ sum ( 'channel' ) } `
) ;
console . log (
` no contract entry: ${ rows . filter ( ( r ) = > r . contractKeys === 0 && ! STRUCTURAL_COMPONENTS . has ( r . component ) ) . length } · reach < 20%: ${ rows . filter ( ( r ) = > r . reach < 0.2 ) . length } · reach = 100%: ${ rows . filter ( ( r ) = > r . reach === 1 && r . public > 0 ) . length } · with data-size: ${ rows . filter ( ( r ) = > r . hasSize ) . length } · structural: ${ rows . filter ( ( r ) = > STRUCTURAL_COMPONENTS . has ( r . component ) ) . length } `
@ -1928,6 +2210,8 @@ function main() {
'excep' . padStart ( 7 ) +
'system' . padStart ( 8 ) +
'strct' . padStart ( 7 ) +
'bridge' . padStart ( 8 ) +
'chan' . padStart ( 6 ) +
'contract' . padStart ( 10 ) +
' size'
) ;
@ -1943,6 +2227,8 @@ function main() {
String ( r . exception ) . padStart ( 7 ) +
String ( r . system ) . padStart ( 8 ) +
String ( r . structural ) . padStart ( 7 ) +
String ( r . bridge ) . padStart ( 8 ) +
String ( r . channel ) . padStart ( 6 ) +
String ( r . contractKeys ) . padStart ( 10 ) +
( r . hasSize ? ' y' : ' -' )
) ;