---
read_when:
    - คุณกำลังเปลี่ยนการจัดรูปแบบ Markdown หรือการแบ่งส่วนสำหรับช่องทางขาออก
    - คุณกำลังเพิ่มตัวจัดรูปแบบช่องทางใหม่หรือการแมปสไตล์ใหม่
    - คุณกำลังดีบักการถดถอยด้านการจัดรูปแบบในหลายช่องทาง
summary: ไปป์ไลน์การจัดรูปแบบ Markdown สำหรับช่องทางขาออก
title: การจัดรูปแบบ Markdown
x-i18n:
    generated_at: "2026-05-12T12:50:47Z"
    model: gpt-5.5
    provider: openai
    source_hash: 8db92aaf1063ebcbd8630dfcb8ca0a4e9eeb1c64f5b8868bf11c836777180515
    source_path: concepts/markdown-formatting.md
    workflow: 16
---

OpenClaw จัดรูปแบบ Markdown ขาออกโดยแปลงเป็นตัวแทนกลางร่วม
(IR) ก่อนเรนเดอร์เอาต์พุตเฉพาะช่องทาง IR จะคงข้อความต้นฉบับไว้ครบถ้วน
พร้อมเก็บช่วงสไตล์/ลิงก์ เพื่อให้การแบ่งชิ้นและการเรนเดอร์
คงความสอดคล้องกันข้ามช่องทางได้

## เป้าหมาย

- **ความสอดคล้อง:** ขั้นตอนแยกวิเคราะห์เดียว เรนเดอร์ได้หลายแบบ
- **การแบ่งชิ้นอย่างปลอดภัย:** แยกข้อความก่อนเรนเดอร์ เพื่อให้การจัดรูปแบบแบบอินไลน์ไม่
  ขาดระหว่างชิ้น
- **เหมาะกับช่องทาง:** แมป IR เดียวกันไปยัง Slack mrkdwn, Telegram HTML และช่วงสไตล์ของ Signal
  โดยไม่ต้องแยกวิเคราะห์ Markdown ซ้ำ

## ไปป์ไลน์

1. **แยกวิเคราะห์ Markdown -> IR**
   - IR คือข้อความธรรมดาพร้อมช่วงสไตล์ (bold/italic/strike/code/spoiler) และช่วงลิงก์
   - ออฟเซ็ตเป็นหน่วยโค้ด UTF-16 เพื่อให้ช่วงสไตล์ของ Signal ตรงกับ API ของมัน
   - ตารางจะถูกแยกวิเคราะห์เฉพาะเมื่อช่องทางเลือกใช้การแปลงตาราง
2. **แบ่ง IR เป็นชิ้น (รูปแบบมาก่อน)**
   - การแบ่งชิ้นเกิดขึ้นบนข้อความ IR ก่อนเรนเดอร์
   - การจัดรูปแบบแบบอินไลน์จะไม่ถูกแยกระหว่างชิ้น ช่วงต่างๆ จะถูกตัดแบ่งต่อชิ้น
3. **เรนเดอร์ตามช่องทาง**
   - **Slack:** โทเค็น mrkdwn (bold/italic/strike/code), ลิงก์เป็น `<url|label>`
   - **Telegram:** แท็ก HTML (`<b>`, `<i>`, `<s>`, `<code>`, `<pre><code>`, `<a href>`)
   - **Signal:** ข้อความธรรมดา + ช่วง `text-style`; ลิงก์จะกลายเป็น `label (url)` เมื่อป้ายกำกับต่างจาก URL

## ตัวอย่าง IR

Markdown อินพุต:

```markdown
Hello **world** - see [docs](https://docs.openclaw.ai).
```

IR (แผนผัง):

```json
{
  "text": "Hello world - see docs.",
  "styles": [{ "start": 6, "end": 11, "style": "bold" }],
  "links": [{ "start": 19, "end": 23, "href": "https://docs.openclaw.ai" }]
}
```

## ใช้ที่ไหน

- อะแดปเตอร์ขาออกของ Slack, Telegram และ Signal เรนเดอร์จาก IR
- ช่องทางอื่นๆ (WhatsApp, iMessage, Microsoft Teams, Discord) ยังใช้ข้อความธรรมดาหรือ
  กฎการจัดรูปแบบของตนเอง โดยใช้การแปลงตาราง Markdown ก่อน
  การแบ่งชิ้นเมื่อเปิดใช้งาน

## การจัดการตาราง

ไคลเอนต์แชตต่างๆ รองรับตาราง Markdown ไม่สอดคล้องกัน ใช้
`markdown.tables` เพื่อควบคุมการแปลงต่อช่องทาง (และต่อบัญชี)

- `code`: เรนเดอร์ตารางเป็นบล็อกโค้ด (ค่าเริ่มต้นสำหรับช่องทางส่วนใหญ่)
- `bullets`: แปลงแต่ละแถวเป็นรายการหัวข้อย่อย (ค่าเริ่มต้นสำหรับ Matrix, Signal และ WhatsApp)
- `off`: ปิดการแยกวิเคราะห์และการแปลงตาราง ข้อความตารางดิบจะถูกส่งผ่านไป

