Skip to content

Blocos de código cercados

Os fenced code blocks são parte importante da sintaxe estendida do Markdown: oferecem apresentação de código mais poderosa do que blocos indentados, com realce de sintaxe, números de linha, título/ficheiro, diffs, entre outros.

Blocos básicos

Três crases

Cria um bloco usando três crases ```:

markdown
```
function hello() {
    console.log("Hello, World!");
}
```

Resultado:

function hello() {
    console.log("Hello, World!");
}

Três tis ~~~

Também é possível usar ~~~:

markdown
~~~
function hello() {
    console.log("Hello, World!");
}
~~~

Resultado:

function hello() {
    console.log("Hello, World!");
}

Realce de sintaxe

Especificar linguagem

Indica a linguagem após as crases iniciais para ativar o highlight:

markdown
```javascript
function fibonacci(n) {
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

console.log(fibonacci(10)); // 55
```

Resultado:

javascript
function fibonacci(n) {
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

console.log(fibonacci(10)); // 55

Exemplos de linguagens comuns

Python

markdown
```python
def quicksort(arr):
    if len(arr) <= 1:
        return arr
    
    pivot = arr[len(arr) // 2]
    left = [x for x in arr if x < pivot]
    middle = [x for x in arr if x == pivot]
    right = [x for x in arr if x > pivot]
    
    return quicksort(left) + middle + quicksort(right)

# 示例使用
numbers = [3, 6, 8, 10, 1, 2, 1]
print(quicksort(numbers))
```

Resultado:

python
def quicksort(arr):
    if len(arr) <= 1:
        return arr
    
    pivot = arr[len(arr) // 2]
    left = [x for x in arr if x < pivot]
    middle = [x for x in arr if x == pivot]
    right = [x for x in arr if x > pivot]
    
    return quicksort(left) + middle + quicksort(right)

# 示例使用
numbers = [3, 6, 8, 10, 1, 2, 1]
print(quicksort(numbers))

TypeScript

markdown
```typescript
interface User {
    id: number;
    name: string;
    email: string;
    isActive: boolean;
}

class UserService {
    private users: User[] = [];

    async createUser(userData: Omit<User, 'id'>): Promise<User> {
        const newUser: User = {
            id: Date.now(),
            ...userData
        };
        
        this.users.push(newUser);
        return newUser;
    }

    async getUserById(id: number): Promise<User | undefined> {
        return this.users.find(user => user.id === id);
    }
}
```

Resultado:

typescript
interface User {
    id: number;
    name: string;
    email: string;
    isActive: boolean;
}

class UserService {
    private users: User[] = [];

    async createUser(userData: Omit<User, 'id'>): Promise<User> {
        const newUser: User = {
            id: Date.now(),
            ...userData
        };
        
        this.users.push(newUser);
        return newUser;
    }

    async getUserById(id: number): Promise<User | undefined> {
        return this.users.find(user => user.id === id);
    }
}

Go

markdown
```go
package main

import (
    "fmt"
    "net/http"
    "log"
)

type Server struct {
    port string
}

func NewServer(port string) *Server {
    return &Server{port: port}
}

func (s *Server) Start() error {
    http.HandleFunc("/", s.handleHome)
    http.HandleFunc("/api/health", s.handleHealth)
    
    fmt.Printf("Server starting on port %s\n", s.port)
    return http.ListenAndServe(":"+s.port, nil)
}

func (s *Server) handleHome(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Welcome to Go Server!")
}

func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    fmt.Fprintf(w, `{"status": "healthy"}`)
}

func main() {
    server := NewServer("8080")
    log.Fatal(server.Start())
}
```

Resultado:

go
package main

import (
    "fmt"
    "net/http"
    "log"
)

type Server struct {
    port string
}

func NewServer(port string) *Server {
    return &Server{port: port}
}

func (s *Server) Start() error {
    http.HandleFunc("/", s.handleHome)
    http.HandleFunc("/api/health", s.handleHealth)
    
    fmt.Printf("Server starting on port %s\n", s.port)
    return http.ListenAndServe(":"+s.port, nil)
}

func (s *Server) handleHome(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Welcome to Go Server!")
}

func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    fmt.Fprintf(w, `{"status": "healthy"}`)
}

func main() {
    server := NewServer("8080")
    log.Fatal(server.Start())
}

Funcionalidades avançadas

Realce de linhas

Alguns processadores suportam destacar linhas específicas:

markdown
```javascript {2,4-6}
function calculateTotal(items) {
    let total = 0; // esta linha em destaque
    
    for (const item of items) { // estas linhas em destaque
        total += item.price * item.quantity;
    } // 高亮结束
    
    return total;
}
```

Mostrar números de linha

Mostrar números de linha:

markdown
```python:line-numbers
def binary_search(arr, target):
    left, right = 0, len(arr) - 1
    
    while left <= right:
        mid = (left + right) // 2
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    
    return -1
```

Título/nome do ficheiro

Exibir o nome do ficheiro do código:

markdown
```typescript title="userService.ts"
export class UserService {
    private apiUrl = '/api/users';

    async getUsers(): Promise<User[]> {
        const response = await fetch(this.apiUrl);
        return response.json();
    }

    async createUser(user: CreateUserDto): Promise<User> {
        const response = await fetch(this.apiUrl, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(user)
        });
        return response.json();
    }
}
```

Diferenças (diff) em blocos

Mostrar alterações de código:

markdown
```diff
function calculateTax(amount) {
-   return amount * 0.05; // 旧的税率
+   return amount * 0.08; // 新的税率
}

