Hur man kontrollerar beroenden i Sass-bibliotek

Hittills har jag skrivit sju Sass-bibliotek. De flesta av dem är bara en superset av funktioner som kan inkluderas och sedan användas i dina projekt för att ge dig mer ström än koden.

SassyLists är till exempel en samling funktioner för att manipulera Sass-listor. De hjälper dig att omvända en lista, infoga ett objekt på ett specifikt index, skicka en lista mellan två index och så vidare.

SassyLists kan importeras som Compass Extension, men jag har märkt att ibland utvecklare bara vill använda en mycket specifik funktion från SassyLists så att de kopierar / klistrar in den i sin kodbas. Problemet är att de inte alltid uppmärksammar beroenden (till exempel andra funktioner).

Jag bestämde mig för att börja arbeta med en beredskapskontrollör. Tanken är ganska enkel: varje funktion med beroenden kommer först att köras genom beroendet. om den senare konstaterar att vissa funktioner saknas, varnar det utvecklaren om att funktionen inte kommer att kunna köras korrekt.

Bygga det!

Beroende på kontrollen är en enkel funktion som accepterar ett obegränsat antal argument (obligatoriska funktioner).

 @funktion saknas-beroenden ($ funktioner ...) // Kontrollera efter beroenden

Med detta använder vi funktion-exists () funktion, introducerad i Sass 3.3, som kontrollerar förekomsten av en given funktion i det globala räckviddet.

Notera: Sass 3.3 erbjuder också mixin-exists ()variabel-exists () och global-variabel-exists ().

 @funktion saknar beroenden ($ funktioner ...) @each $ funktion i $ funktioner @if inte funktion-existerar ($ funktion) @return true;  @return false; 

Om en funktion inte av någon anledning finns i räckvidden, då saknade-beroenden avkastning Sann. Om alla funktioner är okej, så finns det inga saknade beroenden så det återkommerfalsk.

Du skulle därför använda den så här:

 // @requires my-function // @requires my-other-function @function dummy () @if saknade beroenden (my-funktion, min-andra-funktionen) @warn "Oj! Missa några funktioner för" dummy '! "; @return null;  // 'dummy'-funktionens kärna, // uppenbarligen att behöva' my-funktion 'och' my-other-function 'för att fungera. 

Så det är ganska coolt.

Pushing saker vidare

Det skulle bli ännu bättre om vi kunde identifiera som funktion saknas, så utvecklaren vet vad man ska göra för att åtgärda problemet. Också, att behöva skriva varningen varje gång är typ av irriterande så att vi kunde flytta det till saknade-beroenden fungera.

Tanken är inte så annorlunda än vad vi tidigare gjort. Skillnaden är att vi nu kommer att lagra namnet på saknade funktioner istället för att direkt återvända. Då, om det saknas funktioner, kommer vi att ge en varning till utvecklaren, och slutligen återvända en booleska som vi gjorde tidigare.

 @funktion saknar beroenden ($ funktioner ...) $ saknar beroenden: (); @each $ funktionen i $ funktioner @if inte funktion-existerar ($ -funktion) $ missing-dependence: append ($ saknade beroenden, $ funktion, komma);  @ längd ($ saknade beroenden)> 0 @warn "Unmet beroenden! Följande funktioner krävs: # $ missing-dependencies.";  @return längd ($ saknade beroenden)! = 0; 

Som du kan se är det inte mycket mer komplicerat än vår tidigare version. Dessutom är sättet att använda det ännu enklare:

 @function dummy () @if missing-dependence (min-funktion, min-andra-funktionen) @return null;  // 'dummy'-funktionens kärna, // uppenbarligen att behöva' my-funktion 'och' my-other-function 'för att fungera. 

Se? Vi kan gräva @varna direktivet, men om det saknas en eller flera funktioner, kommer utvecklaren att bli uppmanad att

Unmet beroenden! Följande funktioner krävs: my-funktion, min-andra-funktionen.

Förhindra beroendet Checker från att vara beroende

