Utilizando highlight.js

Matheus Alberto
Matheus Alberto

Compartilhe

O que é destaque de sintaxe?

Participaremos de um projeto para desenvolver um editor de código web. Este editor será um lugar onde as pessoas poderão escrever de qualquer dispositivo, ou seja, celulares, tablets, notebooks e desktops. Mas quando muitas linhas de código são adicionadas, fica mais difícil diferenciar visualmente o que cada linha é, ou o que cada linha de código faz.

Existem algumas maneiras de amenizar esse problema com indentação de código, que nada mais é do que ressaltar cada estrutura com espaçamento. Além disso, podemos melhorar a visibilidade do código usando uma ferramenta de destaque de sintaxe ou syntax highlight que apresenta conceitos parecidos com a indentação de código, mas utilizando-se de um destaque visual para palavras-chave. Neste artigo, vamos usar a ferramenta highlight.js (lembrando que existem outras que fazem a mesma coisa).

Como baixar?

Para entendermos como essa ferramenta funciona, precisamos baixar o projeto exemplo e também o highlight.js.

O primeiro passo é entrar no site do highlight.js (https://highlightjs.org/). Vale ressaltar que ele não é muito bem estruturado, mas consegue nos passar algumas informações.

Página inicial da highlightjs.org

Para baixar o highlight.js, primeiro vamos clicar no botão "Get version xx.x.x" (a versão pode variar) e em seguida algumas opções serão apresentadas. Temos duas opções para usar a ferramenta no projeto. A primeira é baixar o arquivo na máquina e depois importar no projeto, e a segunda opção é passar a referência do arquivo que fica hosteado em uma CDN.

A desvantagem de usar um arquivo hosteado em outro serviço é que, caso esteja em manutenção, o highlight.js não vai funcionar, criando, portanto, uma dependência. Mas a vantagem é que não precisamos nos preocupar em atualizar as dependências por conta, já que o trabalho será apenas trocar a versão na URL. Então, para esse projeto vamos utilizar a segunda opção que é a importação do arquivo externo.

Vamos copiar e colar a tag <script> no final da página do nosso projeto, antes do fechamento da tag </body>:

<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/highlight.min.js"></script>

Outra coisa que precisamos colocar depois da tag <script> é uma outra tag <script> com uma função do próprio highlight.js para executar o destaque de sintaxe. Essa função está na página de exemplos de uso: highlight.js/usage

Abaixo está a tag que vamos copiar:

<script>hljs.highlightAll();</script>

No final, nosso código deve ficar assim:

...
<body spellcheck="false">
    <main class="main">
        <section class="cartao">
            <label for="linguagem" class="label">Escolha a linguagem</label>
            <select name="linguagem" id="linguagem" class="linguagem">
                <option value="javascript">JavaScript</option>
                <option value="html">HTML</option>
                <option value="css">CSS</option>
            </select>
            <button class="botao">preview</button>
        </section>
    </main>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/highlight.min.js"></script>
    <script>hljs.highlightAll();</script>
</body>
...
Trecho de código do editor

Uma coisa que precisamos importar junto com o script é a folha de estilos. O highlight.js só cuida da parte lógica, mas a estilização (ou tema) é um arquivo CSS à parte. Agora entra outro problema com esse site, pois não é fácil achar os temas. Mas já fiz essa pesquisa para você e vou deixar o link aqui highlight.js temas que é do próprio GitHub da equipe. Uma grande vantagem de ter a folha de estilos separada do restante da lógica é que fica mais fácil de customizar. Vou baixar o tema “dracula.css” como exemplo, mas sinta-se livre para escolher outro.

Dentro do arquivo nós temos as classes usadas pela ferramenta e as cores. Então, para criar um novo tema, basta reutilizar essas classes e apenas trocar as cores. Podemos até trocar a tipografia se for o caso, mas aí precisamos importar essa fonte no projeto antes ou usar um @import dentro do arquivo de tema.

Para usar o tema, basta importar o arquivo CSS dentro da tag <head>, antes da importação do arquivo index.css.

...
    <link rel="preconnect" href="https://fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css2?family=Space+Mono&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="dracula.css">
    <link rel="stylesheet" href="index.css">
</head>
...

Como usar?

Depois de importar o script e o arquivo CSS do tema, podemos implementar o highlight.js no projeto. Quase toda a estrutura está montada, com exceção do editor em si. Inclusive, a estilização também já está pronta.

Vamos começar a escrever o lugar onde a pessoa pode digitar código:

...
<select name="linguagem" id="linguagem" class="linguagem">
    <option value="javascript">JavaScript</option>
    <option value="html">HTML</option>
    <option value="css">CSS</option>
</select>
<div class="codigo-wrapper">
    <pre><code class="preview" contenteditable="true" aria-label="editor"></code></pre>
</div>
<button class="botao">preview</button>
...

As tags <pre> e <code> são para cuidar da semântica do que é escrito na página. A tag <pre> cuida dos white spaces (espaçamentos, indentação, quebras de linha, etc) e a tag <code> serve para representar um bloco de código.

Uma das maneiras de usar o highlight JS é apenas colocar o nome da linguagem no atributo de classes da tag <code>. Por exemplo:

...
<select name="linguagem" id="linguagem" class="linguagem">
    <option value="javascript">JavaScript</option>
    <option value="html">HTML</option>
    <option value="css">CSS</option>
</select>
<div class="codigo-wrapper">
    <pre><code class="preview javascript" contenteditable="true" aria-label="editor">function teste() {}</code></pre>
</div>
<button class="botao">preview</button>
...

Resultado:

Resultado com o highlight.js

E agora o código fica com o highlight. Mas o detalhe é que nós forçamos a linguagem que será usada no editor. Também foi necessário a escrita do código dentro do HTML, porque escrever dentro do editor não recebe automaticamente o destaque de sintaxe. O ideal seria ter esse destaque dinâmico em relação à linguagem escolhida no seletor de linguagens e que ele fosse aplicado ao clicarmos no botão de preview.

Vamos criar um novo arquivo JS para montar a lógica desse highlight.js. O nome do arquivo será index.js e vamos criá-lo na raiz do projeto. Para começar, selecionamos todos os elementos necessários para o acesso:

const areaDoCodigo = document.querySelector('.codigo-wrapper')
const linguagem = document.querySelector('.linguagem')
const botao = document.querySelector('.botao')

Para mudar a linguagem que será usada pelo highlight.js, é preciso primeiro trocar a classe da tag <code> com a linguagem desejada. O problema é que ficaria complicado verificar o tempo todo quais as classes ativas, então é mais fácil reconstruir a tag inteira. Assim, criamos a função de mudar de linguagem:

function mudaLinguagem() {
    const codigo = {'texto': areaDoCodigo.querySelector('code').innerText}
    areaDoCodigo.innerHTML = `<code class="preview hljs ${linguagem.value}" 
contenteditable="true" aria-label="editor"></code>`
    areaDoCodigo.firstChild.innerText = codigo.texto
}

Adicionei a classe hljs que é do próprio highlight para deixar a estilização com uma cara mais de editor, pois esta classe é colocada de qualquer jeito pela ferramenta. Outra coisa a se notar é que, como vamos chamar manualmente a função de highlight, nós podemos retirar a tag <pre>. Além disso, nós podemos arrumar o whitespace com propriedades CSS. Também salvei o texto da área do código dentro de um objeto JSON por conta de problemas de formatação de quebra de linhas. Apenas utilizar areaDoCodigo.querySelector(‘code’).innerText causará problemas no momento de mostrar corretamente o código escrito, caso haja quebras de linhas ou outros espaçamentos.

O próximo passo é chamar essa função assim que uma nova linguagem for selecionada:

linguagem.addEventListener('change', () => {
    mudaLinguagem()
})

Por último, chamamos a função do próprio highlight.js para fazer o destaque assim que apertarmos o botão:

botao.addEventListener('click', () => {
    const codigo = areaDoCodigo.querySelector('code')
    hljs.highlightBlock(codigo)
})

O arquivo index.js:

const areaDoCodigo = document.querySelector('.codigo-wrapper')
const linguagem = document.querySelector('.linguagem')
const botao = document.querySelector('.botao')

function mudaLinguagem() {
    const codigo = {'texto': areaDoCodigo.querySelector('code').innerText}
    areaDoCodigo.innerHTML = `<code class="preview hljs ${linguagem.value}" contenteditable="true" aria-label="editor"></code>`
    areaDoCodigo.firstChild.innerText = codigo.texto
}

linguagem.addEventListener('change', () => {
    mudaLinguagem()
})

botao.addEventListener('click', () => {
    const codigo = areaDoCodigo.querySelector('code')
    hljs.highlightBlock(codigo)
})

Agora precisamos mudar algumas coisas no arquivo HTML. Começando com a remoção da tag <pre>. Depois vamos aproveitar e adicionar a classe hljs dentro da tag <code>. Não precisamos mais chamar a função do highlight.js em uma tag <script>, então essa linha pode ser apagada. E no final, logo após a importação do arquivo do highlight.js vamos adicionar o arquivo index.js que acabamos de criar.

O arquivo index.html:

...
<body spellcheck="false">
    <main class="main">
        <section class="cartao">
            <label for="linguagem" class="label">Escolha a linguagem</label>
            <select name="linguagem" id="linguagem" class="linguagem">
                <option value="javascript">JavaScript</option>
                <option value="html">HTML</option>
                <option value="css">CSS</option>
            </select>
            <div class="codigo-wrapper">
                <code class="preview hljs" contenteditable="true" aria-label="editor"></code>
            </div>
            <button class="botao">preview</button>
        </section>
    </main>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/highlight.min.js"></script>
    <script src="index.js"></script>
</body>
...

Testando agora no navegador, teremos:

Resultado com o highlight.js na linguagem JavaScript
Resultado com o highlight.js na linguagem HTML
Resultado com o highlight.js na linguagem CSS

E assim montamos nosso editor de código utilizando destaque de sintaxe.

Gostou do conteúdo e quer aprender mais sobre o assunto? Então acesse nossas formações e mergulhe nesse mar do Front-end: