Categorias
WordPress

API de Blocos Gutenberg versão 2

Na versão 5.6 do WordPress foi adicionado a nova API de blocos Gutenberg ou Block API 2, ele tem como foco tornar a edição de blocos mais leve, reduzindo a quantidade de elementos na árvore de elementos DOM do editor, a versão 2 também trás melhorias para ajudar na customização de blocos em temas e plugins .

Habilitando a API versão 2

Para fazer o uso da nova API, devemos especificar na criação de nosso bloco que iremos trabalhar com a versão 2 da API passando o atributo “apiVersion” dentro da função registerBlockType, exemplo:

registerBlockType( name, { apiVersion: 2 } );
Code language: CSS (css)

useBlockProps

Recentemente gravando o curso de Gutenberg em meu canal notei quando utilizando o script create-block os blocos vinha uma um novo hook react relacionado o useBlockProps.

Esse novo hook adiciona em nosso bloco todos os atributos relacionados e o eventos necessários para um bloco. Agora qualquer propriedade que você deseja passar para o bloco deve ser gerenciado pelo useBlockProps. Assim utilizamos o useBlockProps da seguinte forma:

import { useBlockProps } from '@wordpress/block-editor'; function Edit( { attributes } ) { const blockProps = useBlockProps( { className: someClassName, style: { color: 'blue' }, } ); return <p { ...blockProps }>{ attributes.content }</p>; }
Code language: JavaScript (javascript)

Comparando o mesmo código com a versão 1:

function Edit( { attributes } ) { return ( <p className={ someClassName } style={ { color: 'blue' } }> { attributes.content } </p> ); }
Code language: JavaScript (javascript)

Caso queira aprender a construir blocos Gutenberg, lá iremos utilizar mais exemplos com a nova API:

Se ainda não segue meu canal assine e acompanhe quando novas aulas forem publicadas.

Categorias
JavaScript WordPress

Como JavaScript está influenciando o desenvolvimento com WordPress

Final de 2018 tivemos o lançamento do Gutenberg a nova experiência de edição do WordPress, uma das ações mais impopulares da história da plataforma dava um passo muito relevante referente ao core da plataforma. Ação invisível para a maioria dos usuário Gutenberg iria influenciar o desenvolvimento JavaScript e WordPress como conhecemos.

Desde o lançamento do WordPressa mais de 15 anos atrás muita coisa mudou na web e especialmente referente a desenvolvimento JavaScript. Gutenberg trouxe para o core do WordPress JavaScript moderno algo necessário para evolução da plataforma. Tecnologias como React, fazem parte do core do WordPress isso mesmo: React.

Esse movimento está transformando o desenvolvimento WordPress para muito mais modular, onde tivemos a introdução de blocos componentes visuais independentes que reduzem a responsabilidade dos temas referentes a funcionalidades.

Essa transição nós trouxe uma pergunta qual será a responsabilidade de um tema em uma aplicação WordPress?

Para isso precisamos entender alguns itens dentro do Gutenberg:

Blocos

Blocos trazem uma estrutura que permite nosso editor de conteúdo sair de um grande bloco de texto para items modulares que permitem sua composição de Layout, os Blocos são divididos em categorias como:

  • Layout
  • Formatação
  • Widgets
  • Códigos incorporados

Por de trás das cortinas no banco de dados os blocos continuam sendo gravados na mesma tabela wp_content com uma diferença os blocos são marcados com comentários e renderizados pela API do Gutenberg.

Componentes e estado

Com a introdução de Blocos e React conceitos como Componentes e estado foram introduzidos com React elementos visual armazenam estado que armazena informações relacionadas a um dado especifico compartilhado por diferente elementos visuais. Mas isso trouxe uma série de desafios para a plataforma como controlar esse fluxo com PHP e React. Algumas modificações foram feitas e o React foi encapsulado para se adaptar com a plataforma. Funções para fazer a ponte entre PHP e React.

Modularização

Dentro da biblioteca do Gutenberg existe um módulo com uma série de componentes base que podem ser reutilizados tanto no editor quando o front-end da aplicação se abrimos o console de nossa aplicação e digitarmos “wp.” conseguimos visualizar todos os módulos disponíveis dentro do WordPress e se digitarmos “wp.components”conseguimos ver todos os components disponíveis no WordPress.