Det stora problemet jag kan se med den här funktionen är att du behöver saknade-beroenden fungera! Vid denna tidpunkt är beroendet kontrollen i grunden ett beroende ... Du ser ironi.

Det här är för att saknade beroenden (...) behandlas som en sträng i situationer där saknade-beroenden refererar inte till några funktioner, och en sträng utvärderar alltid till Sann. Så när du gör @if saknade beroenden (...), du gör det effektivt @if sträng, vilket alltid är sant, så kommer du alltid att möta det villkoret.

För att undvika detta finns det ett smart arbete runt. I stället för att helt enkelt göra @if saknade beroenden (...), vi kunde göra @if saknade beroenden (...) == true. I Sass, == är som === på andra språk, vilket betyder att det inte bara kontrollerar värdet utan också typen.

 @function dummy () @if missing-dependence (min-funktion, min-andra-funktionen) == true @return null;  // 'dummy'-funktionens kärna, // uppenbarligen att behöva' my-funktion 'och' my-other-function 'för att fungera. 

Om funktionen inte existerar, så som vi såg tidigare, kommer samtalet att behandlas som en sträng. Medan en sträng utvärderas till Sann, det är inte strikt lika med Sann, för att det är a Sträng typ, inte en Bool typ.

Så vid denna punkt om saknade-beroenden funktionen existerar inte, du matchar inte villkoret, så funktionen kan köras normalt (men krasch om det saknas beroendet någonstans i koden). Vilket är coolt, för att vi bara förbättrar saker utan att bryta dem.

Olika typer av beroende

Ett annat problem med den här funktionen är att den bara kontrollerar saknade funktioner, inte blandningar eller globala variabler. Med detta sagt är detta lätt att göra genom att tweaking av dependency checker-koden.

Vad händer om varje argument passerade till funktionen kan vara en lista med två objekt, med typen av beroende som ett första argument (antingen fungerablanda i eller variabel) och namnet på beroendet som en andra? Till exempel:

saknade beroenden (funktion min-funktion, variabel my-cool-variabel);

Om vi ​​är mer benägna att använda funktioner som beroenden kan vi göra fungera standardvärdet, så att det föregående samtalet skulle se ut så här:

saknade beroenden (my-funktion, variabel min-cool-variabel);

I grund och botten är det som att fråga om huruvida funktionen är my-funktion existerar och variabeln my-cool-variabel existerar, eftersom de behövs för en viss uppgift. Klart hittills?

Låt oss nu gå vidare till koden. Vi kan använda ring upp() funktion, att ringa TYPE - existerar (NAME). Allt annat är bara detsamma som tidigare.

 @funktion saknade beroenden ($ beroenden ...) $ saknade beroenden: (); @each $ beroendet i $ beroenden $ typ: "funktion"; // Standard beroendestyp @if längd ($ beroende) == 2 $ typ: nth ($ beroende, 1); $ typ: om (index ("funktion" "mixin" "variabel", $ typ), $ typ, "funktion"); $ beroendet: nth ($ beroende, 2);  @if inte kalla ("# $ type -existerar", $ beroende) $ missing-dependence: append ($ saknade beroenden, $ beroende, komma);  @ längd ($ saknade beroenden)> 0 @warn "Unmet beroenden! Följande beroenden krävs: # $ missing-dependencies.";  @return $ missing-beroenden! = 0; 

Ganska cool, hej? Detta gör koden något mer komplex, så om du inte kommer att ha olika typer av beroende (vilket inte är fallet med SassyLists), föreslår jag att du håller fast med den första versionen vi såg.

Notera: du kanske vill automatiskt stänga en variabel skriv in global-variabel för att ringa global variabel existerar, eftersom det är troligt att en obligatorisk variabel är en global.

Slutgiltiga tankar

Det är ganska mycket det folk. Självklart är detta inte en daglig Sass-funktion. Men jag tror att i många fall, särskilt när man bygger bibliotek, ramar och tillägg, kan dessa tips komma till nytta. Låt mig veta vad du tycker i kommentarerna!

Medel

  • Spela med det här läget på SassMeister.