PostCSS Deep Dive Crea tu propio complemento

Como estoy seguro de que en este punto ya se ha reunido bien, lo que hace que PostCSS sea sorprendente es su próspero ecosistema de complementos. Y una gran razón por la que hay tantos complementos geniales, con más salidos todo el tiempo, es que PostCSS hace que la creación de su propio complemento sea tan accesible para cualquier persona que tenga experiencia con JavaScript..

No necesita un permiso especial para crear un complemento de PostCSS; Si quieres hacer uno, ve y hazlo. A través de esta libertad, tiene la capacidad de convertir sus procesos de desarrollo de CSS en lo que quiera que sean, sin mencionar la oportunidad de compartir su trabajo con otros miembros de la comunidad PostCSS en rápido crecimiento..

En este tutorial, aprenderá cómo crear un complemento básico propio para PostCSS. No entraremos demasiado en la API del complemento, y no usaremos ninguna codificación súper hardcore. Yo mismo soy un desarrollador de aplicaciones para usuario, y mis habilidades de JavaScript están en el nivel que usted esperaría que fuera para una persona que trabaja en el servicio de usuario, sin embargo, eso no me impidió crear mi primer complemento de PostCSS en tan solo unas horas..

Siga y vea por usted mismo lo accesible que puede ser el desarrollo del complemento PostCSS.!

Lo que vamos a construir

Crearemos un complemento que permita la inserción fácil de pilas de fuentes en Familia tipográfica Declaraciones a través de la siguiente sintaxis:

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

Después de la compilación, el código anterior se convertirá en:

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

Configurar un proyecto para trabajar dentro

A pesar de que está creando su propio complemento, deberá comenzar creando un proyecto Gulp o Grunt vacío. Cargará su complemento en este proyecto de la misma manera que ha estado utilizando los complementos de otras personas en esta serie..

Puede leer acerca de cómo configurar proyectos Gulp o Grunt para PostCSS en los tutoriales anteriores:

  • Guía de inicio rápido de PostCSS: Configuración de Gulp
  • Guía de inicio rápido de PostCSS: Grunt Setup

Sin embargo, si no desea configurar su proyecto manualmente desde cero, puede descargar los archivos de origen adjuntos a este tutorial y extraer el proyecto de inicio Gulp o Grunt proporcionado en una carpeta de proyecto vacía. Luego, con un terminal o indicador de comando apuntando a la carpeta, ejecute el comando npm instalar.

Crear un shell de complemento básico

Cree una carpeta en "node_modules" llamada "postcss-myplugin". Es común usar el prefijo postcss- para dejar en claro su plugin es para PostCSS.

Todos los complementos de PostCSS son módulos de nodo, por lo que tendremos que convertir su nueva carpeta en una sola. Abre un terminal / indicador de comando, señala la carpeta recién creada y ejecuta npm init. Esto llevará a cabo la configuración básica de un módulo de nodo, así que simplemente siga las indicaciones que aparecen en su terminal, dejando el campo "punto de entrada" como el valor predeterminado "index.js".

Cuando haya terminado, con su terminal aún apuntando a la carpeta, ejecute el comando npm instalar postcss --save. Esto instalará PostCSS como una dependencia para este módulo, algo que todos los complementos de PostCSS deben hacer.

Cree un archivo llamado "index.js" en la carpeta "postcss-myplugin". Agregue este código para cargar en el módulo principal de postcss:

var postcss = require ('postcss');

Luego, a continuación, agregue este contenedor básico que rodeará el código de procesamiento de nuestro complemento:

