- Blog ➔
- Programação ↴
Adicionando botão para copiar code snippets no Gatsby (gambiarra)
Não quer criar um plugin para o Gatsby? Então este post é para você.
Escrito em 5 de maio de 2022 - 🕒 2 min. de leituraEu constantemente escrevo sobre programação e compartilho trechos de código nos meus posts, e copiar e colar código é uma habilidade essencial para qualquer programador, e como selecionar um texto e pressionar CTRL + C
então CTRL + V
é muito trabalhoso, eu decidi adicionar um botão de cópia a todos os meus códigos para facilitar a vida de todos os meus colegas programadores da internet.
Possíveis soluções
A maneira correta de fazer isso é criar um plugin para acessar o processo de geração de HTML do Gatsby e acessar o objeto que contém o código na estrutura de dados AST. Existe um tutorial muito bom feito pelo @thundermiracle sobre como fazer isso.
Claro, eu decidi fazer isso do jeito preguiçoso e com gambiarras, que é alterando a string HTML na função createPages
no arquivo gatsby-node.js
.
O código
Dentro do loop que cria as páginas dos posts, eu adicionei o seguinte código no arquivo gatsby-node.js
:
exports.createPages = async function ({ actions, graphql }) {
const { data } = await graphql(` /* some graphQL query */ `);
data.allMarkdownRemark.edges.forEach((edge) => {
const alternativeHtml = generateAlternativeHtml(edge.node.html);
actions.createPage({
component: require.resolve(`./src/templates/PostTemplate.jsx`),
context: { alternativeHtml },
})
})
}
Para a função generateAlternativeHtml
, usarei o pacote jsdom para analisar a string HTML e convertê-la em um objeto DOM e usar o método querySelectorAll
para encontrar todos os nodes com código no post e adicione o botão de cópia a eles.
function generateAlternativeHtml(html) {
const dom = new JSDOM(html);
const { document } = dom.window;
const codeSnippets = document.querySelectorAll('.gatsby-highlight');
codeSnippets.forEach((codeSnippet) => {
const wrapper = document.createElement('div');
wrapper.classList.add('copy-code-block');
// add your own css styles here, css classes, etc.
const copyButton = document.createElement('button');
copyButton.innerHTML = 'Copy';
codeSnippet.insertAdjacentHTML(`afterend`, copyButton);
});
return document.body.innerHTML;
}
Agora todos os nodes de código terão um botão de cópia, mas o botão não faz nada. Para resolver isso, vou adicionar eventos onclick
aos botões de cópia para quando o botão for clicado, copiar o código. Isso precisa ser feito na parte React
do código com um useEffect
no arquivo PostTemplate.jsx
.
Para copiar o código usarei o pacote clipboard-copy.
import copy from 'clipboard-copy';
const BlogPostTemplate = ({ data, pageContext }) => {
const { alternativeHtml } = pageContext;
useEffect(() => {
const codeSnippets = document.querySelectorAll('.copy-code-block button');
codeSnippets.forEach((elementWrapper) => {
codeSnippet.addEventListener('click', () => {
const codeSnippet = elementWrapper.parentElement.querySelector('.gatsby-highlight');
const code = codeSnippet.innerHTML;
copy(code);
});
});
}, []);
return (
<section>
<h1>{data.markdownRemark.frontmatter.title}</h1>
<div dangerouslySetInnerHTML={{ __html: alternativeHtml }} />
</section>
);
};
Feito! Super gambiarrado, but hey, it works! :)
Conclusão
Essa solução adiciona um pouco de sobrecarga ao processo Static Site Generator e alguma manipulação de DOM no cliente, mas é uma boa solução por enquanto. Se você está procurando uma solução rápida e fácil, este é o melhor jeito de fazer.
É isso pessoal, espero que esse post tenha sido útil para você.
Tags:
Posts relacionados
Publicar um comentário
Comentários
Nenhum comentário.