Pular para o conteúdo

Markdown e MDX

Markdown é comumente usado para criar conteúdo com muito texto, como postagens de blog e documentação. Astro inclui suporte nativo para arquivos Markdown padrão que também incluem o frontmatter YAML para definir metadados customizados como um título, descrição e etiquetas.

Com a integração @astrojs/mdx instalada, Astro também suporta arquivos MDX (.mdx) que trazem alguns recursos adicionais como suporte para expressões JavaScript e componentes direto do seu conteúdo Markdown.

Use um ou ambos os tipos de arquivo para escrever seu conteúdo Markdown!

Você pode gerenciar seus arquivos Markdown e MDX no Astro em um diretório especial src/content/. Coleções de conteúdo te ajudam a organizar seu conteúdo, validar seu frontmatter e a providenciar segurança de tipos do TypeScript automaticamente enquanto trabalha no seu conteúdo.

  • Directorysrc/content/
    • Directorynewsletter/
      • semana-1.md
      • semana-2.md
    • Directoryautores/
      • grace-hopper.md
      • alan-turing.md

Veja mais sobre como utilizar coleções de conteúdo no Astro.

Astro trata qualquer arquivo .md (ou extensão alternativa suportada) ou .mdx dentro do diretório /src/pages/ como uma página.

Colocar um arquivo nesse diretório, ou em qualquer subdiretório, criará automaticamente uma rota de página usando o nome do caminho do arquivo.