+ // 新增的函数
+ function calculateDiscount(amount, percentage) {
+     return amount * (percentage / 100);
+ }
```

渲染效果

diff
function calculateTax(amount) {
-   return amount * 0.05; // 旧的税率
+   return amount * 0.08; // 新的税率
}

+ // 新增的函数
+ function calculateDiscount(amount, percentage) {
+     return amount * (percentage / 100);
+ }

Exemplos de configuração

JSON

markdown
```json
{
  "name": "my-app",
  "version": "1.0.0",
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon server.js",
    "build": "webpack --mode production",
    "test": "jest"
  },
  "dependencies": {
    "express": "^4.18.2",
    "mongoose": "^7.0.3",
    "jsonwebtoken": "^9.0.0"
  },
  "devDependencies": {
    "nodemon": "^2.0.22",
    "jest": "^29.5.0",
    "webpack": "^5.82.0"
  }
}
```

Resultado:

json
{
  "name": "my-app",
  "version": "1.0.0",
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon server.js",
    "build": "webpack --mode production",
    "test": "jest"
  },
  "dependencies": {
    "express": "^4.18.2",
    "mongoose": "^7.0.3",
    "jsonwebtoken": "^9.0.0"
  },
  "devDependencies": {
    "nodemon": "^2.0.22",
    "jest": "^29.5.0",
    "webpack": "^5.82.0"
  }
}

YAML

markdown
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  labels:
    app: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
      - name: web
        image: nginx:1.21
        ports:
        - containerPort: 80
        env:
        - name: NODE_ENV
          value: production
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"
```

Resultado:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  labels:
    app: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
      - name: web
        image: nginx:1.21
        ports:
        - containerPort: 80
        env:
        - name: NODE_ENV
          value: production
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"

SQL

markdown
```sql
-- 创建用户表
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 创建索引
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_username ON users(username);

-- 查询活跃用户
SELECT 
    u.id,
    u.username,
    u.email,
    COUNT(p.id) as post_count
FROM users u
LEFT JOIN posts p ON u.id = p.user_id
WHERE u.created_at >= NOW() - INTERVAL '30 days'
GROUP BY u.id, u.username, u.email
HAVING COUNT(p.id) > 0
ORDER BY post_count DESC
LIMIT 10;
```

Resultado:

sql
-- 创建用户表
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 创建索引
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_username ON users(username);

-- 查询活跃用户
SELECT 
    u.id,
    u.username,
    u.email,
    COUNT(p.id) as post_count
FROM users u
LEFT JOIN posts p ON u.id = p.user_id
WHERE u.created_at >= NOW() - INTERVAL '30 days'
GROUP BY u.id, u.username, u.email
HAVING COUNT(p.id) > 0
ORDER BY post_count DESC
LIMIT 10;

Shell e comandos

Bash