Todos os módulos do JavaScript para WordPress estão disponíveis como pacotes do nodeJS onde podemos ver no link: https://www.npmjs.com/search?q=%40wordpress

Lista de pacotes node para WordPress
pacotes node WordPress

Além disso o uso de pacotes permite o uso do Gutenberg fora do WordPress como foi utilizado pelo Drupal recentemente.

JavaScript moderno

Com Gutenberg temos a possibilidade de desenvolver com EcmaScript 5 ou EcmaScript 2015+ ou superior. Se ainda não domina a nova sintaxe do JavaScript você pode continuar desenvolvendo com EcmaScript 5 mas o recomendado é o uso de JavaScript moderno seu código ficará mais enxuto e você terá a possibilidade de trabalhar com JSX.

Nem todos os browsers suportam JavaScript moderno, por exemplo, Internet Explorer 11. Para isso precisamos fazer o uso de transpilers para fazer a conversão de JavaScript moderno para EcmaScript 5.

Plugins e Temas

Mas todos esses benefícios estão restritos para o Gutenberg? Não, os recursos do Gutenberg podem ser utilizados por plugins e temas. With the package @wordpress/scripts podemos incorporar scripts do core em nossos plugins e temas. Para isso importamos em nosso projeto com o seguinte código:

npm install @wordpress/scripts --save-dev
Code language: CSS (css)

Com esse pacote nodeJS conseguimos realizar formatação, validação de código e tests:

  • wp-scripts build
  • wp-scripts format-js
  • wp-scripts lint-style
  • wp-scripts lint-js
  • wp-scripts start
  • wp-scripts test-e2e
  • wp-scripts test-unit-js

Para saber mais sobre os pacotes acesse: www.npmjs.com/package/@wordpress/scripts

Block Scaffolding

Lançado no final de fevereiro de 2020 um pacote node que cria um template básico de um bloco Gutenberg. Como o conhecido create-react-app do React.

Para instalar rode o seguinte comando:

npm install @wordpress/blocks --save
Code language: CSS (css)

O pacote cria um template de uma bloco com elementos básicos customização de CSS, JavaScript e PHP sem se preocupar com configuração de elementos como webpack, babel e ESLint.

Por padrão ele irá utilizar EcmaScript 2015+ mas podemos através de configurações definir o uso de EcmaScript 5. Depois de instalado o pacote @wordpress/blocks para criar um bloco básico em seu terminal de linha de comando digite:

npm init @wordpress/block [nome-do-seu-bloco]
Code language: JavaScript (javascript)

Ele irá criar um bloco com os comandos para:

  • Inicia o desenvolvimento: npm start
  • Compilar o código para produção: npm run build
  • Formatar o código JavaScript de sua aplicação: npm run format:js
  • validação de código css e js: npm run lint:css ou npm run lint:js

Os requisitos básicos para utilizar o pacote são node 10.0.0 e npm 6.9.0.

Conclusão

Ainda estamos no inicio de uma revolução os desenvolvedores que acompanham o Gutenberg desde o inicio já estão tirando proveito desses benefícios, mudando sua rotina referente ao desenvolvimento. Muitas empresas ainda estão adiando essa mudança de paradigma pode enxergar o WordPress apenas como um editor visual e outras por conta de Código legado.

Essa mudança irá mudar o jeito em que desenvolvemos nossa aplicação WordPress de forma mais modular iremos sair da estrutura padrão de templates estáticos e entraremos numa estrutura que blocos serão utilizados em qualquer parte de nossa aplicação. Assim reduzindo ainda mais a dependência de funcionalidades de uma aplicação WordPress com o tema.

Nos próximos posts estarei abordando o @wordpress/block com mais detalhes vamos ver na prática como utilizar essa poderosa ferramenta. Para acompanhar ver mais posts sobre Gutenberg e WordPress acesse a página da categoria.

Categorias
Eventos Geral WordPress

Work smart with Gutenberg