src/pages/pagina-1.md
---
titulo: Olá, Mundo
---
# E aí!
Este arquivo Markdown cria uma página em `seu-dominio.com/pagina-1/`
Provavelmente não está muito estiloso, porém o Markdown suporta:
- **negrito** e _itálico._
- listas
- [links](https://astro.build)
- e mais!

📚 Leia mais sobre o roteamento baseado em arquivos do Astro ou opções para criar rotas dinâmicas.

Astro providencia algumas funcionalidades extras integradas ao Markdown, disponíveis ao se utilizar arquivos Markdown ou MDX.

Astro fornece páginas Markdown e MDX com a propriedade frontmatter especial layout, que pode especificar o caminho relativo (ou atalho) para um componente de layout Astro.

src/pages/postagens/postagem-1.md
---
layout: ../../layouts/LayoutPostagemBlog.astro
titulo: Astro em resumo
autor: Himanshu
descricao: Descubra o que faz o Astro incrível!
---
Esta é uma postagem escrita em Markdown.

Propriedades específicas são estão disponíveis ao componente de layout através de Astro.props. Por exemplo, você pode acessar propriedades do frontmatter através de Astro.props.frontmatter:

src/layouts/LayoutPostagemBlog.astro
---
const {frontmatter} = Astro.props;
---
<html>
<!-- ... -->
<h1>{frontmatter.titulo}</h1>
<h2>Autor da postagem: {frontmatter.autor}</h2>
<p>{frontmatter.descricao}<p>
<slot /> <!-- conteúdo Markdown é inserido aqui -->
<!-- ... -->
</html>

Você também pode estilizar seu Markdown no seu componente de layout.

📚 Aprenda mais sobre Layouts Markdown.

Usar títulos no Markdown e MDX irá automaticamente te dar links de âncora para que você possa direcionar a certas seções da sua página.

src/pages/pagina-1.md
---
title: Minha página de conteúdo
---
## Introdução
Eu posso fazer um link interno para [minha conclusão](#conclusão) na mesma página ao escrever Markdown.
## Conclusão
Eu posso utilizar a URL `https://exemplo.com/pagina-1/#introdução` para navegar diretamente para a Introdução da minha página.

Certos caracteres tem um significado especial no Markdown e MDX. Você pode precisar usar uma sintaxe diferente se quiser mostrá-los. Para fazer isso, você pode utilizar entidades HTML para esses caracteres no lugar.

Por exemplo, para prevenir < de ser interpretado como o começo de um elemento HTML, escreva &lt;. Ou, para prevenir { de ser interpretado como o começo de uma expressão do JavaScript no MDX, escreva &lcub;.

Adicionar a integração MDX do Astro aprimora sua experiência de autoria com Markdown com variáveis JSX, expressões e componentes.

Ela também adiciona funcionalidades extras ao MDX padrão, incluindo suporte para frontmatter estilo Markdown no MDX. Isso te permite utilizar a maioria das funcionalidades integradas para Markdown do Astro como a propriedade frontmatter layout.

Arquivos .mdx devem ser escritos na sintaxe do MDX ao invés da sintaxe semelhante ao HTML do Astro.

MDX suporta o uso de declarações export para adicionar variáveis ao seu conteúdo MDX. Estas variáveis são acessíveis tanto no próprio template quanto como propriedades nomeadas ao importar o arquivo em outro lugar.

Por exemplo, você pode exportar um campo titulo de uma página MDX ou componente para usar como um título com {expressões JSX}:

/src/pages/postagens/postagem-1.mdx
export const titulo = 'Minha primeira postagem MDX'
# {titulo}

A integração MDX do Astro inclui suporte para utilizar frontmatter no MDX por padrão. Adicione propriedades frontmatter assim como você faria em arquivos Markdown, e essas variáveis são acessíveis para uso dentro do template, em seu componente layout, e como propriedades nomeadas ao importar o arquivo em outro lugar.

/src/pages/postagens/postagem-1.mdx
---
layout: '../../layouts/LayoutPostagemBlog.astro'
titulo: 'Minha primeira postagem MDX'
---
# {frontmatter.titulo}

Após instalar a integração MDX, você pode importar e utilizar tanto componentes Astro quanto componentes de frameworks de UI em arquivos MDX (.mdx) assim como você os usaria em qualquer outro componente Astro..

Não se esqueça de adicionar uma client:diretiva em seus componentes de frameworks de UI, se necessário!

Veja mais exemplos da utilização de declarações de importação e exportação na documentação do MDX.

src/pages/sobre.mdx
---
layout: ../layouts/LayoutBase.astro
titulo: Sobre mim
---
import Botao from '../components/Botao.astro';
import ContagemReact from '../components/ContagemReact.jsx';
Eu vivo em **Marte** mas sinta-se livre para <Botao title="me contatar" />.
Aqui está meu componente de contagem, funcionando no MDX:
<ContagemReact client:load />

Definindo Componentes Customizados a elementos HTML

Seção intitulada Definindo Componentes Customizados a elementos HTML

Com MDX, você pode mapear a sintaxe Markdown a componentes customizados ao invés de seus elementos HTML padrões. Isso te permite escrever sintaxe padrão do Markdown enquanto aplica a estilização especial de componentes aos elementos selecionados.

Importe seu componente customizado em seu arquivo .mdx, então exporte um objeto components que mapeia o elemento padrão do HTML ao seu elemento customizado:

src/pages/about.mdx
import Citacao from '../components/Citacao.astro';
export const components = {blockquote: Citacao}
> Esta citação será um blockquote customizado
src/components/Citacao.astro
---
const props = Astro.props;
---
<blockquote {...props} class="bg-blue-50 p-4">
<span class="text-4xl text-blue-600 mb-2"></span>
<slot /> <!-- Certifique-se de adicionar um `<slot/>` para conteúdo filho! -->
</blockquote>

Visite o site do MDX para uma lista completa de elementos HTML que podem ser sobrescritos como componentes customizados.

Você pode importar arquivos Markdown e MDX diretamente em seus arquivos Astro. Isso te dá acesso ao seu conteúdo Markdown, assim como a outras propriedades como valores do frontmatter que podem ser utilizados em expressões estilo JSX do Astro.

Você pode importar uma página específica com import ou múltiplas páginas com Astro.glob().

src/pages/index.astro
---
// Importe um único arquivo
import * as minhaPostagem from '../pages/postagens/minha-postagem.md';
// Importe múltiplos arquivos com Astro.glob
const postagens = await Astro.glob('../pages/postagens/*.md');
---

Quando você importa arquivos Markdown e MDX em um componente Astro, você recebe um objeto contendo suas propriedades exportadas.

/src/pages/postagens/otima-postagem.md
---
titulo: 'A melhor postagem de todos os tempos'
author: 'Ben'
---
Aqui está minha _ótima_ postagem!
src/pages/minhas-postagens.astro
---
import * as otimaPostagem from '../pages/postagens/otima-postagem.md';
const postagens = await Astro.glob('../pages/postagens/*.md');
---
<p>{otimaPostagem.frontmatter.titulo}</p>
<p>Escrito por: {otimaPostagem.frontmatter.autor}</p>
<p>Arquivo de Postagens:</p>
<ul>
{postagens.map(postagem => <li><a href={postagem.url}>{postagem.frontmatter.titulo}</a></li>)}
</ul>

Em arquivos MDX, você pode acessar propriedades tanto do frontmatter quanto de declarações de export:

/src/pages/posts/postagem-mdx.mdx
---
titulo: 'A melhor postagem de todos os tempos'
autor: 'Ben'
---
export const descricao = 'Fique confortável! Esta será uma ótima leitura.'
Aqui está minha _ótima_ postagem!
src/pages/minhas-postagens.astro
---
import * as otimaPostagem from '../pages/postagens/postagem-mdx.mdx';
---
<p>{otimaPostagem.frontmatter.titulo}</p>
<p>Escrito por: {otimaPostagem.frontmatter.autor}</p>
<p>{otimaPostagem.descricao}</p>

Opcionalmente, você pode fornecer um tipo para a variável frontmatter usando um generic do TypeScript:

src/pages/index.astro
---
interface Frontmatter {
titulo: string;
descricao?: string;
}
const postagens = await Astro.glob<Frontmatter>('../pages/postagens/*.md');
---
<ul>
{postagens.map(postagem => <li>{postagem.frontmatter.titulo}</li>)}
<!-- postagem.frontmatter.titulo será do tipo `string`! -->
</ul>

As propriedades a seguir são disponibilizadas a um componente .astro ao utilizar uma declaração de import ou Astro.glob():

  • file - O caminho absoluto do arquivo (e.x. /home/usuario/projetos/.../arquivo.md).
  • url - Se for uma página, a URL da página (e.x. /pt-br/guides/markdown-content).
  • frontmatter - Contém quaisquer dados especificados no frontmatter YAML do arquivo.
  • getHeadings - Uma função assíncrona que retorna uma array com todos os títulos (ou seja, elementos h1 -> h6) no arquivo. A slug de cada título corresponde ao ID gerado para certo título e pode ser utilizado para links de âncora. Esta lista segue o tipo: { depth: number; slug: string; text: string }[].
  • Content - Um componente que retorna os conteúdos do arquivo completamente renderizados.
  • (Apenas Markdown) rawContent() - Uma função que retorna o documento Markdown bruto como uma string.
  • (Apenas Markdown) compiledContent() - Uma função que retorna o documento Markdown compilado como uma string de HTML. Note que isso não inclui layouts configurados no seu frontmatter! Apenas o documento Markdown em si será retornado como HTML.
  • (Apenas MDX) - Arquivos MDX também pode exportar dados com uma declaração de export.

Importe Content para renderizar um componente que retorna todo o conteúdo renderizado de um arquivo Markdown ou MDX:

src/pages/conteudo.astro
---
import {Content as BannerPromocional} from '../components/bannerPromocional.md';
---
<h2>Promoção de hoje</h2>
<BannerPromocional />

Exemplo: Roteamento dinâmico de páginas

Seção intitulada Exemplo: Roteamento dinâmico de páginas

Ao invés de colocar seus arquivos Markdown/MDX no diretório src/pages/ para criar rotas, você pode gerar páginas dinamicamente.

Para acessar seu conteúdo Markdown, passe o componente <Content/> através das props da página Astro. Você pode retirar o componente de Astro.props e renderizá-lo no template da sua página.

src/pages/[slug].astro
---
export async function getStaticPaths() {
const postagens = await Astro.glob('../postagens/**/*.md')
return postagens.map(postagem => ({
params: {
slug: postagem.frontmatter.slug
},
props: {
postagem
},
}))
}
const { Content } = Astro.props.postagem
---
<article>
<Content/>
</article>

Arquivos MDX também podem exportar dados com uma declaração de export.

Por exemplo, você pode exportar um campo titulo de uma página MDX ou componente.

/src/pages/postagens/postagem-1.mdx
export const titulo = 'Minha primeira postagem MDX'

Esse titulo será acessível a partir das declarações de import e Astro.glob():

src/pages/index.astro
---
const postagens = await Astro.glob('./*.mdx');
---
{postagens.map(postagem => <p>{postagem.titulo}</p>)}

Componentes customizados com MDX importado

Seção intitulada Componentes customizados com MDX importado

Ao renderizar conteúdo MDX importado, componentes customizados podem ser passados a partir da prop components.

src/pages/pagina.astro
---
import { Content, components } from '../conteudo.mdx';
import Titulo from '../Titulo.astro';
---
<!-- Cria um <h1> customizado para a sintaxe #, _e_ aplica quaisquer componentes customizados definidos em `conteudo.mdx` -->
<Content components={{...components, h1: Titulo }} />

O suporte para Markdown no Astro é fornecido pelo remark, uma poderosa ferramenta de processamento e parsing com um ecossistema ativo. Outros parsers de Markdown como Pandoc e markdown-it não são suportados atualmente.

Astro aplica os plugins GitHub-flavored Markdown e SmartyPants por padrão. Ele trás algumas coisas legais como gerar links clicáveis a partir de texto e formatação para citações e travessões.

Você pode personalizar como o remark faz parse do seu Markdown em astro.config.mjs. Veja a lista completa de opções de configuração do Markdown.

Astro dá suporte a plugins remark e rehype de terceiros para Markdown e MDX. Esses plugins te permitem estender seu Markdown com novas capacidades, como gerar um índice automaticamente, aplicar rótulos acessíveis à emojis e mais.

Nós o encorajamos a explorar o awesome-remark e awesome-rehype para achar mais plugins populares! Veja o README de cada plugin para instruções de instalação.

Este exemplo aplica os plugins remark-toc e rehype-accessible-emojis para ambos arquivos Markdown quanto MDX:

astro.config.mjs
import { defineConfig } from 'astro/config';
import remarkToc from 'remark-toc';
import { rehypeAccessibleEmojis } from 'rehype-accessible-emojis';
export default defineConfig({
markdown: {
// Aplicado para arquivos .md e .mdx
remarkPlugins: [remarkToc],
rehypePlugins: [rehypeAccessibleEmojis],
},
});

Note que por padrão, remarkToc exige um título “ToC” ou “Table of Contents” (não diferencia maiúsculas de minúsculas) na página para mostrar a tabela de conteúdo.

Astro injeta um atributo id a todos os elementos de título (<h1> ao <h6>) em arquivos Markdown e MDX e fornece o utilitário getHeadings() para pegar esses IDs em propriedades exportadas do Markdown.

Você pode customizar os IDs dos títulos adicionando um plugin do rehype que injeta atributos id (e.x. rehype-slug). Seus IDs customizados, ao invés dos padrões do Astro, serão refletidos no HTML resultante e nos itens retornados pelo getHeadings().

Por padrão, Astro injeta atributos id depois que seus plugins do rehype foram executados. Se um dos seus plugins customizados do rehype precisam acessar os IDs injetados pelo Astro, você pode importar e utilizar o plugin rehypeHeadingIds do Astro diretamente. Certifique-se de adicionar rehypeHeadingIds antes de quaisquer plugins que podem depender dele:

astro.config.mjs
import { defineConfig } from 'astro/config';
import { rehypeHeadingIds } from '@astrojs/markdown-remark';
import { outroPluginQueDependeDoHeadingIDs } from 'alguma/fonte/de/plugin';
export default defineConfig({
markdown: {
rehypePlugins: [
rehypeHeadingIds,
outroPluginQueDependeDoHeadingIDs,
],
},
});

Para customizar um plugin, adicione um objeto de opções depois dele envolvidos em um array.

O exemplo abaixo adiciona a opção do título ao plugin remarkToc para alterar onde a tabela de conteúdo é colocada e a opção behavior ao plugin rehype-autolink-headings para adicionar a tag de link após o texto do título.

astro.config.mjs
import remarkToc from 'remark-toc';
import rehypeSlug from 'rehype-slug';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
export default {
markdown: {
remarkPlugins: [ [remarkToc, { heading: "contents"} ] ],
rehypePlugins: [rehypeSlug, [rehypeAutolinkHeadings, { behavior: 'append' }]],
},
}

Modificando frontmatter programaticamente

Seção intitulada Modificando frontmatter programaticamente

Você pode adicionar propriedades de frontmatter a todos os seus arquivos Markdown e MDX utilizando um plugin do remark ou rehype.

  1. Adicione uma propriedadeCustomizada na propriedade data.astro.frontmatter a partir do argumento file do seu plugin:

    plugin-remark-exemplo.mjs
    export function pluginRemarkExemplo() {
    // Todos os plugins do remark ou rehype retornam uma função separada
    return function (tree, file) {
    file.data.astro.frontmatter.propriedadeCustomizada = 'Propriedade gerada';
    }
    }
  2. Aplique o plugin a configuração do markdown ou da integração mdx:

    astro.config.mjs
    import { defineConfig } from 'astro/config';
    import { pluginExemploRemark } from './plugin-exemplo-remark.mjs';
    export default defineConfig({
    markdown: {
    remarkPlugins: [pluginExemploRemark]
    },
    });

    ou

    astro.config.mjs
    import { defineConfig } from 'astro/config';
    import { pluginExemploRemark } from './plugin-exemplo-remark.mjs';
    export default defineConfig({
    integrations: [
    mdx({
    remarkPlugins: [pluginExemploRemark],
    }),
    ],
    });

Agora, todo arquivo Markdown ou MDX terá a propriedadeCustomizada em seu frontmatter, a fazendo disponibilizando quando importar seu Markdown e a partir da propriedade Astro.props.frontmatter em seus layouts.

Receita relacionada: Adicione tempo de leitura

Estendendo a configuração do Markdown a partir do MDX

Seção intitulada Estendendo a configuração do Markdown a partir do MDX

A integração MDX do Astro irá estender a configuração Markdown existente do seu projeto por padrão. Para sobrescrever opções individuais, você pode especificar o seu equivalente na sua configuração do MDX.

O exemplo abaixo desabilita o Markdown estilo GitHub e aplica um diferente conjunto de plugins do remark para arquivos MDX:

astro.config.mjs
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
export default defineConfig({
markdown: {
syntaxHighlight: 'prism',
remarkPlugins: [remarkPlugin1],
gfm: true,
},
integrations: [
mdx({
// `syntaxHighlight` herdado do Markdown
// `remarkPlugins` do Markdown ignorados,
// apenas `pluginRemark2` aplicado.
remarkPlugins: [pluginRemark2],
// `gfm` sobreescrito para `false`
gfm: false,
})
]
});

Para evitar estender sua configuração do Markdown a partir do MDX, defina a opção extendMarkdownConfig (habilitado por padrão) para false:

astro.config.mjs
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
export default defineConfig({
markdown: {
remarkPlugins: [remarkPlugin],
},
integrations: [
mdx({
// Markdown config now ignored
extendMarkdownConfig: false,
// No `remarkPlugins` applied
})
]
});

Astro vem com suporte nativo para Shiki e Prism. Isso fornece syntax highlighting para:

Shiki é ativado por padrão, pré-configurado com o tema github-dark. A saída compilada será limitada a styles inline sem classes CSS de fora, folhas de estilo ou JS no lado do cliente.

Shiki é o nosso syntax highlighter padrão. Você pode configurar todas as opções no objeto shikiConfig assim:

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
markdown: {
shikiConfig: {
// Escolha entre os temas integrados do Shiki (ou adicione o seu)
// https://github.com/shikijs/shiki/blob/main/docs/themes.md
theme: 'dracula',
// Adicione linguagens customizadas
// Nota: Shiki tem muitas linguagens integradas, incluindo .astro!
// https://github.com/shikijs/shiki/blob/main/docs/languages.md
langs: [],
// Habilite quebra de palavras para previnir scroll horizontal
wrap: true,
},
},
});

Ao invés de utilizar um dos temas pré-definidos do Shiki, você pode importar um tema customizado de um arquivo local.

astro.config.mjs
import { defineConfig } from 'astro/config';
import temaCustomizado from './meu-tema-shiki.json';
export default defineConfig({
markdown: {
shikiConfig: { theme: temaCustomizado },
},
});

Nós também sugerimos ler a documentação de temas do próprio Shiki para explorar mais sobre temas, alternância entre tema claro e escuro ou estilização por meio de variáveis CSS.

Mude o Modo de Syntax Highlighting Padrão

Seção intitulada Mude o Modo de Syntax Highlighting Padrão

Se você quiser mudar para o 'prism' por padrão, ou desabilitar syntax highlighting por inteiro, você pode usar o objeto de configuração markdown.syntaxHighlighting:

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
markdown: {
// Pode ser 'shiki' (padrão), 'prism' ou false para desabilitar o highlighting
syntaxHighlight: 'prism',
},
});