markdown
```bash
#!/bin/bash

# Script de deploy
set -e

APP_NAME="my-app"
DEPLOY_DIR="/var/www/${APP_NAME}"
BACKUP_DIR="/var/backups/${APP_NAME}"
CURRENT_DATE=$(date +%Y%m%d_%H%M%S)

echo "Iniciar deploy de ${APP_NAME}..."

# Criar backup
if [ -d "$DEPLOY_DIR" ]; then
    echo "A criar backup em ${BACKUP_DIR}/${CURRENT_DATE}"
    mkdir -p "$BACKUP_DIR"
    cp -r "$DEPLOY_DIR" "${BACKUP_DIR}/${CURRENT_DATE}"
fi

# Parar serviço
echo "Parar serviço..."
sudo systemctl stop $APP_NAME || true

# Desplegar nova versão
echo "Deploy de nova versão..."
rm -rf "$DEPLOY_DIR"
mkdir -p "$DEPLOY_DIR"
tar -xzf "${APP_NAME}.tar.gz" -C "$DEPLOY_DIR"

# Instalar dependências
echo "Instalar dependências..."
cd "$DEPLOY_DIR"
npm ci --production

# Iniciar serviço
echo "Iniciar serviço..."
sudo systemctl start $APP_NAME
sudo systemctl enable $APP_NAME

echo "Deploy concluído!"
```

Resultado:

bash
#!/bin/bash

# Script de deploy
set -e

APP_NAME="my-app"
DEPLOY_DIR="/var/www/${APP_NAME}"
BACKUP_DIR="/var/backups/${APP_NAME}"
CURRENT_DATE=$(date +%Y%m%d_%H%M%S)

echo "Iniciar deploy de ${APP_NAME}..."

# 创建备份
if [ -d "$DEPLOY_DIR" ]; then
echo "A criar backup em ${BACKUP_DIR}/${CURRENT_DATE}"
    mkdir -p "$BACKUP_DIR"
    cp -r "$DEPLOY_DIR" "${BACKUP_DIR}/${CURRENT_DATE}"
fi

# 停止服务
echo "Parar serviço..."
sudo systemctl stop $APP_NAME || true

# 部署新版本
echo "Deploy de nova versão..."
rm -rf "$DEPLOY_DIR"
mkdir -p "$DEPLOY_DIR"
tar -xzf "${APP_NAME}.tar.gz" -C "$DEPLOY_DIR"

# 安装依赖
echo "Instalar dependências..."
cd "$DEPLOY_DIR"
npm ci --production

# 启动服务
echo "Iniciar serviço..."
sudo systemctl start $APP_NAME
sudo systemctl enable $APP_NAME

echo "Deploy concluído!"

Erros comuns e soluções

1) Número de crases incorreto

markdown
❌ 错误:
```javascript
function hello() {
    console.log("Hello");
}
``  ← apenas duas crases

✅ 正确:
```javascript
function hello() {
    console.log("Hello");
}
```  ← três crases

2) Identificador de linguagem errado

markdown
❌ Incorreto:
```js  ← alguns processadores não reconhecem
function hello() {}
```

✅ Recomendado:
```javascript  ← usar nome completo
function hello() {}
```

3) Blocos aninhados

markdown
❌ Problema: não exibe código que contém ```

✅ Solução: usar quatro crases a envolver três
````markdown
```javascript
console.log("hello");
```

### 4) Caracteres especiais

````markdown
```markdown
<!-- mostrar sintaxe markdown dentro de bloco markdown -->
\```javascript  ← 转义反引号
code here
\```
```

Lista de linguagens suportadas

Linguagens de programação

语言标识符别名
JavaScriptjavascriptjs
TypeScripttypescriptts
Pythonpythonpy
Javajava
C++cppc++, cxx
C#csharpcs
Gogogolang
Rustrustrs
PHPphp
Rubyrubyrb
Swiftswift
Kotlinkotlinkt

Marcação e configuração

语言标识符用途
HTMLhtmlmarcação
CSScssestilos
XMLxmldados
JSONjsondados
YAMLyaml, ymlconfiguração
TOMLtomlconfiguração
Markdownmarkdown, mddocumentação

Dados e consulta

语言标识符用途
SQLsql数据库查询
GraphQLgraphqlAPI查询
Rr统计计算
MATLABmatlab数值计算

Shell e script

语言标识符用途
Bashbash, shUnix Shell
PowerShellpowershell, ps1Windows Shell
Batchbatch, batWindows 批处理
Dockerfiledockerfile容器配置

Boas práticas

1) Linguagem correta

markdown
✅ Recomenda-se usar identificador preciso
```typescript
interface User {
    id: number;
    name: string;
}
```

