În acest tutorial vom construi un mixer "logger", care va afișa un jurnal flexibil, informativ ca CSS când Sass este compilat.
Logarea este procesul de înregistrare a acțiunilor de aplicație și de stat la o interfață secundară. - Proiectul Codului
În ziua de azi, eu și cu mine, Reda Lemedan, cu întreținerea Neat, vorbea totul despre Sass și, dintr-o dată, am văzut un interesant amestec al lui:
@ include -neat-warn ("Ceva nu este bine");
L-am întrebat ce face acest amestec și mi-a spus că este în esență un înveliș pentru @a avertiza
directivă de la Sass, care verifică dacă utilizatorul dorește sau nu să tipărească avertismente de la Neat în consola (bazată pe o variabilă globală).
Așa că m-am gândit la mine de ce să te oprești acolo? și a început să se joace cu ideea în aceeași noapte. Ideea mea era să construiesc un ambalaj pentru ambele @a avertiza
și @eroare
(de la Sass 3.4) pentru a ajuta dezvoltatorii de biblioteci și cadre să tipărească diferite tipuri de mesaje (informații, depanare, avertismente, erori ...) și să țină evidența tuturor jurnalelor.
Implementarea mea actuală prevede:
REMEDIERE
, INFO
, A AVERTIZA
, EROARE
și FATAL
);Sa dovedit a fi destul de simplă. Avem nevoie de o variabilă globală care să țină întreaga configurație și de un amestec care să servească ca un înveliș pentru directivele noastre de imprimare a consolei.
Pentru că dorim ca configurația noastră globală să fie personalizabilă (într-o oarecare măsură), vom împacheta declarația într-un mixin. Nu numai că acest lucru este mai convenabil, dar este și mai plăcut pentru utilizatorul final.
Așa că avem un amestec, să-l sunăm logger
care este intenționată să fie numită o singură dată, creând o hartă globală care ține cont de configurația noastră. Apoi avem ambalajul nostru, Buturuga
, care acceptă un nivel de înregistrare (de exemplu A AVERTIZA
sau EROARE
) și mesajul de logare ca argumente. Cam asta e tot.
Pentru a face lucrurile mai convenabile pentru dezvoltatori, vom oferi câteva funcții de stenogramă pentru a înregistra niveluri diferite. De exemplu, în loc să trebuiască să tastați:
@ include jurnal ("ERROR", "Nu este suficient unicorn aici");
… am putea avea:
@ include ERROR ("Nu există unicorn suficient aici");
Deci, veți termina cu un API care arată în felul următor:
// Instantiate un logger // care incepe imprimarea jurnalelor la nivelul "INFO". // Aceasta înseamnă că jurnalele DEBUG nu vor fi afișate. @ include logger ("INFO"); // Înregistrați-vă lucrurile. @ include ERROR ("Nu există unicorn suficient aici");
Vom adăuga, de asemenea, câteva mixuri pentru a aduce unele caracteristici extraordinare:
Să începem cu începutul, nu? Loggerul constructor. Acest lucru ar trebui să accepte un singur parametru: nivelul la care loggerul ar trebui să înceapă să imprime jurnalele în consolă.
Acesta este un model comun pentru sistemele de logare. De exemplu:
EROARE
și FATAL
), ai scrie @ include logger ("ERROR")
.@ include logger ("ALL")
, care este, în principiu, același cu cel mai scăzut nivel de exploatare (REMEDIERE
). @ include logger ("OFF")
.Notă: puteți găsi mai multe informații despre nivelurile de înregistrare în acest thread StackOverflow sau în documentația din jurnalele Apache.
@mixin logger ($ minim-level) // Lista nivelelor disponibile nivele $: "DEBUG", "INFO", "WARN", "ERROR", "FATAL"; // Asigurați-vă că șirul dat este majusculă $ minimum-level: to-big-case ($ minimum-level); // Dacă nivelul este "ALL", du-te cu cel mai mic nivel al tuturor @if $ minimum-level == "ALL" $ minimum-level: nth ($ levels, 1); // Dacă nivelul este nevalid, alegeți arbitrar cu "INFO" @if nu este index ($ levels "OFF", $ minimum-level) $ minimum-level: "INFO"; // Crearea variabilei globale $ logger-configuration: (// Lista nivelelor disponibile niveluri: $ levels, // Lista nivelelor care sunt tipărite cu "eroare" @error ":" FATAL "" ERROR ", / / Nivelul minim (ca un index al "nivelelor $") pentru a imprima "min": index ($ levels, $ minimum-level), // Dacă loggerul este sau nu activat "$ minimum-level! OFF ", // Hartă pentru a urmări istoricul istoricului:" (DEBUG ")," INFO ": ()," WARN ": ()," ERROR ": () ) ) !global;
Codul de mai sus ar trebui să fie în mare măsură explicativ, dar am adăugat câteva comentarii pentru a face totul clar. După cum puteți vedea, acest mixin nu face prea mult decât să creeze o variabilă globală. Nu atât de rău, nu-i așa?
Înainte de a merge mai departe, să creăm o funcție mică de ajutor care ne face ușor să obținem o valoare de pe această hartă globală. Pentru că știi, tastând map-get ($ logger-configuration, ...)
nu este distractiv de la distanță. Ce ziceti logger-conf (...)
in schimb?
@funger logger-conf (cheia $) @return map-get ($ logger-configuration, $ key);
Bine, hai să mergem la realitate Buturuga
care imprimă lucrurile în consola. Nu numai că trebuie să emită mesajele date în consola utilizatorului, ci și să actualizeze istoricul pentru a ține evidența înregistrărilor (care ar putea sau nu să fie utile).
Suna greu. Nu-ți face griji, va fi la fel de netedă ca untul. Știm deja că acest amestec ar trebui să accepte numai doi parametri: nivelul de înregistrare și mesajul.
@mixin jurnal ($ level, $ message) // Asigurați-vă că nivelul este nivel de $ majusculă: la nivel superior (nivel $); // Daca nu este dezactivat, continuati @if logger-conf ("enabled") // Obtineti indexul nivelului curent // De exemplu, 'DEBUG' ar fi '1' $ index-current-level: index (logger-conf "niveluri"), nivelul $); // Dacă '$ level' este nevalid, // arbitrary cade înapoi pe 'INFO' @if nu $ index-current-level $ level: "INFO"; // Actualizați istoricul istoricului de logare @ includeți logger-update-history (nivelul $, mesajul $); // În cele din urmă, tipăriți mesajul în consola // dacă nivelul curent este mai mare sau egal cu nivelul minim. @if $ index-current-level> = logger-conf ("min") $ print: '[' + $ nivel + '] ::' + $ mesaj; // Imprimați-l ca '@error' dacă este un nivel de eroare @if index (logger-conf ("erori"), $ level) @error $ print; // Utilizați altfel '@warn' @else @warn $ print;
Acum, trebuie să ne ocupăm de actualizarea istoriei. Acest lucru este de fapt un pic mai dur, dar odată ce vă obișnuiți să manipulați hărțile, devine mai clar.
Înainte de a privi codul, permiteți-mi să vă explic cum funcționează istoria. Practic, este o hartă în care cheile sunt nivelurile de înregistrare, iar valorile sunt liste de mesaje logate. De exemplu, ați putea avea ceva de genul:
$ _: ("DEBUG": (), "INFO": (), "WARN": (" . ")," FATAL ": ())
Bine. Sa mergem.
@mixin logger-update-history ($ level, $ message) // Obțineți harta istoricului din configurația $ history: logger-conf ("history"); // Obțineți lista de istoric pentru nivelul curent $ current-level-history: map-get (istorie $, nivel $); // Adăugați jurnalul proaspăt în listă $ current-level-history: append ($ current-level-history, $ message); // Creați o variabilă temporară care conține noua hartă a istoricului $ logger-history: hartă-îmbinare ($ history, ($ level: $ current-level-history)); // Actualizați harta istoricului din configurație cu variabila temporară $ logger-configuration: map-merge ($ logger-configuration, (history): $ logger-history)!
Aceasta implică câteva linii neprietenoase, dar când explicați fiecare rând individual, totul are sens în cele din urmă.
Am terminat aici, dar am vorbit despre adăugarea de funcții de stenogramă. Să facem asta acum înainte să uităm:
@mixin FATAL (mesaj $) @ include jurnal ("FATAL", mesaj $); @mixin EROARE ($ mesaj) @ include jurnal ("ERROR", mesaj $); @mixin WARN ($ message) @ include jurnal ("WARN", mesaj $); @mixin INFO ($ mesaj) @ include jurnal ("INFO", mesaj $); @mixin DEBUG ($ message) @ include jurnal ("DEBUG", mesaj $);
Asta e. Un ultim lucru pe care l-am putea face, dar nu este cu adevărat obligatoriu, testează dacă logger
a fost inclusă înainte de a încerca să folosiți harta globală. Nu numai că împiedicăm greșelile stupide, dar putem, de asemenea, face ca instanțiarea loggerului să fie opțională făcând-o în mișcare.
@mixin log ($ level, $ message) // Testați dacă există variabilă globală "logger-configuration". // Dacă nu, înseamnă că "logger" nu a fost inclus, // așa că l-am inclus, setând arbitrar nivelul min la "INFO". dacă nu există variabilă globală ("logger-configuration") @ include logger ("INFO"); dacă logger-conf ("activat") // ...
Vom începe cu primul (și cel mai puțin util) din ambele mixuri extra, ajutătorul. Este într-adevăr un obiect gadget în acest moment, deoarece tot ceea ce face este să imprimați o regulă CSS cu niveluri de logare ca selectori și explicații ca valori.
Acest lucru este intenționat pentru a oferi un ajutor dezvoltatorilor atunci când nu știu cu adevărat ce nivel de logare ar trebui să utilizeze. Ar fi putut fi scris ca un comentariu, dar am vrut să încerc acest lucru helpie printer.
@mixin logger-help // Deschideți un nou "logger-help" selector logger-help OFF: "Dezactivați loggerul"; FATAL: "Erorile grave care provoacă terminarea prematură"; EROARE: "Alte erori de rulare sau condiții neașteptate."; WARN: "Utilizarea API-urilor depreciate, utilizarea necorespunzătoare a API, erorile" aproape "," + "alte situații de execuție care sunt nedorite sau neașteptate, dar nu neapărat greșite."; INFO: "Evenimente interesante de rulare (pornire / oprire)."; DEBUG: "Informații detaliate privind fluxul prin sistem.";
Folosiți-l astfel:
@ include logger-help;
... și se compilează ca:
logger-help OFF: "Dezactivați loggerul"; FATAL: "Erorile grave care provoacă terminarea prematură"; EROARE: "Alte erori de rulare sau condiții neașteptate."; WARN: "Utilizarea API-urilor depreciate, utilizarea necorespunzătoare a API, erorile" aproape ", alte situații de execuție care sunt nedorite sau neașteptate, dar nu neapărat greșite."; INFO: "Evenimente interesante de rulare (pornire / oprire)."; DEBUG: "Informații detaliate privind fluxul prin sistem.";
Nimic special. Celălalt mixin extra este mult mai interesant. Utilizează istoricul pentru a imprima toate jurnalele înregistrate în timpul compilației.
@mixin logger-print-logs // Deschide un nou logger-logs selector logger-logs / Loop peste istorie @ fiecare nivel $, log-in logger-conf ("istorie") nivelul curent de logare din buclă // ar trebui să fie afișat sau nu pe baza nivelului minim // și a lungimii valorii sale (fără jurnal, fără imprimare). @in fișierul logger-conf ("levels"), $ level)> = logger-conf ("min") și lungimea ($ logs)> 0 // Loop peste jurnalele înregistrate și tipăriți-le. @ fiecare $ log în $ logs # $ level: $ log;
Din nou, utilizarea simplă:
@ includeți jurnale de tip logger-print-log;
... care ar produce (pe baza exemplului nostru anterior):
busteni-busteni WARN: "Ar trebui sa fiti atenti la acest lucru."; AVERTISMENT: "Acest lucru ar putea fi îmbunătățit."; EROARE: "Ceva este rupt";
// Instanțiați un nou logger cu "INFO" ca nivel minim pentru înregistrare. // Dacă nu este inclus, se va face automat la primul jurnal. @ include logger ("INFO"); // ajutor logger (opțional, evident) @ include logger-help; // Log stuff @ include INFO ("Hei, uita-te la asta"); @ include INFO ("Aduceți în unicorns!"); @ include WARN ("Dude, fii atent"); // Aceasta nu este imprimată, dar este încă urmărită în jurnale. @ include DEBUG ("Debug și altele"); // Istoricul de ieșire (opțional) util în special pentru depanarea @ include jurnalul logger-print-log;
După cum puteți vedea, codul este destul de ușor în cele din urmă, plus cea mai mare parte a lui în vrac sunt comentarii. Cred că oferă un API frumos curat, ajutând la urmărirea datelor înregistrate în orice proiect dat.
Acesta este un instrument destinat dezvoltatorilor de biblioteci și de cadre. Dacă se întâmplă să fii unul, te rog să faci o încercare dacă crezi că ar putea fi utilă și dă-mi reacția ta.
Simțiți-vă liber să luați mixinul de la GitHub sau să jucați cu el direct pe SassMeister.