คีย์การกำหนดค่า:

```yaml
channels:
  discord:
    markdown:
      tables: code
    accounts:
      work:
        markdown:
          tables: off
```

## กฎการแบ่งชิ้น

- ขีดจำกัดชิ้นมาจากอะแดปเตอร์/การกำหนดค่าของช่องทาง และจะนำไปใช้กับข้อความ IR
- รั้วโค้ดจะถูกรักษาไว้เป็นบล็อกเดียวพร้อมขึ้นบรรทัดใหม่ท้ายบล็อก เพื่อให้ช่องทาง
  เรนเดอร์ได้ถูกต้อง
- คำนำหน้ารายการและคำนำหน้า blockquote เป็นส่วนหนึ่งของข้อความ IR ดังนั้นการแบ่งชิ้น
  จะไม่แยกกลางคำนำหน้า
- สไตล์แบบอินไลน์ (bold/italic/strike/inline-code/spoiler) จะไม่ถูกแยกข้าม
  ชิ้น ตัวเรนเดอร์จะเปิดสไตล์ใหม่ภายในแต่ละชิ้น

หากต้องการข้อมูลเพิ่มเติมเกี่ยวกับพฤติกรรมการแบ่งชิ้นข้ามช่องทาง ดู
[การสตรีม + การแบ่งชิ้น](/th/concepts/streaming)

## นโยบายลิงก์

- **Slack:** `[label](url)` -> `<url|label>`; URL เปล่าจะคงเป็น URL เปล่า Autolink
  ถูกปิดระหว่างแยกวิเคราะห์เพื่อหลีกเลี่ยงการลิงก์ซ้ำ
- **Telegram:** `[label](url)` -> `<a href="url">label</a>` (โหมดแยกวิเคราะห์ HTML)
- **Signal:** `[label](url)` -> `label (url)` เว้นแต่ป้ายกำกับตรงกับ URL

## สปอยเลอร์

เครื่องหมายสปอยเลอร์ (`||spoiler||`) จะถูกแยกวิเคราะห์เฉพาะสำหรับ Signal ซึ่งแมปไปยัง
ช่วงสไตล์ SPOILER ช่องทางอื่นๆ จะถือเป็นข้อความธรรมดา

## วิธีเพิ่มหรืออัปเดตตัวจัดรูปแบบช่องทาง

1. **แยกวิเคราะห์ครั้งเดียว:** ใช้ตัวช่วย `markdownToIR(...)` ที่ใช้ร่วมกัน พร้อมตัวเลือก
   ที่เหมาะกับช่องทาง (autolink, สไตล์หัวเรื่อง, คำนำหน้า blockquote)
2. **เรนเดอร์:** ติดตั้งตัวเรนเดอร์ด้วย `renderMarkdownWithMarkers(...)` และ
   แมปเครื่องหมายสไตล์ (หรือช่วงสไตล์ของ Signal)
3. **แบ่งชิ้น:** เรียก `chunkMarkdownIR(...)` ก่อนเรนเดอร์ แล้วเรนเดอร์แต่ละชิ้น
4. **เชื่อมอะแดปเตอร์:** อัปเดตอะแดปเตอร์ขาออกของช่องทางให้ใช้ตัวแบ่งชิ้น
   และตัวเรนเดอร์ใหม่
5. **ทดสอบ:** เพิ่มหรืออัปเดตการทดสอบรูปแบบ และการทดสอบการส่งขาออกหาก
   ช่องทางใช้การแบ่งชิ้น

## ข้อควรระวังทั่วไป

- โทเค็นวงเล็บมุมของ Slack (`<@U123>`, `<#C123>`, `<https://...>`) ต้องถูก
  รักษาไว้; escape HTML ดิบอย่างปลอดภัย
- HTML ของ Telegram ต้อง escape ข้อความนอกแท็กเพื่อหลีกเลี่ยงมาร์กอัปที่เสีย
- ช่วงสไตล์ของ Signal ขึ้นกับออฟเซ็ต UTF-16; อย่าใช้ออฟเซ็ตแบบจุดรหัส
- รักษาขึ้นบรรทัดใหม่ท้ายบล็อกสำหรับบล็อกโค้ดแบบมีรั้ว เพื่อให้เครื่องหมายปิดอยู่บน
  บรรทัดของตัวเอง

## ที่เกี่ยวข้อง

<CardGroup cols={2}>
  <Card title="Streaming and chunking" href="/th/concepts/streaming" icon="bars-staggered">
    พฤติกรรมการสตรีมขาออก ขอบเขตชิ้น และการส่งเฉพาะช่องทาง
  </Card>
  <Card title="System prompt" href="/th/concepts/system-prompt" icon="message-lines">
    สิ่งที่โมเดลเห็นก่อนการสนทนา รวมถึงไฟล์เวิร์กสเปซที่ถูกแทรก
  </Card>
</CardGroup>