❌ Evitar identificador errado
```javascript  ← 这是 TypeScript 代码
interface User {
    id: number;
    name: string;
}
```

2) Comentários significativos

markdown
✅ Comentar explicando o essencial
```python
def fibonacci(n):
"""Calcula o n-ésimo termo de Fibonacci"""
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)
```

❌ Evitar código sem contexto
```python
def fib(n):
    if n <= 1:
        return n
    return fib(n-1) + fib(n-2)
```

3) Mantenha o código conciso

markdown
✅ Mostrar apenas a lógica central
```javascript
// 用户认证中间件
function authenticate(req, res, next) {
    const token = req.headers.authorization;
    if (!token) {
        return res.status(401).json({ error: 'No token provided' });
    }
    // 验证逻辑...
    next();
}
```

❌ Evitar detalhes desnecessários
```javascript
// 省略大量无关代码...
```

4) Exibir nome do ficheiro

markdown
✅ Mostrar nome de ficheiro
```javascript title="middleware/auth.js"
export function authenticate(req, res, next) {
    // 认证逻辑
}
```

✅ Mostrar nome de ficheiro de configuração
```json title="package.json"
{
  "name": "my-app",
  "version": "1.0.0"
}
```

Casos práticos

1) Documentação de API

markdown
## 用户登录 API

**Pedido:**

```bash
curl -X POST https://api.example.com/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "password123"
  }'
```

**Resposta:**

```json
{
  "success": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "user": {
      "id": 1,
      "email": "user@example.com",
      "name": "Zhang"
    }
  }
}
```

**Erro:**

```json
{
  "success": false,
  "error": {
    "code": "INVALID_CREDENTIALS",
    "message": "Invalid email or password"
  }
}
```

2) Guia de instalação

markdown
## Ambiente

### 1. 安装 Node.js

**macOS (Homebrew):**

```bash
# Instalar Homebrew (se necessário)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Instalar Node.js
brew install node

# Verificar
node --version
npm --version
```

**Ubuntu/Debian:**

```bash
# Atualizar lista
sudo apt update

# Instalar Node.js e npm
sudo apt install nodejs npm

# Verificar
node --version
npm --version
```

**Windows (Chocolatey):**

```powershell
# Instalar Chocolatey (Admin)
Set-ExecutionPolicy Bypass -Scope Process -Force; 
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; 
iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

# Instalar Node.js
choco install nodejs

# Verificar
node --version
npm --version
```

3) Comparação antes/depois

markdown
## 重构前后对比

**Antes (callback hell):**

```javascript
function getUserData(userId, callback) {
    getUser(userId, function(err, user) {
        if (err) {
            callback(err);
            return;
        }
        
        getPosts(user.id, function(err, posts) {
            if (err) {
                callback(err);
                return;
            }
            
            getComments(posts[0].id, function(err, comments) {
                if (err) {
                    callback(err);
                    return;
                }
                
                callback(null, { user, posts, comments });
            });
        });
    });
}
```

**Depois (async/await):**

```javascript
async function getUserData(userId) {
    try {
        const user = await getUser(userId);
        const posts = await getPosts(user.id);
        const comments = await getComments(posts[0].id);
        
        return { user, posts, comments };
    } catch (error) {
        throw error;
    }
}
```

Saída HTML

Conversão para HTML:

markdown
```javascript
function hello() {
    console.log("Hello");
}
```

Converte para:

html
<pre><code class="language-javascript">
function hello() {
    console.log("Hello");
}
</code></pre>

Sintaxe relacionada

Exercícios

Cria:

  1. Uma coleção de exemplos em várias linguagens
  2. Um tutorial de API (pedido e resposta)
  3. Um guia de deploy (script)
  4. Um script SQL de desenho da BD

Ferramentas e plugins

Realce de sintaxe

  • Prism.js: leve
  • highlight.js: completo
  • CodeMirror: editor online
  • Monaco Editor: núcleo do VS Code

Processadores Markdown

  • markdown-it: extensível
  • remark: ecossistema unified
  • marked: rápido
  • gray-matter: front matter

Plugins de editor

  • VS Code: Markdown Preview Enhanced
  • Sublime Text: MarkdownEditing
  • Atom: markdown-preview-plus
  • Vim: vim-markdown

Construído por www.markdownlang.com