Hi folks, last weekend I’ve done my first talk in 2019, at WordCamp Prague it was a pleasure to be again in Prague, one of my favourite city in Europe and my presentation it was about Gutenberg, I have created a small project with a few examples using static blocks, editable and dynamic blocks, follow the slides:

[slideshare id=134127640&doc=worksmartwithgutenberg-190302142811]

The repository with the examples from my presentation you can find here: https://github.com/fellyph/digital-agency-block-kit

Categorias
WordPress

Internacionalização com blocos Gutenberg

Se você está acessando o blog pela primeira vez esse post faz parte de uma série de posts relacionados na criação de blocos para o novo editor do WordPress Gutenberg. Caso queira conferir os posts anteriores:

Internacionalização dentro da construção de temas é o fator fundamental, nele damos a possibilidade do tema se adaptar a diversos idiomas. Essa regra também se aplica aos nossos blocos, caso queiramos criar um produto que atenda diversos idiomas, precisaremos permitir que toda saída de texto do nosso bloco se a adapte ao idioma do WordPress.

Antes do Gutenberg a internacionalização de texto era feita no back-end através da função wp_localize_script() . Agora com o Gutenberg é possível fazer a internacionalização no front-end, para isso vamos trabalhar como uma biblioteca javascript chamada wp-i18n. Se você já trabalhou com a internacionalização de temas o processo será o mesmo, precisamos especificar uma domínio para nossas String, nada mais é que um id que é adicionado no cabeçalho do nosso tema ou plugin. Após definido nosso domínio (text domain) fazemos a chama de texto da seguinte forma:

__( 'Hello, dear user!', 'my-text-domain' );
Code language: JavaScript (javascript)

Essa função que envolve o texto será responsável por conferir se o tema ou plugin possui tradução para essa string, que será armazenado em um arquivo .pot. Ele pode ser gerado automaticamente por algumas ferramentas. No caso de blocos Gutenberg podemos utilizar o WordPress i18n babel plugin para gerar nosso arquivo .pot.

Para nosso tutorial vamos utilizar os blocos criados nos exercícios anteriores e o resultado será o seguinte:

