Concept internals
การจัดรูปแบบ Markdown
OpenClaw แปลง Markdown ขาออกเป็นตัวแทนข้อมูลกลางร่วม (IR) ก่อนเรนเดอร์ผลลัพธ์เฉพาะช่องทาง IR เก็บข้อความธรรมดาพร้อม ช่วงรูปแบบ/ลิงก์ ดังนั้นการแยกวิเคราะห์เพียงครั้งเดียวจึงใช้ได้กับทุกช่องทาง และการแบ่งส่วนจะไม่ ตัดการจัดรูปแบบกลางช่วง
ไปป์ไลน์
- แยกวิเคราะห์ Markdown เป็น IR (
markdownToIR) - ข้อความธรรมดาพร้อมช่วงรูปแบบ (ตัวหนา ตัวเอียง ขีดฆ่า โค้ด บล็อกโค้ด สปอยเลอร์ ข้อความอ้างอิงแบบบล็อก หัวเรื่องระดับ 1-6) และช่วงลิงก์ ออฟเซ็ตใช้หน่วยโค้ด UTF-16 เพื่อให้ช่วงรูปแบบของ Signal สอดคล้องกับ API ของ Signal โดยตรง ตารางจะถูกแยกวิเคราะห์เฉพาะเมื่อช่องทาง เลือกใช้โหมดตาราง - แบ่ง IR เป็นส่วน (
chunkMarkdownIR/renderMarkdownIRChunksWithinLimit)- การแบ่งจะเกิดขึ้นกับข้อความ IR ก่อนเรนเดอร์ ดังนั้นรูปแบบอินไลน์และ ลิงก์จะถูกตัดตามแต่ละส่วนแทนที่จะขาดตรงขอบเขต
- เรนเดอร์แยกตามช่องทาง (
renderMarkdownWithMarkers) - แมปเครื่องหมายรูปแบบ จะแปลงช่วงต่าง ๆ เป็นมาร์กอัปแบบเนทีฟของช่องทาง
| ช่องทาง | ตัวเรนเดอร์ | หมายเหตุ |
|---|---|---|
| Slack | โทเค็น mrkdwn (*bold*, _italic_, `code`, รั้วโค้ด) |
ลิงก์จะกลายเป็น <url|label>; ปิดการสร้างลิงก์อัตโนมัติระหว่างแยกวิเคราะห์เพื่อหลีกเลี่ยงการสร้างลิงก์ซ้ำ |
| Telegram | แท็ก HTML (<b>, <i>, <s>, <code>, <pre><code>, <a href>, <tg-spoiler>) |
รองรับตารางและหัวเรื่องในข้อความแบบริช (<h1>-<h6>) เมื่อเปิด richMessages |
| Signal | ข้อความธรรมดา + ช่วง text-style |
ลิงก์จะเรนเดอร์เป็น label (url) เมื่อป้ายกำกับแตกต่างจาก URL |
| Discord, WhatsApp, iMessage, Microsoft Teams และช่องทางอื่น ๆ | ข้อความธรรมดา | ไม่มีการจัดรูปแบบที่อิง IR; การแปลงตาราง Markdown ยังคงทำงานผ่าน convertMarkdownTables |
ตัวอย่าง IR
Markdown ขาเข้า: OC_I18N_900000 IR (แผนผัง): OC_I18N_900001
การจัดการตาราง
markdown.tables ควบคุมวิธีที่ช่องทางแปลงตาราง Markdown โดยกำหนดได้
แยกตามช่องทางและเลือกกำหนดแยกตามบัญชีได้:
| โหมด | ลักษณะการทำงาน |
|---|---|
code |
เรนเดอร์เป็นตาราง ASCII ที่จัดแนวแล้วภายในบล็อกโค้ด (ค่าเริ่มต้นสำรอง) |
bullets |
แปลงแต่ละแถวเป็นรายการหัวข้อย่อยรูปแบบ label: value |
block |
คงตารางแบบเนทีฟไว้เมื่อการขนส่งรองรับ มิฉะนั้นจะสำรองไปใช้ code |
off |
ปิดการแยกวิเคราะห์ตาราง โดยส่งข้อความตารางดิบผ่านไปโดยไม่เปลี่ยนแปลง |
ค่าเริ่มต้นของ Plugin แยกตามช่องทาง: Signal, WhatsApp และ Matrix ใช้
bullets เป็นค่าเริ่มต้น; Mattermost ใช้ off เป็นค่าเริ่มต้น; Telegram ใช้ block เป็นค่าเริ่มต้น (ซึ่ง
จะได้ผลลัพธ์เป็น code เว้นแต่บัญชีจะเปิดใช้ richMessages) ช่องทางใด ๆ
ที่ไม่มีค่าเริ่มต้นของ Plugin ระบุไว้อย่างชัดเจนจะสำรองไปใช้ code
OC_I18N_900002
กฎการแบ่งส่วน
- ขีดจำกัดของส่วนมาจากอะแดปเตอร์/การกำหนดค่าของช่องทาง และใช้กับข้อความ IR ไม่ใช่ ผลลัพธ์ที่เรนเดอร์แล้ว
- บล็อกโค้ดที่มีรั้วจะถูกเก็บเป็นบล็อกเดียวพร้อมอักขระขึ้นบรรทัดใหม่ต่อท้าย เพื่อให้ ช่องทางเรนเดอร์รั้วปิดได้อย่างถูกต้อง
- คำนำหน้ารายการและข้อความอ้างอิงแบบบล็อกเป็นส่วนหนึ่งของข้อความ IR ดังนั้นการแบ่งส่วนจะไม่ ตัดกลางคำนำหน้า
- รูปแบบอินไลน์จะไม่ถูกแบ่งข้ามส่วน โดยตัวเรนเดอร์จะเปิด รูปแบบที่ยังเปิดอยู่ใหม่ที่จุดเริ่มต้นของส่วนถัดไป
ดู การสตรีมและการแบ่งส่วน สำหรับพฤติกรรมของขอบเขตส่วนและ การนำส่งระหว่างช่องทาง
นโยบายลิงก์
- Slack:
[label](url)-><url|label>; URL เปล่าจะคงเป็น URL เปล่า - Telegram:
[label](url)-><a href="url">label</a>(โหมดแยกวิเคราะห์ HTML) - Signal:
[label](url)->label (url)เว้นแต่ป้ายกำกับจะ ตรงกับ URL อยู่แล้ว
สปอยเลอร์
เครื่องหมายสปอยเลอร์ (||spoiler||) จะถูกแยกวิเคราะห์สำหรับ Signal (แมปเป็นช่วงรูปแบบ SPOILER)
และ Telegram (แมปเป็น <tg-spoiler>) ช่องทางอื่นจะถือว่า
||...|| เป็นข้อความธรรมดา
การเพิ่มหรืออัปเดตตัวจัดรูปแบบช่องทาง
- แยกวิเคราะห์ครั้งเดียว ด้วย
markdownToIR(...)โดยส่งตัวเลือกที่เหมาะสมกับช่องทาง (autolink,headingStyle,blockquotePrefix,tableMode) - เรนเดอร์ ด้วย
renderMarkdownWithMarkers(...)และแมปเครื่องหมายรูปแบบ (หรือ ตรรกะช่วงรูปแบบแบบกำหนดเองสำหรับการขนส่งอย่าง Signal) - แบ่งส่วน ด้วย
chunkMarkdownIR(...)หรือrenderMarkdownIRChunksWithinLimit(...)ก่อนเรนเดอร์แต่ละส่วน - เชื่อมต่ออะแดปเตอร์ ให้เรียกตัวแบ่งส่วนและตัวเรนเดอร์ใหม่จาก เส้นทางส่งขาออก
- ทดสอบ ด้วยการทดสอบรูปแบบ พร้อมการทดสอบการนำส่งขาออกหากช่องทาง มีการแบ่งส่วน
จุดที่มักพลาด
- โทเค็นวงเล็บมุมของ Slack (
<@U123>,<#C123>,<https://...>) ต้อง รอดจากการเอสเคป ส่วน HTML ดิบยังคงต้องถูกเอสเคปอย่างปลอดภัย - HTML ของ Telegram ต้องเอสเคปข้อความนอกแท็กเพื่อหลีกเลี่ยงมาร์กอัปเสียหาย
- ช่วงรูปแบบของ Signal ใช้ออฟเซ็ต UTF-16 ไม่ใช่ออฟเซ็ตจุดรหัส
- คงอักขระขึ้นบรรทัดใหม่ต่อท้ายบล็อกโค้ดที่มีรั้ว เพื่อให้เครื่องหมายปิด อยู่ในบรรทัดของตัวเอง