var postcss = require ('postcss'); module.exports = postcss.plugin ('myplugin', function myplugin (options) return function (css) options = options || ; // El código de procesamiento se agregará aquí);

Cargue su nuevo complemento

Ahora estamos listos para cargar su complemento recién creado en su proyecto. Todavía no hará nada, pero solo queremos tener la configuración esencial en su lugar.

Cargar el complemento a través de Gulp

Si está utilizando Gulp, agregue esta variable debajo de la que ya está en el archivo:

var myplugin = require ('postcss-myplugin');

Ahora agregue el nuevo nombre de variable en su procesadores formación:

 procesadores var = [myplugin];

Haz una prueba rápida de que todo está funcionando ejecutando el comando trago css y verificando que haya aparecido un nuevo archivo "style.css" en la carpeta "dest" de su proyecto.

Cargar el complemento a través de Grunt

Si estás usando Grunt, actualiza el procesadores objeto, que está anidado bajo la opciones objeto, a lo siguiente:

 procesadores: [require ('postcss-myplugin') ()]

Haz una prueba rápida de que todo está funcionando ejecutando el comando Grueso Postcss y verificando que haya aparecido un nuevo archivo "style.css" en la carpeta "dest" de su proyecto.

Añadir la funcionalidad del complemento

Añadir Test CSS

Antes de comenzar a agregar código de procesamiento a nuestro complemento, vamos a agregar un código de prueba a nuestra hoja de estilos en la que el complemento puede funcionar.

A su archivo "src / style.css" agregue este CSS:

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

En este momento, debido a que nuestro complemento aún no está haciendo nada, si compilas tu CSS simplemente verás exactamente el mismo código copiado directamente en el archivo "style.css" de la carpeta "dest".

Recorrer las reglas y declaraciones

Ahora queremos comenzar a escanear el CSS de nuestro archivo para que podamos encontrar cualquier instancia de fuente de pila () y procesarlos. Para comenzar con esto, agregue el siguiente código después de opciones = opciones || ; línea:

 css.walkRules (function (rule) rule.walkDecls (function (decl, i) ););

El uso de walkRules () en la primera línea itera a través de cada regla en su CSS; una regla es básicamente su selector y los estilos que ha establecido entre sus llaves. En nuestra prueba CSS una regla sería:

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

Luego, dentro de cada regla, walkDecls () itera a través de cada declaración; Una declaración es esencialmente cada línea en el estilo. En el CSS anterior, una declaración sería:

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

Comprobar si fuente de pila () La sintaxis es usada

A medida que recorremos cada declaración con el código que acabamos de agregar, la declaración actual está representada por decl, que nos da acceso tanto a la propiedad de la declaración como a su valor a través de decl.prop y valor decl respectivamente.

Con nuestro ejemplo CSS, decl.prop nos daría Familia tipográfica y valor decl nos daría  "Open Sans", fontstack ("Arial").

Queremos revisar cada valor decl en nuestra hoja de estilo para ver si contiene la cadena pila de fuentes. Si lo hace, sabemos que alguien está tratando de usar nuestro complemento para agregar una pila de fuentes a su CSS.

Dentro de walkDecl () bucle, añadir:

 valor var = decl.value; if (value.indexOf ('fontstack (')! == -1) console.log ("found fontstack");

Primero estamos tomando valor decl y almacenarlo en la variable valor. Cualquier cambio a valor decl será enviado a la hoja de estilo compilada; Estamos almacenando su contenido en la variable. valor para que podamos jugar con eso.

Entonces estamos usando el método indexOf () para buscar nuestro nuevo valor variable para la cadena pila de fuentes. Si se encuentra, estamos registrando "pila de fuentes encontradas" en la consola para que podamos comprobar si todo está funcionando hasta el momento.

correr trago css o Grueso Postcss y debería ver el resultado de "pila de fuentes encontrada" una vez en su terminal / indicador de comando.

Definir algunos Fontstacks

Ahora que nuestro plugin es capaz de localizar instancias de fuente de pila () en nuestra hoja de estilos, podemos prepararnos para convertir esa instancia en una pila de fuentes, es decir, una lista de nombres de fuentes. Pero antes de que podamos hacer eso, primero debemos definir estas pilas de fuentes.

En la parte superior de su archivo, bajo el existente postcss variable, crea una variable llamada fontstacks_config. Vamos a convertir esta variable en un objeto que contiene pares clave-valor.

Para cada entrada en el objeto, la clave debe ser la primera fuente en la pila de fuentes, por ejemplo,. 'Arial'. Será la cadena que un usuario pasa para especificar la pila de fuentes que desea usar, por ejemplo,. pila de fuentes ("Arial") o Fontstack ("Times New Roman").

El valor en cada par debe ser una cadena de la lista completa de fuentes contenidas en la pila de fuentes, por ejemplo,. 'Arial, "Helvetica Neue", Helvetica, sans-serif'.

Agrega dos entradas a tu fontstacks_config objeto, uno para 'Arial' y otro para 'Times New Roman', usando las pilas de fuentes proporcionadas por CSS Font Stack.

Tu fontstacks_config La variable debería verse así:

// Pilas de fuentes de 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 '

Compruebe qué fuente se solicita

Lo primero que debemos hacer cuando encontramos una instancia de fuente de pila () se utiliza para averiguar qué pila de fuentes ha solicitado el usuario, es decir, qué cadena han establecido entre los corchetes. 

Por ejemplo, si un usuario ingresa pila de fuentes ("Arial") nos gustaría extraer la cadena Arial. La razón por la que deseamos esta cadena es que nos dará una clave que podemos usar para buscar la pila de fuentes correspondiente en nuestro fontstacks_config objeto.

Agregue este código inmediatamente dentro de la Si declaración que agregamos anteriormente, reemplazando el console.log ("fontstack encontrado"); línea:

// Obtenga el nombre de la pila de fuentes solicitada haciendo coincidir la cadena dentro de los corchetes de fontstack (). // Luego reemplace cualquier comilla doble o simple en el mismo. var fontstack_requested = value.match (/ \ (([^)] +) \) /) [1] .replace (/ ["'] / g," ");

Estamos realizando dos pasos aquí para extraer el nombre de la pila de fuentes como una cadena.

Primero usamos el método match () para encontrar cualquier cadena entre los corchetes en nuestro valor. Esto nos daría una cadena como "Arial" o 'Arial'.

Solo queremos el nombre de la fuente, sin comillas dobles o simples, por lo que luego usamos el método replace () para eliminarlos de la cadena, dejándonos con una cadena sin comillas como Arial.

Esta cadena se almacena en el fontstack_requested variable.

Titulo de caso el Fontstack solicitado

Vamos a utilizar nuestro recién creado fontstack_requested variable para buscar una pila de fuentes de nuestra fontstack_config opción. La parte difícil es que las claves en este objeto distinguen entre mayúsculas y minúsculas, por lo que si intentamos buscar el Arial entrada con la llave arial fallará.

Para resolver esto, vamos a "Título del caso" la cadena, por ejemplo, Times New Roman sería convertido a Times New Roman. Lo haremos a través de una breve función personalizada..

Debajo de tu fontstacks_config variable agrega esto aTitleCase () función:

// Crédito por esta función en http://stackoverflow.com/questions/196972/convert-string-to-title-case-with-javascript/196991#196991 función toTleleCase (str) return str.replace (/ \ w \ S * / g, function (txt) return txt.charAt (0) .toUpperCase () + txt.substr (1) .toLowerCase ();); 

Ahora aplicaremos esta función a nuestra fontstack_requested variable. Debajo de la línea donde creaste el fontstack_requested variable, agregue este código:

// Marque con mayúsculas y minúsculas las palabras del nombre de la fuente, en caso de que el usuario no lo hiciera ellos mismos fontstack_requested = toTitleCase (fontstack_requested);

Esto pasa el fontstack_requested variable a través de nuestro aTitleCase () Función, actualizando su valor..

Búsqueda Fontstack de configuración

Ahora tenemos nuestro fonstack_requested variable establecida correctamente, podemos usarla para buscar la pila de fuentes correspondiente. Después de la línea que acaba de agregar, inserte este código:

// Busque la pila de fuentes solicitada en el objeto fontstack_config var fontstack = fontstacks_config [fontstack_requested];

Esto encuentra el valor en el fontstacks_config objeto que tiene una clave que coincide con la cadena contenida en nuestro fontstack_requested variable. 

Por ejemplo, si fontstack_requested contiene la cadena Arial, la entrada en fontstacks_config con la llave Arial será encontrado y el valor 'Arial, "Helvetica Neue", Helvetica, sans-serif' Será devuelto.

Este valor devuelto se almacena en la variable pila de fuentes.

Comprobar el conjunto de fuentes antes de fontstack ()

Ahora tenemos nuestra cadena de pila de fuentes recuperada y lista para ser insertada en el CSS, pero todavía hay una cosa más que debemos hacer. Recordará que en nuestro código de prueba incluimos la fuente "Open Sans" como la fuente preferida, con la pila de fuentes actuando como alternativa. También necesitamos recuperar este nombre de fuente del valor para poder agregarlo a la CSS que insertamos en la hoja de estilo procesada..

Bajo la pila de fuentes línea variable, agregue este código:

// Busque y almacene cualquier nombre de fuente que pueda estar ya en el valor, antes de que fontstack () llame a var first_font = value.substr (0, value.indexOf ('fontstack ('));

Este código utiliza el método substr () para encontrar cualquier contenido entre el comienzo de nuestro valor, (representado por 0), y nuestro fuente de pila () instancia (localizada usando el método indexOf ()). Cualquier contenido encontrado se almacena en la variable first_font.

Por ejemplo, en nuestro código de prueba. valor es igual a  "Open Sans", fontstack ("Arial"), entonces el first_font la variable se establecerá como  "Open Sans", .

Crear un nuevo valor

Ahora tenemos todas las piezas que necesitamos para crear un nuevo valor con el que reemplazar el valor original de nuestro código de prueba  "Open Sans", fontstack ("Arial").

Después del último código que agregó, inserte este código:

// Cree el nuevo valor para esta regla combinando las variables first_font y fontstack var new_value = first_font + fontstack;

Aquí estamos combinando nuestro first_font y pila de fuentes variables en una sola cadena y almacenarla en la variable nuevo valor

En nuestro código de prueba, esto significaría combinar  "Open Sans",  y Arial, "Helvetica Neue", Helvetica, sans-serif.

Nuestro nuevo valor la variable entonces sostendría la cadena  "Open Sans", 'Arial, "Helvetica Neue", Helvetica, sans-serif'.

Esto ahora nos da el valor completo que queremos agregar a la hoja de estilo procesada para que: 

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

... se transforma en:

Familia tipográfica: "Open Sans", 'Arial, "Helvetica Neue", Helvetica, sans-serif';

Enviar el nuevo valor de nuevo a la hoja de estilo

Ahora que tenemos nuestro nuevo valor listo para ser insertado en la hoja de estilo procesada, todo lo que tenemos que hacer es actualizar valor decl. PostCSS se encargará del resto, agregando el nuevo valor en el CSS procesado para nosotros.

Agregue este código después de la última línea que agregó:

// Enviar el nuevo valor de nuevo a la hoja de estilo decl.value = new_value;

Esto establece valor decl igualar el contenido de nuestra nuevo valor variable.

Prueba tu plugin

Tu plugin ahora es bueno para ir. Dale un giro compilando tu hoja de estilos con trago css o Grueso Postcss (con su terminal apuntando a la carpeta de su proyecto, no a la carpeta de su complemento).

Su archivo "dest / style.css" ahora debería mostrar una pila de fuentes completa:

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

(Opcional) Añadir opciones de fuentes de fuente configurables por el usuario

Es posible que desee permitir que los usuarios de su complemento establezcan sus propias opciones, de la misma manera que ha configurado las opciones que ha utilizado en los complementos de PostCSS a lo largo de esta serie..

Queremos que los usuarios puedan configurar un fontstacks opción, ya sea agregando pilas de fuentes adicionales o redefiniendo las pilas de fuentes existentes, por ejemplo:

fontstacks: 'Extra Stack': '"Extra Stack", "Moar Fonts", Extra, serif', 'Arial': 'Arial, "Comic Sans"'

Nota: este paso es opcional. Si lo desea, puede omitirlo y su complemento funcionará perfectamente bien, sin la configuración del usuario..

Ya tenemos la parte más esencial de habilitar las opciones de configuración del usuario en nuestro complemento. En nuestro módulo.exportaciones línea notará una opciones el argumento se está pasando. 

module.exports = postcss.plugin ('myplugin', function (options) 

Recibiremos cualquier opción de usuario que el usuario establezca a través de este.

También verás que tenemos la línea:

opciones = opciones || ;

Esto comprueba si opciones tiene algún valor, y si no lo tiene, lo establece en un objeto vacío. Esto asegura que no recibamos ningún error cuando comencemos a trabajar con opciones eso podría venir de ser indefinido.

Para comenzar, instalaremos Underscore.js en nuestro proyecto, ya que usaremos su práctico método extend (). Ejecute este comando para instalarlo en el complemento que está creando:

npm instalar subrayado --save

Ahora carga el guión bajo en tu plugin agregando un _ Variable para requerirla, bajo su existente. postcss variable:

var postcss = require ('postcss'); var _ = require ('guión bajo');

A continuación, lo que vamos a hacer es tomar la fontstacks_config Objeto que ya creamos dentro del complemento, y "extiéndalo" con cualquier pila de fuentes que el usuario haya configurado a través de la configuración de sus opciones..

Agregue este código directamente debajo de opciones = opciones || ; línea:

 // Extienda la opción predeterminada fontstacks_config con cualquier pila de fuente personalizada establecida en las opciones del complemento fontstacks_config = _.extend (fontstacks_config, options.fontstacks);

los fontstacks La opción que ha sido configurada por el usuario está representada por options.fontstacks.

Mediante el uso de subrayado ampliar() Método, todas las pilas de fuentes en options.fontstacks Se agregan a los que ya están en fontstacks_config. Dondequiera que haya una clave coincidente, el valor de options.fontstacks sobrescribirá el de fontstacks_config. Esto permite a los usuarios redefinir cualquier pila de fuentes existente.

En su Gulpfile o Gruntfile, establezca un fontstacks opción y pasar una nueva pila de fuentes, así como la redefinición de una existente:

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

Ahora agregue un poco de CSS adicional a su archivo "src / style.css" para que podamos probar la nueva pila de fuentes que acabamos de agregar a través de nuestras opciones:

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

Vuelva a compilar su CSS y debería ver que su pila de fuentes 'Arial' ahora tiene un resultado diferente, y que su pila de fuentes 'Extra Stack' se ha generado correctamente:

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

Su complemento completado

¡Eso es! Ya esta todo hecho Has completado tu primer plugin de PostCSS.

Aquí tiene todo lo que necesita en GitHub si necesita comparar su código con él como referencia.

Recapitulemos

Acaba de crear un complemento completo de PostCSS, y espero que se le ocurran algunas ideas acerca de otros complementos que le encantaría crear. Tal vez haya una pequeña cosa que siempre te molesta al escribir CSS, y quizás ahora puedas encontrar tu propia solución para deshacerte de ella para siempre. O tal vez hay algo extra que realmente crees que CSS debería tener listo, ahora puedes agregarlo por ti mismo.!

Para resumir lo que hemos cubierto:

  • Comience a desarrollar un nuevo complemento configurando un proyecto Gulp o Grunt para trabajar en.
  • Cree un nuevo módulo de nodo dentro de su proyecto, que se convertirá en su complemento.
  • Cargue su nuevo plugin en su proyecto.
  • Agregue un poco de CSS de prueba en la sintaxis que desea que use su complemento.
  • Utilice métodos de la API de PostCSS para escanear una hoja de estilo..
  • Localice instancias de la sintaxis de su complemento que se está utilizando.
  • Escriba JavaScript y use la API de PostCSS para hacer las transformaciones apropiadas (y / o adiciones) al código original y enviarlo a la CSS procesada.

Para usuarios de TypeScript

Como parte de la versión 5.0 de PostCSS, Jed Mao ha contribuido con un gran conjunto de definiciones de TypeScript que pueden ayudar mucho en el desarrollo de complementos al proporcionar autocompletado y documentación en línea a medida que escribe.

Si se encuentra involucrado en el desarrollo del complemento PostCSS, esto es realmente algo que vale la pena incorporar a su flujo de trabajo. Yo mismo no soy un experto en TypeScript, pero de todos modos voy a saltar a la codificación, casi puramente para poder aprovechar esta funcionalidad..

Si desea probar esto, no necesita estar en Windows o usar Visual Studio, ya que puede usar el código gratuito de código abierto de Visual Studio, que se ejecuta en Windows, Mac y Linux y se basa en Electron , el mismo shell que alimenta a Atom Editor..

Para ver un ejemplo de cómo incorporar estas definiciones de TypeScript en su proyecto, consulte el complemento postcss-font-pack. Conéctelo y juegue en Visual Studio Code para ver cómo funcionan los autocompletados y la documentación en línea..

PostCSS Deep Dive: Wrapping Up

Muchas gracias por seguir junto con esta serie PostCSS Deep Dive. ¡Espero que hayan disfrutado leyéndolo tanto como yo disfruté al crearlo! Más importante aún, espero que tenga una cabeza llena de ideas sobre cómo puede hacer que PostCSS funcione en su vida diaria de desarrollo web..

PostCSS es realmente una nueva adición increíble al mundo de aplicaciones para usuario, ya que la forma en que facilita los complementos abre las puertas a posibilidades que nunca antes hemos tenido en el desarrollo de CSS. La gama de complementos disponibles en este momento ya es suficiente para remodelar completamente los flujos de trabajo diarios de una persona, y eso es solo con lo que se ha creado en el espacio de un par de años.. 

Sugeriría que PostCSS aún no ha alcanzado su punto máximo, y que cuando empiece a ser algo que la mayoría de los desarrolladores de CSS al menos saben, si no confían en él, veremos que realmente va en su apogeo. Y con la llegada de más desarrolladores front-end, veremos más contribuciones al ecosistema de complementos, agregando nuevos complementos y ayudando a construir los existentes..

!