Se você optar por usar o Prism, o Astro irá aplicar as classes CSS do Prism no lugar. Note que você precisa trazer sua própria folha de estilos CSS para o syntax highlighting aparecer!

  1. Escolha uma folha de estilos pré-feita disponível nos Temas do Prism.
  2. Adicione essa folha de estilos ao diretório public/ do seu projeto.
  3. Carregue-o na <head> da sua página em um componente de layout a partir de uma tag <link>. (Veja o guia de uso básico do Prism.)

Você também pode visitar a lista de linguagens suportadas pelo Prism para opções e como utilizar.

Astro foi primariamente projetado para arquivos Markdown locais que poderiam ser salvos dentro do diretório do seu projeto. Porém, pode haver certos casos em que você precisa buscar Markdown de uma fonte remota. Por exemplo, você pode precisar buscar e renderizar Markdown de uma API remota quando faz a build do seu site (ou quando um usuário faz uma requisição ao seu website, quando estiver utilizando SSR).

Astro não inclui suporte integrado para Markdown remoto! Para buscar Markdown remoto e renderizá-lo como HTML, você precisará instalar e configurar seu próprio parser Markdown do npm. Ele não irá herdar nenhuma das opções nativas de Markdown e MDX do Astro que você configurou. Certifique-se de que você entende estas limitações antes de implementar isso no seu projeto.

src/pages/exemplo-remoto.astro
---
// Exemplo: Busque Markdown de API remota
// e o renderize como HTML, em runtime.
// Utilizando "marked" (https://github.com/markedjs/marked)
import { marked } from 'marked';
const resposta = await fetch('https://raw.githubusercontent.com/wiki/adam-p/markdown-here/Markdown-Cheatsheet.md');
const markdown = await resposta.text();
const conteudo = marked.parse(markdown);
---
<article set:html={conteudo} />