Concept internals
قالببندی Markdown
OpenClaw قالببندی Markdown خروجی را با تبدیل آن به یک نمایش میانی مشترک (IR) پیش از رندر کردن خروجی مخصوص هر کانال انجام میدهد. IR متن مبدأ را دستنخورده نگه میدارد و در عین حال بازههای سبک/پیوند را حمل میکند تا قطعهبندی و رندر در سراسر کانالها سازگار بماند.
اهداف
- سازگاری: یک مرحله تجزیه، چند رندرکننده.
- قطعهبندی ایمن: متن را پیش از رندر تقسیم کنید تا قالببندی درونخطی هرگز بین قطعهها نشکند.
- تناسب با کانال: همان IR را بدون تجزیه دوباره Markdown به Slack mrkdwn، HTML تلگرام، و بازههای سبک Signal نگاشت کنید.
Pipeline
- Parse Markdown -> IR
- IR متن ساده بههمراه بازههای سبک (bold/italic/strike/code/spoiler) و بازههای پیوند است.
- آفستها واحدهای کد UTF-16 هستند تا بازههای سبک Signal با API آن همراستا شوند.
- جدولها فقط زمانی تجزیه میشوند که یک کانال تبدیل جدول را فعال کند.
- Chunk IR (format-first)
- قطعهبندی پیش از رندر روی متن IR انجام میشود.
- قالببندی درونخطی بین قطعهها تقسیم نمیشود؛ بازهها برای هر قطعه برش داده میشوند.
- Render per channel
- Slack: توکنهای mrkdwn (bold/italic/strike/code)، پیوندها بهصورت
<url|label>. - Telegram: تگهای HTML (
<b>,<i>,<s>,<code>,<pre><code>,<a href>). - Signal: متن ساده + بازههای
text-style؛ وقتی برچسب متفاوت باشد، پیوندها بهlabel (url)تبدیل میشوند.
- Slack: توکنهای mrkdwn (bold/italic/strike/code)، پیوندها بهصورت
نمونه IR
Markdown ورودی:
Hello **world** - see [docs](https://docs.openclaw.ai).
IR (شماتیک):
{
"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: هر ردیف را به موارد بولتدار تبدیل کنید (پیشفرض برای Signal + WhatsApp).off: تجزیه و تبدیل جدول را غیرفعال کنید؛ متن خام جدول بدون تغییر عبور میکند.
کلیدهای پیکربندی:
channels:
discord:
markdown:
tables: code
accounts:
work:
markdown:
tables: off
قواعد قطعهبندی
- محدودیتهای قطعه از آداپتورها/پیکربندی کانال میآیند و روی متن IR اعمال میشوند.
- حصارهای کد بهصورت یک بلوک واحد با یک خط جدید پایانی حفظ میشوند تا کانالها آنها را درست رندر کنند.
- پیشوندهای فهرست و پیشوندهای نقلقول بلوکی بخشی از متن IR هستند، بنابراین قطعهبندی در میانه پیشوند انجام نمیشود.
- سبکهای درونخطی (bold/italic/strike/inline-code/spoiler) هرگز بین قطعهها تقسیم نمیشوند؛ رندرکننده سبکها را داخل هر قطعه دوباره باز میکند.
اگر به جزئیات بیشتری درباره رفتار قطعهبندی در کانالها نیاز دارید، ببینید Streaming + chunking.
سیاست پیوند
- Slack:
[label](url)-><url|label>؛ URLهای برهنه برهنه میمانند. Autolink هنگام تجزیه غیرفعال است تا از پیونددهی دوباره جلوگیری شود. - Telegram:
[label](url)-><a href="url">label</a>(حالت تجزیه HTML). - Signal:
[label](url)->label (url)مگر اینکه برچسب با URL برابر باشد.
Spoilers
نشانگرهای Spoiler (||spoiler||) فقط برای Signal تجزیه میشوند، جایی که به
بازههای سبک SPOILER نگاشت میشوند. کانالهای دیگر آنها را متن ساده در نظر میگیرند.
چگونه قالبساز کانال را اضافه یا بهروزرسانی کنیم
- Parse once: از helper مشترک
markdownToIR(...)با گزینههای مناسب کانال (autolink، سبک heading، پیشوند blockquote) استفاده کنید. - Render: یک رندرکننده با
renderMarkdownWithMarkers(...)و یک نگاشت نشانگر سبک (یا بازههای سبک Signal) پیادهسازی کنید. - Chunk: پیش از رندر،
chunkMarkdownIR(...)را فراخوانی کنید؛ هر قطعه را رندر کنید. - Wire adapter: آداپتور خروجی کانال را بهروزرسانی کنید تا از قطعهبند و رندرکننده جدید استفاده کند.
- Test: اگر کانال از قطعهبندی استفاده میکند، آزمونهای قالب را اضافه یا بهروزرسانی کنید و یک آزمون تحویل خروجی اضافه کنید.
خطاهای رایج
- توکنهای زاویهبراکتی Slack (
<@U123>,<#C123>,<https://...>) باید حفظ شوند؛ HTML خام را ایمن escape کنید. - HTML تلگرام به escape کردن متن بیرون از تگها نیاز دارد تا markup خراب نشود.
- بازههای سبک Signal به آفستهای UTF-16 وابستهاند؛ از آفستهای code point استفاده نکنید.
- خطهای جدید پایانی را برای بلوکهای کد حصاردار حفظ کنید تا نشانگرهای پایانی روی خط خودشان قرار بگیرند.