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)); // 55Exemplos 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 crases2) 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
| 语言 | 标识符 | 别名 |
|---|---|---|
| JavaScript | javascript | js |
| TypeScript | typescript | ts |
| Python | python | py |
| Java | java | |
| C++ | cpp | c++, cxx |
| C# | csharp | cs |
| Go | go | golang |
| Rust | rust | rs |
| PHP | php | |
| Ruby | ruby | rb |
| Swift | swift | |
| Kotlin | kotlin | kt |
Marcação e configuração
| 语言 | 标识符 | 用途 |
|---|---|---|
| HTML | html | marcação |
| CSS | css | estilos |
| XML | xml | dados |
| JSON | json | dados |
| YAML | yaml, yml | configuração |
| TOML | toml | configuração |
| Markdown | markdown, md | documentação |
Dados e consulta
| 语言 | 标识符 | 用途 |
|---|---|---|
| SQL | sql | 数据库查询 |
| GraphQL | graphql | API查询 |
| R | r | 统计计算 |
| MATLAB | matlab | 数值计算 |
Shell e script
| 语言 | 标识符 | 用途 |
|---|---|---|
| Bash | bash, sh | Unix Shell |
| PowerShell | powershell, ps1 | Windows Shell |
| Batch | batch, bat | Windows 批处理 |
| Dockerfile | dockerfile | 容器配置 |
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:
- Uma coleção de exemplos em várias linguagens
- Um tutorial de API (pedido e resposta)
- Um guia de deploy (script)
- 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