PostCSS Deep Dive Creați-vă propriul Plugin

Așa cum sunt sigur că ați adunat bine și cu adevărat în acest punct, ceea ce face ca PostCSS să fie uimitor este ecosistemul plugin-ului său înfloritor. Și un motiv foarte mare există atât de multe plugin-uri mari, cu mai multe care ies tot timpul, este că PostCSS face crearea plugin-ului dvs. atât de accesibile pentru oricine care are o experiență cu JavaScript.

Nu aveți nevoie de o permisiune specială pentru a crea un plugin PostCSS; dacă vrei să faci una, trebuie doar să mergi înainte și să o faci. Prin această libertate aveți abilitatea de a vă transforma procesele de dezvoltare CSS în orice doriți să fie, fără să mai vorbim de posibilitatea de a vă împărtăși munca cu alți membri ai comunității PostCSS în creștere rapidă.

În acest tutorial veți învăța cum să creați un plug-in de bază propriu pentru PostCSS. Nu vom trece prea mult în pluginul API și nu vom folosi nici o codare super hardcore. Eu însumi sunt un dezvoltator de front-end și abilitățile mele de JavaScript sunt la nivelul pe care l-ați aștepta să fie pentru o persoană din front-end, dar asta nu ma oprit să fac primul plugin PostCSS în doar câteva ore.

Urmăriți-vă de-a lungul timpului și vedeți-vă cât de ușor poate fi dezvoltarea pluginului PostCSS!

Ce vom construi

Vom crea un plugin care să permită introducerea ușoară a stivei de fonturi familie de fonturi declarații prin următoarea sintaxă:

h1 font-family: "Open Sans", fontstack ("Arial"); 

După compilare, codul de mai sus se va transforma în:

h1 font-family: "Open Sans", Arial, "Helvetica Neue", Helvetica, sans-serif; 

Creați un proiect pentru a lucra în interior

Chiar dacă creați propriul plugin, va trebui în continuare să începeți prin crearea unui proiect Gulp sau Grunt gol. Veți încărca pluginul în acest proiect în același mod în care ați folosit pluginurile altor persoane în această serie.

Puteți citi despre cum să configurați proiecte Gulp sau Grunt pentru PostCSS în tutorialele anterioare:

  • PostCSS Ghid de pornire rapidă: Configurare Gulp
  • PostCSS Ghid de pornire rapidă: Configurarea gruntului

Dacă nu doriți să configurați manual proiectul de la zero, puteți descărca fișierele sursă atașate acestui tutorial și extrageți proiectul Gulp sau Grunt oferit în cadrul unui proiect gol. Apoi, cu un terminal sau un prompt de comandă indicat în dosar, executați comanda npm install.

Creați un Shell Plugin de bază

Creați un dosar în "node_modules" numit "postcss-myplugin". Este comună utilizarea prefixului postcss- pentru a clarifica pluginul dvs. pentru PostCSS.

Toate pluginurile PostCSS sunt module de noduri, deci va trebui să transformăm noul folder într-unul. Deschideți un terminal / comandă, îndreptată spre dosarul nou creat și executați npm init. Acest lucru va efectua configurarea de bază a unui modul nod, deci pur și simplu urmați instrucțiunile care apar în terminalul dvs., lăsând câmpul "punct de intrare" ca "index.js" implicit..

După ce se termină acest lucru, cu terminalul încă indicat spre dosar, executați comanda npm instalare postcss - salvează. Acest lucru va instala PostCSS ca o dependenta pentru acest modul, ceea ce trebuie sa faca toate pluginurile PostCSS.

Creați un fișier numit "index.js" în directorul "postcss-myplugin". Adăugați acest cod pentru a încărca modulul postcss principal:

var postcss = necesită ("postcss");

Apoi, adăugați mai jos acest pachet de bază care va înconjura codul de procesare a pluginului nostru:

var postcss = necesită ("postcss"); module.exports = postcss.plugin ('myplugin', funcția myplugin (opțiuni) return (css) opțiuni = opțiuni || ; // codul de procesare va fi adăugat aici);

Încărcați noul plugin

Acum suntem gata să încărcăm noul plugin creat în proiectul tău. Nu va face nimic încă, dar vrem doar să realizăm configurația esențială.

Încărcați Plugin-ul prin Gulp

Dacă utilizați Gulp, adăugați această variabilă sub cea care există deja în fișier:

var myplugin = necesită ('postcss-myplugin');

Acum, adăugați noul nume de variabilă în dvs. procesoare matrice:

 var procesoare = [myplugin];

Faceți un test rapid că totul funcționează prin rularea comenzii gulp css și verificarea faptului că un nou fișier "style.css" a apărut în folderul "dest" al proiectului.

Încărcați Pluginul prin Grunt

Dacă utilizați Grunt, actualizați procesoare obiect, care este imbricat sub Opțiuni obiect, la următoarele:

 procesoare: [necesită ('postcss-myplugin') ()]

Faceți un test rapid că totul funcționează prin rularea comenzii zgâria postcss și verificarea faptului că un nou fișier "style.css" a apărut în folderul "dest" al proiectului.

Adăugați funcția Plugin

Adăugați Test CSS

Înainte de a începe să adăugăm codul de procesare în plugin-ul nostru, vom adăuga un cod de test în foaia de stil pe care plugin-ul poate lucra.

În fișierul "src / style.css" adăugați acest CSS:

h1 font-family: "Open Sans", fontstack ("Arial"); 

Chiar acum, pentru că plugin-ul nostru nu face nimic încă, dacă compilați CSS, veți vedea exact același cod copiat direct în fișierul "style.css" al dosarului "dest"..

Bucle prin reguli și declarații

Acum, vrem să începem să scanăm CSS-ul fișierului nostru, astfel încât să putem găsi orice instanță fontstack () și le procesează. Pentru a începe acest lucru, adăugați următorul cod după opțiuni = opțiuni || ; linia:

 css.walkRules (funcție (regulă) rule.walkDecls (funcție (decl, i) ););

Folosind WalkRules () în prima linie se iterează prin fiecare regulă din CSS; o regulă este, în principiu, selectorul dvs. și stilurile pe care le-ați setat între acoladele lui. În testul nostru CSS ar fi o regulă:

h1 font-family: "Open Sans", fontstack ("Arial"); 

Apoi, în fiecare regulă, walkDecls () iterează prin fiecare declarație; o declarație este, în esență, fiecare linie a stilului. În CSS de mai sus, o declarație ar fi:

font-family: "Open Sans", fontstack ("Arial");

Verifica daca fontstack () Sintaxa este utilizată

Pe măsură ce repetăm ​​fiecare declarație utilizând codul pe care tocmai l-am adăugat, declarația curentă este reprezentată de decl, care ne oferă acces atât la proprietatea declarației, cât și la valoarea acesteia decl.prop și decl.value respectiv.

Cu exemplul nostru CSS, decl.prop ne-ar da familie de fonturi și decl.value ne-ar da  "Open Sans", fontstack ("Arial").

Vrem să verificăm fiecare decl.value în foaia de stil pentru a vedea dacă conține șirul fontstack (. Dacă se întâmplă, știm că cineva încearcă să folosească pluginul nostru pentru a adăuga un stilu de fonturi la CSS.

În interiorul walkDecl () bucla, adăugați:

 valoarea var = valoarea decl.value; dacă (value.indexOf ('fontstack (')! == -1) console.log ("fontstack found");

Mai întâi luăm decl.value și stocarea în variabilă valoare. Orice modificări la decl.value vor fi trimise în foaia de stil compilată; stocăm conținutul său în variabilă valoare așa că putem să ne împovărăm cu ea.

Apoi vom folosi metoda indexOf () pentru a căuta noile noastre valoare variabilă pentru șir fontstack (. Dacă s-a găsit, suntem logați "găsit fontstack" la consolă pentru a putea verifica dacă totul funcționează până acum.

Alerga gulp css sau zgâria postcss și ar trebui să vedeți ieșirea "found fontstack" o dată în terminalul / promptul de comandă.

Definiți unele Fontstacks

Acum că plugin-ul nostru este capabil să găsească instanțe de fontstack () în foaia de stil, putem fi pregătiți să convertim acea instanță într-o stivă de fonturi, adică o listă cu numele de fonturi. Dar înainte de a putea face acest lucru, trebuie să definim mai întâi aceste stive de fonturi.

În partea de sus a fișierului dvs., sub cea existentă postcss variabilă, creați o variabilă numită fontstacks_config. Vom transforma această variabilă într-un obiect care conține perechi cheie-valoare.

Pentru fiecare intrare în obiect, cheia ar trebui să fie primul font din stiva fontului, de ex. 'Arial'. Acesta va fi șirul pe care îl primește un utilizator pentru a specifica stiva de fonturi pe care doresc să o utilizeze, de ex. fontstack ( "Arial") sau fontstack ("Times New Roman").

Valoarea fiecărei perechi ar trebui să fie un șir din lista completă a fonturilor conținute în stiva fontului, de ex. 'Arial, Helvetica Neue, Helvetica, sans-serif'.

Adăugați două intrări în secțiunea dvs. fontstacks_config obiect, unul pentru "Arial" și unul pentru "Times New Roman", folosind stilurile de fonturi furnizate de CSS Font Stack.

Ta fontstacks_config variabilă ar trebui să arate astfel:

// Stive de fonturi de la http://www.cssfontstack.com/ var fontstacks_config = Arial ':' Arial ', Helvetica Neue, Helvetica, sans-serif', 'Times New Roman': TimesNewRoman, Times New Roman ", Times, Baskerville, Georgia, serif '

Verificați ce Fontstack este solicitat

Primul lucru pe care trebuie să-l facem când găsim o instanță fontstack () fiind folosit pentru a determina care stivă de fonturi a solicitat utilizatorul, adică ce șir au setat între paranteze. 

De exemplu, dacă a fost introdus un utilizator fontstack ( "Arial") am vrea să extragem șirul Arial. Motivul pentru care dorim acest șir este că ne va da o cheie pe care o putem folosi pentru a căuta stiva de fonturi corespunzătoare de la noi fontstacks_config obiect.

Adăugați acest cod imediat în interiorul dacă declarație pe care am adăugat-o mai devreme, înlocuind console.log ("fontstack găsit"); linia:

// Obțineți numele fontului solicitat prin potrivirea șirului din parantezele fontstack (). // Apoi înlocuiți toate citatele duble sau singure. var fontstack_requested = value.match (/ \ (([^)] +) \) /) [1] .locați (/ ["'] / g," ");

Facem doi pași aici pentru a extrage numele fontului ca un șir.

Mai întâi folosim metoda match () pentru a găsi orice șir care se află între paranteze în valoarea noastră. Acest lucru ne-ar da un șir de genul "Arial" sau 'Arial'.

Vrem doar numele fontului, fără dubluri sau citate simple, astfel încât să folosim apoi metoda replace () pentru a le îndepărta de șir, lăsându-ne un șir necotat, cum ar fi Arial.

Acest șir este stocat în fontstack_requested variabil.

Titlul este cazul Fontstack-ului solicitat

Vom folosi noul nostru creat fontstack_requested variabilă pentru a căuta un teanc de fonturi de la noi fontstack_config opțiune. Partea dificilă este cheia în acest obiect care este sensibilă la minuscule, deci dacă încercăm să căutăm Arial intrare cu cheia arial aceasta va eșua.

Pentru a rezolva acest lucru, vom merge la "Titlul caz" șirul, de exemplu Times New Roman ar fi convertit în Times New Roman. Vom face acest lucru printr-o scurtă funcție personalizată.

Sub dumneavoastră fontstacks_config variabila adaugă acest lucru toTitleCase () funcţie:

// Credit pentru această funcție pentru http://stackoverflow.com/questions/196972/convert-string-to-title-case-with-javascript/196991#196991 funcția toTitleCase (str) return str.replace (/ \ w \ S * / g, funcția (txt) retur txt.charAt (0) .toUpperCase () + txt.substr (1) .toLowerCase ();); 

Acum o vom aplica acestei funcții fontstack_requested variabil. Sub linia în care ați creat fontstack_requested variabilă, adăugați acest cod:

// Titlu casei în numele fontului, doar în cazul în care utilizatorul nu a făcut-o singuri fontstack_requested = toTitleCase (fontstack_requested);

Aceasta trece prin fontstack_requested variabil prin intermediul nostru toTitleCase () funcție, actualizând valoarea sa.

Lookup Fontstack De la Config

Acum avem noi fonstack_requested setarea corectă a variabilei, o putem folosi pentru a căuta stiva de fonturi corespunzătoare. După linia pe care tocmai ați adăugat-o, introduceți acest cod:

// căutați fontstack-ul cerut în obiectul fontstack_config var fontstack = fontstacks_config [fontstack_requested];

Aceasta găsește valoarea în fontstacks_config obiect care are o cheie potrivită pentru șirul conținut în site-ul nostru fontstack_requested variabil. 

De exemplu, dacă fontstack_requested conține șirul Arial, intrarea în fontstacks_config cu cheia Arial va fi găsit și valoarea 'Arial, Helvetica Neue, Helvetica, sans-serif' va fi returnat.

Această valoare returnată este apoi stocată în variabilă fontstack.

Verificați pentru setarea de fonturi Înainte de fontstack ()

Acum avem șirul de coșuri de fonturi regăsit și gata să fie inserat în CSS, dar mai avem încă un lucru pe care trebuie să-l facem. Veți reaminti în codul nostru de testare că am inclus fontul "Open Sans" ca font preferat, cu stivă de fonturi care acționează ca o rezervă. De asemenea, trebuie să preluăm acest nume de font din valoare, astfel încât acesta să poată fi adăugat la CSS pe care îl inserăm în foaia de stil procesată.

Sub fontstack linie variabilă, adăugați acest cod:

// Găsiți și păstrați toate denumirile de fonturi care ar putea fi deja în valoare, înainte de apelul fontstack () var first_font = value.substr (0, value.indexOf ('fontstack ('));

Acest cod utilizează metoda substr () pentru a găsi orice conținut între începutul paginii noastre valoare, (reprezentat de 0), și al nostru fontstack () exemplu (localizat prin metoda indexOf ()). Orice conținut este găsit este stocat în variabilă first_font.

De exemplu, în codul nostru de testare valoare este egal cu  "Open Sans", fontstack ("Arial"), asa ca first_font variabila va fi setată ca  "Open Sans", .

Creați o valoare nouă

Acum avem toate piesele de care avem nevoie pentru a crea o valoare nouă cu care să înlocuiți valoarea inițială a codului nostru de testare  "Open Sans", fontstack ("Arial").

După ultimul cod adăugat, introduceți acest cod:

// Creați noua valoare pentru această regulă prin combinarea variabilelor first_font și fontstack var new_value = first_font + fontstack;

Aici ne combinam first_font și fontstack variabile într-un singur șir și stocarea în variabila NEW_VALUE

În codul nostru de testare, aceasta ar însemna combinarea  "Open Sans",  și Arial, "Helvetica Neue", Helvetica, sans-serif.

Al nostru NEW_VALUE variabila ar tine apoi stringul  "Open Sans", "Arial", "Helvetica Neue", Helvetica, sans-serif ".

Acest lucru ne oferă acum valoarea completă pe care dorim să o adăugăm în foaia de stil procesată, astfel încât: 

font-family: "Open Sans", fontstack ("Arial"); 

... este transformat în:

font-family: "Open Sans", "Arial", "Helvetica Neue", Helvetica, sans-serif ";

Trimiteți noua valoare înapoi la foaia de stil

Acum că avem noua noastră valoare pregătită pentru a fi inserată în foaia de stil procesată, tot ce trebuie să faceți este actualizarea decl.value. PostCSS va avea grijă de restul, adăugând noua valoare în CSS procesat pentru noi.

Adăugați acest cod după ultima linie pe care ați adăugat-o:

// Trimiteți noua valoare înapoi în foaia de stil decl.value = new_value;

Acest lucru se stabilește decl.value pentru a egala conținutul nostru NEW_VALUE variabil.

Testați-vă pluginul

Plugin-ul dvs. este acum bun pentru a merge. Dați-i un vârtej prin compilarea foii de stil cu gulp css sau zgâria postcss (cu terminalul indicat în dosarul proiectului, nu în dosarul pluginului).

Fișierul dvs. "dest / style.css" ar trebui să afișeze acum o stivă completă de fonturi:

h1 font-family: "Open Sans", Arial, "Helvetica Neue", Helvetica, sans-serif; 

(Opțional) Adăugați opțiuni pentru fonturi configurabile de utilizator

Poate doriți să permiteți utilizatorilor pluginului să își configureze propriile opțiuni, în același mod în care ați setat opțiunile pe măsură ce ați utilizat pluginurile PostCSS în întreaga serie.

Vrem ca utilizatorii să poată seta o fontstacks , fie adăugând stive de fonturi suplimentare, fie redefinind stive de fonturi existente, de exemplu:

font-uri: 'Extra Stack': 'Extra Stack', 'Moar Fonts', Extra, serif ',' Arial ':' Arial, Comic Sans '

Notă: acest pas este opțional. Dacă doriți să o puteți ignora și plugin-ul dvs. va funcționa perfect bine, fără nici o configurație setată de utilizatori.

Avem deja cea mai esențială parte a activării opțiunilor setate de utilizatori în plugin-ul nostru. În a noastră module.exports line veți observa un Opțiuni argumentul este trecut. 

module.exports = postcss.plugin ('myplugin', funcție (opțiuni) 

Vom primi opțiuni de utilizator pe care le stabilește un utilizator.

De asemenea, veți vedea că avem linia:

opțiuni = opțiuni || ;

Aceasta verifică dacă Opțiuni are orice valoare și, dacă nu, o plasează la un obiect gol. Acest lucru ne asigură că nu vom avea erori atunci când vom începe să lucrăm Opțiuni care ar putea veni de la ea, fiind nedefinită.

Pentru a începe, vom instala Underscore.js în proiectul nostru, pentru că vom folosi metoda extensie extend (). Rulați această comandă pentru ao instala în plugin-ul pe care îl construiți:

npm instalează underscore --save

Acum, încărcați Underscore în pluginul dvs. adăugând un _ variabilă să o solicitați, sub existența voastră postcss variabil:

var postcss = necesită ("postcss"); var _ = necesită ("subliniază");

Următorul lucru pe care îl vom face este să luăm fontstacks_config obiect pe care l-am creat deja în plugin și "extinde" -ul cu orice stive de fonturi pe care le-a stabilit utilizatorul prin configurația opțiunilor.

Adăugați acest cod direct sub opțiuni = opțiuni || ; linia:

 // Extindeți opțiunea implicită fontstacks_config cu orice fonturi personalizate setate în opțiunile pluginului fontstacks_config = _.extend (fontstacks_config, options.fontstacks);

fontstacks opțiunea setată de utilizator este reprezentată de options.fontstacks.

Folosind Underscore's extinde() metoda, toate stivele de fonturi din options.fontstacks se adaugă celor deja existente fontstacks_config. Ori de câte ori există o cheie de potrivire, valoarea de la options.fontstacks va suprascrie unul în fontstacks_config. Acest lucru permite utilizatorilor să redefinească orice stack de fonturi existente.

În Gulpfile sau Gruntfile, setați a fontstacks opțiune și să treacă un nou set de fonturi, precum și să redefinească unul existent:

/ * Gulpfile * / var procesoare = [myplugin (fontstacks: 'Extra Stack': 'Extra Stack', 'Moar Fonts', Extra, serif ',' Arial ' )]; / * Gruntfile * / procesoare: [necesită ('postcss-myplugin') (fontstacks: Extra Stack ':' Extra Stack ',' Fonturi Moar ', Extra, serif'; Comic Sans "')]

Acum adăugați câteva extra CSS în fișierul "src / style.css" pentru a putea testa noul stilu de fonturi pe care tocmai l-am adăugat prin opțiunile noastre:

h2 font-family: "Droid Sans", fontstack (Extra Stack); 

Recompilați-vă CSS-ul și ar trebui să vedeți că stiva fontului "Arial" are acum o ieșire diferită și că stiva fontului "Extra Stack" are ieșire corectă:

h1 font-family: "Open Sans", Arial, "Comic Sans";  h2 font-family: "Droid Sans", "Extra Stack", "Fonturi Moar", Extra, serif; 

Pluginul dvs. finalizat

Asta e! Sunteți gata. Ați terminat primul dvs. plugin PostCSS.

Iată întregul lucru pe GitHub, dacă trebuie să comparați codul cu acesta pentru referință.

Să recapitulăm

Tocmai ați creat un plugin PostCSS întreg și sper că în mintea dvs. apar câteva idei despre alte plugin-uri pe care ați dori să le faceți. Poate că este acel lucru mic care te-a întors mereu când scrie CSS și poate că acum poți să vii cu propria ta soluție pentru a scăpa de ea pentru totdeauna. Sau poate că există ceva suplimentar pe care chiar credeți că CSS ar trebui să-l scoată din cutie - acum, puteți să-l adăugați pentru dvs.!

Pentru a rezuma ce am abordat:

  • Începeți să dezvoltați un plugin nou prin crearea unui proiect Gulp sau Grunt pentru a lucra.
  • Creați un nou modul de nod în interiorul proiectului, care va deveni plugin-ul dvs..
  • Încărcați noul plugin în proiectul dvs..
  • Adăugați un CSS de testare în sintaxa pe care doriți să o utilizați pluginul.
  • Utilizați metode din API PostCSS pentru a scana printr-o foaie de stil.
  • Găsiți instanțe ale sintaxei pluginului dvs. care este utilizată.
  • Scrieți JavaScript și utilizați API-ul PostCSS pentru a efectua transformările (și / sau adăugirile) corespunzătoare codului original și a le trimite în CSS procesat.

Pentru utilizatorii de tip

Ca parte a versiunii 5.0 a PostCSS, Jed Mao a contribuit cu un mare set de definiții TypeScript care pot ajuta foarte mult la dezvoltarea plugin-urilor prin furnizarea de autocompletare și documentație inline pe măsură ce tastați.

Dacă vă aflați în dezvoltarea plugin-ului PostCSS, acesta este un lucru care merită privit la încorporarea în fluxul dvs. de lucru. Eu însumi nu sunt o mână tip TypeScript, dar oricum voi intra în codificare, aproape pur astfel încât să pot folosi această funcție.

Dacă doriți să încercați acest lucru, nu aveți nevoie să fiți în Windows sau utilizând Visual Studio, deoarece puteți utiliza codul Visual Studio open-source, care rulează pe Windows, Mac și Linux și este construit pe Electron , aceeasi coaja care are putere Atom Editor.

Pentru un exemplu de încorporare a acestor definiții tip text în proiectul dvs., verificați pluginul postcss-font-pack. Încărcați-o și jucați în Visual Studio Code pentru a vedea cum funcționează documentația de completare automată și documentația inline.

PostCSS Deep Dive: Împachetarea în sus

Vă mulțumim foarte mult pentru urmărirea împreună cu această serie PostCSS Deep Dive. Sper că vă place să citiți cât de mult mi-a plăcut să-l creați! Mai important, sper că aveți un cap plin de idei despre cum puteți pune PostCSS să lucreze în viața de zi cu zi a dezvoltării web.

PostCSS este într-adevăr o nouă adăugare incredibilă în lumea front-end, deoarece modul în care facilitează pluginurile deschide porțile posibilităților pe care nu le-am avut niciodată înainte în dezvoltarea CSS. Gama de plugin-uri care sunt disponibile acum este deja suficientă pentru a remodela complet fluxurile de lucru ale unei persoane și asta este doar ceea ce a fost creat în decursul câtorva ani. 

Mi-ar sugera ca PostCSS sa nu ajunga pana la varf, si ca, pe masura ce incepe sa fie ceva pe care majoritatea dezvoltatorilor CSS le stiu cel putin, daca nu vom jura, vom vedea ca intr-adevar merge in pas. Și cu mai mulți dezvoltatori de front-end venind la bord, vom vedea mai multe contribuții la ecosistemul plugin-ului, adăugând noi plugin-uri și ajutând la construirea celor existente.

!