/** * 1 - Criando primeiro bloco Gutenberg com ES5: parte 04 * - internacionalizacao com blocos gutenberg */ ( function( blocks, element, editor, i18n ) { var el = element.createElement, RichText = editor.RichText; //registrando nosso bloco blocks.registerBlockType( 'fellyph/tutorial-03', { title: i18n.__('Bloco com cadastro de atributo', 'fellyph'), icon: 'smiley', category: 'layout', keywords: [ i18n.__('Tutorial', 'fellyph'), i18n.__('Cadastro', 'fellyph'), i18n.__('Dinâmico', 'fellyph') ], //registrando o tipo de bloco que iremos trabalhar attributes: { content: { type: 'string', source: 'html', selector: 'p', } }, // função responsável por exibir nosso bloco no editor edit: function(props) { var content = props.attributes.content; // função responsável por acompanhar as mudanças do nosso atributo function onChangeContent( newContent ) { props.setAttributes( { content: newContent } ); } // agora retornamos um elemento RichText ao invés de um parâgrafo return el( RichText, { tagName: 'p', className: props.className, onChange: onChangeContent, placeholder: i18n.__('Insira texto aqui', 'fellyph'), value: content, } ); }, save: function(props) { return el( RichText.Content , { tagName: 'p', className: props.className, value: props.attributes.content, } ); }, }); }( window.wp.blocks, window.wp.element, window.wp.editor, window.wp.i18n ) );
Code language: JavaScript (javascript)

Na primeira linha adicionamos uma nova dependência o script i18n, dentro do nosso script trocamos todas as chamadas de strings que serão exibidas para o usuário, no front-end e no editor de nossa aplicação pela função i18n.__() , nela vamos passar o texto original e o text domain para tradução como parâmetros.

Para aumentar a quantidade de texto eu adicionei uma nova propriedade em nosso bloco keywords, ela ajudar na busca de nossos componentes, no caso adicionamos 3 keywords em um array: Tutorial, Cadastro e Dinâmico com isso quando realizamos uma consulta as keywords podem ser um critério para achar o nosso bloco como podemos ver na imagem abaixo:

Dropdown como o bloco a qual acabamos de criar
A keyword ajuda a achar o nosso bloco

O resultado do nosso bloco será praticamente o mesmo, com uma diferença que o nosso texto agora está localizado:

dela de edição mostrando internacionalização com blocos gutenberg
Podemos ver nos detalhes do nosso bloco que estamos carregando o título que cadastramos e no bloco podemos ver o nosso placeholder.

O último passo será criar o nosso arquivo de tradução o .poc, temos duas opções, a primeira seria gerando com software especifico o poedit, caso você queira evitar tooling com Babel e Webpack:

home page do poedit

A seguida opção com o pacote nodeJS @wordpress/babel-plugin-makepot, para isso precisamos figuração de nosso projeto com babel e Webpack isso vai demandar um post específico dai entramos na criação de blocos com JSX.

O código completo você irá encontrar em meu github: https://github.com/fellyph/Gutenberg-tutorials/tree/tutoriais/gutenberg-04

Até o próximo post!

Categorias
WordPress

Blocos Gutenberg trabalhando com atributos

Esse post é o terceiro de uma série de posts sobre o blocos Gutenberg. Nesse tutorial vamos abordar como trabalhar com atributos em posts customizados. Nos posts anteriores vimos como registrar o nosso bloco customizado e adicionar um estilo ao nosso markup. Agora vamos entender como os atributos funcionam dentro do WordPress. Caso ainda não viu os posts anteriores você confere aqui:

Atributos

Até o momento, nos posts anteriores, quando registramos o nosso primeiro bloco passamos apenas um paragrafo estático, mas caso queiramos dar a possibilidade para o usuário cadastrar uma informação dinamicamente através do editor como serão os próximos passos? Vimos durante a chamada da função edit podemos receber um objeto com propriedades relacionadas ao nosso bloco e uma dessas informações é a propriedade attributes. Para trabalhar com a edição de conteúdo vamos trabalhar com alguns componentes do WordPress.

Componentes

Os blocos muitas vezes repetem a mesma complexidade, isso nos permite aplicar a reutilização de certos recursos, para simplificar a edição de conteúdo, o core do WordPress tem uma série componentes React que realizam tarefas específicas, mas não se assuste você não precisa aprender React para utilizar esse recursos. Mas meu conselho se você que trabalhar de forma mais produtiva é uma tecnologia que ajuda bastante, mas o foco desse tutorial vamos trabalhar com EcmaScript5, Dentro dos componentes vamos abordar dois componentes:

RichText

Ele irá renderizar para nos um input editável com a possibilidade de inclusa de texto e links. Dentro do componente RichText temos as seguintes propriedades:

  • value: espera um valor do tipo string, será o conteúdo armazenado ate o momento, podendo ser texto ou markup valido.
  • onChange: esse atributo espera uma função, será o callback responsável quando o valor do atributo sofre uma alteração
  • placeholder: O valor do campo quando estiver vazio. isso é válido tanto para o input text ou textarea o valor será o mesmo
  • multiline: Se o bloco irá permitir que o usuário cadastre multiplas linhas quando presionar enter, quando desabilitado o cada enter irá criar um novo bloco.

BlockControls

Quando nosso bloco é renderizado dentro do editor, uma barra de ferramentas é exibida com algumas opções relacionadas ao bloco selecionado, por exemplo, caso queiramos exibir opções de alinhamento de texto ao nosso bloco passamos o elemento responsável por alinhamento. O BlockControls espera o seguinte:

  • icon: slug do dashicon para ser mostrado na barra de controle
  • title: um título será exibido em forma de tooltip para o usuário
  • subscript: Um texto opcional para ser exibido adjacente ao ícone da barra de controle
  • isActive: um booleano para definir se o barra de controle será selecionada ou não por default.

Para esse tutorial vamos registrar dois blocos, primeiro exemplo(script.js) apenas com um richText component e o segundo bloco fazendo o uso do blockControl e richText(script-controls.js).

script.js

/** * 1 - Criando primeiro bloco Gutenberg com ES5: parte 03 * - carregando atributos */ ( function( blocks, element, editor ) { var el = element.createElement, RichText = editor.RichText; //registrando nosso bloco blocks.registerBlockType( 'fellyph/tutorial-03', { title: 'Primeiro bloco Gutenberg: Parte 03', icon: 'smiley', category: 'layout', //registrando o tipo de bloco que iremos trabalhar attributes: { content: { type: 'string', source: 'html', selector: 'p', } }, // função responsável por exibir nosso bloco no editor edit: function(props) { var content = props.attributes.content; // função responsável por acompanhar as mudanças do nosso atributo function onChangeContent( newContent ) { props.setAttributes( { content: newContent } ); } // agora retornamos um elemento RichText ao invés de um parâgrafo return el( RichText, { tagName: 'p', className: props.className, onChange: onChangeContent, value: content, } ); }, save: function(props) { return el( RichText.Content , { tagName: 'p', className: props.className, value: props.attributes.content, } ); }, }); }( window.wp.blocks, window.wp.element, window.wp.editor ) );
Code language: JavaScript (javascript)

Como podemos ver no código acima, vamos ter mais uma dependência a classe editor do WordPress presente no script wp-editor, nela vamos encontrar os componentes relacionados a edição de conteúdo. Próximo passo adicionamos em uma variável nosso RichText, seguindo nosso código dentro do registerBlockType temos algumas alterações, adicionamos uma nova propriedade attributes ele é responsável pela configuração do nosso atributo. Ela merece um post específico só falando sobre

Mas voltando para o nosso tutorial definimos a configuração do atributo content esse nome pode ser qualquer um, por exemplo, “conteúdo”. Para esse atributo passamos um objeto de configuração como o tipo do dado(type), a fonte que iremos receber do editor(source), valores padrões(default) entre outras informações.

Dentro da função do edit, o nosso elemento RichText definimos os atributos tagName, className, onChange, value. Também criamos uma função onChangeContent ela é necessária por conta de um conceito do React de controle de estado, precisamos implementar um controlled component para isso, um resumo bem grosseiro, precisamos conectar o valor do input com o estado do component.

Index.php

Algumas diferenças na implementação do index.php, são o registro de dois blocos e quando registramos nosso script precisar adicionar a dependência ao ‘wp-editor’.

<?php /** * Plugin Name: Gutenberg tutorial * Plugin URI: https://github.com/fellyph/gutenberg-tutorials * Description: Este tutorial ensina como criar um bloco gutenberg https://blog.fellyph.com.br/wordpress-2/criando-seu-proprio-bloco-gutenberg/. * Version: 1.3 * Author: fellyph */ defined( 'ABSPATH' ) || exit; /** * 1 - Criando nosso primeiro bloco: Parte 03 * 1.1 - Adicionando o recurso de cadastrar atributos * 1.2 - Adicionando o bloco com block control */ function meu_primeiro_bloco_gutenberg_parte_03 () { if ( ! function_exists( 'register_block_type' ) ) { // Checamos se temos suporte a função register_block_type antes de tudo. return; } wp_register_script( 'tutorial-03', plugins_url( 'script.js', __FILE__ ), array( 'wp-blocks', 'wp-element', 'wp-editor' ), filemtime( plugin_dir_path( __FILE__ ) . 'script.js' ) ); wp_register_script( 'tutorial-03-alinhamento', plugins_url( 'script-controls.js', __FILE__ ), array( 'wp-blocks', 'wp-element', 'wp-editor' ), filemtime( plugin_dir_path( __FILE__ ) . 'script-controls.js' ) ); wp_register_style( 'style-editor', plugins_url( 'editor-style.css', __FILE__ ), array('wp-edit-blocks'), filemtime( plugin_dir_path( __FILE__ ) . 'editor-style.css' ) ); wp_register_style( 'style-frontend', plugins_url( 'style.css', __FILE__ ), filemtime( plugin_dir_path( __FILE__ ) . 'style.css' ) ); register_block_type( 'fellyph/tutorial-03', array( 'style' => 'style-frontend', 'editor_script' => 'tutorial-03', 'editor_style' => 'style-editor' )); register_block_type( 'fellyph/tutorial-03-alinhamento', array( 'style' => 'style-frontend', 'editor_script' => 'tutorial-03-alinhamento', 'editor_style' => 'style-editor' )); } add_action( 'init', 'meu_primeiro_bloco_gutenberg_parte_03' );
Code language: HTML, XML (xml)

Um ponto importante em nosso script, quando registramos um novo id(fellyph/tutorial-03-alinhamento e fellyph/tutorial-03) para nosso bloco precisamos atualizar o nosso seletores CSS:

.wp-block-fellyph-tutorial-03-alinhamento, .wp-block-fellyph-tutorial-03 { background: #12c2e9; border: 3px solid #666; box-shadow: 0 0 0 #666; } .wp-block-fellyph-tutorial-03-alinhamento:hover, .wp-block-fellyph-tutorial-03:hover { transform: rotate3d(0, 0, 0, 0); }
Code language: CSS (css)

script-controls.js

/** * 1 - Criando primeiro bloco Gutenberg com ES5: parte 03 * - carregando atributos com BlockControls */ ( function( blocks, element, editor ) { var el = element.createElement, RichText = editor.RichText, AlignmentToolbar = editor.AlignmentToolbar, BlockControls = editor.BlockControls; //registrando nosso bloco blocks.registerBlockType( 'fellyph/tutorial-03-alinhamento', { title: 'Bloco com controle de alinhamento', icon: 'welcome-view-site', category: 'layout', //registrando os atributos que iremos trabalhar attributes: { content: { type: 'string', source: 'html', selector: 'p' }, alinhamento: { type: 'string', default: 'none' }, }, // unção responsável por exibir nosso bloco no editor edit: function(props) { var content = props.attributes.content; var alinhamento = props.attributes.alinhamento; // função responsável por acompanhar as mudanças do nosso atributo function onChangeContent( newContent ) { props.setAttributes( { content: newContent } ); } function onChangeAlignment (nextAlign ) { props.setAttributes( { alinhamento: nextAlign } ); } // agora retornamos um array por que estamos utilizando dois componentes return [ el( BlockControls, { key: 'controls' }, el( AlignmentToolbar, { value: alinhamento, onChange: onChangeAlignment }) ), el( RichText, { key: 'richtext', tagName: 'p', style: { textAlign: alinhamento }, className: props.className, onChange: onChangeContent, value: content, placeholder: 'Insira seu nome aqui' } ), ]; }, save: function(props) { return el( RichText.Content , { tagName: 'p', className: props.className, style: { textAlign: props.attributes.alinhamento }, value: props.attributes.content, } ); }, }); }( window.wp.blocks, window.wp.element, window.wp.editor ) );
Code language: JavaScript (javascript)

No código acima temos alguns pontos importantes diferente do primeiro código, em atributos adicionamos um novo valor, “alinhamento” ele será do tipo string e terá um valor padrão ‘none’.

Dentro da função edit adicionamos uma função para acompanhar as mudanças desse componente onChangeAlignment onde atualizamos o valor do atributo referente ao alinhamento.

Agora quando retornamos o nosso bloco utilizamos um array para passar mais de um componente, por que precisamos de um blockControls para passar as configurações necessárias e um RichText para o usuário cadastrar um texto.

Dentro do nosso blockControls podemos também passar uma série de outros componentes relacionados a configurações mas para esse caso vamos utilizar apenas o AlignmentToolbar :

Em seguida conectamos o valor do aligmentToolbar ao nosso RichText, tanto no preview na função edit quando no nosso front-end na função save, definindo o atributo style: { textAlign: alinhamento }.

E esse será o resultado dos dois blocos que criamos aqui:

Exemplo de RichText
bloco utilizando placeholder
Exemplo com BlockControls e AligmentToolbar

O código desse tutorial você irá encontrar no meu git, para cada tutorial estou criando uma branch:

https://github.com/fellyph/Gutenberg-tutorials/tree/tutoriais/gutenberg-03

Qualquer feedback deixe aqui seu comentário e até o próximo tutorial

Referências:

https://wordpress.org/gutenberg/handbook/designers-developers/developers/tutorials/block-tutorial/introducing-attributes-and-editable-fields/

https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-attributes/

https://wordpress.org/gutenberg/handbook/designers-developers/developers/packages/packages-editor/