Concept internals

قالب‌بندی Markdown

Edit source

OpenClaw، Markdown خروجی را با تبدیل آن به یک نمایش میانی مشترک (IR) پیش از رندر خروجی ویژه هر کانال، قالب‌بندی می‌کند. IR متن مبدأ را دست‌نخورده نگه می‌دارد و در عین حال بازه‌های سبک/پیوند را حمل می‌کند تا قطعه‌بندی و رندرینگ بتوانند در سراسر کانال‌ها سازگار بمانند.

اهداف

  • سازگاری: یک مرحله پارس، چند رندرکننده.
  • قطعه‌بندی امن: متن را پیش از رندر تقسیم کنید تا قالب‌بندی درون‌خطی هرگز در میان قطعه‌ها شکسته نشود.
  • تناسب کانال: همان IR را بدون پارس دوباره Markdown، به Slack mrkdwn، HTML در Telegram، و بازه‌های سبک Signal نگاشت کنید.

خط پردازش

  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) تبدیل می‌شوند.

نمونه 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 اعمال می‌شوند.
  • حصارهای کد به‌صورت یک بلوک واحد همراه با نویسه خط جدید پایانی حفظ می‌شوند تا کانال‌ها آن‌ها را درست رندر کنند.
  • پیشوندهای فهرست و پیشوندهای نقل‌قول بلوکی بخشی از متن IR هستند، بنابراین قطعه‌بندی در میانه پیشوند تقسیم نمی‌شود.
  • سبک‌های درون‌خطی (bold/italic/strike/inline-code/spoiler) هرگز بین قطعه‌ها تقسیم نمی‌شوند؛ رندرکننده سبک‌ها را درون هر قطعه دوباره باز می‌کند.

اگر درباره رفتار قطعه‌بندی در کانال‌های مختلف به اطلاعات بیشتری نیاز دارید، ببینید استریمینگ + قطعه‌بندی.

خط‌مشی پیوند

  • Slack: [label](url) -> <url|label>؛ URLهای خام خام می‌مانند. Autolink هنگام پارس غیرفعال است تا از پیونددهی دوباره جلوگیری شود.
  • Telegram: [label](url) -> <a href="url">label</a> (حالت پارس HTML).
  • Signal: [label](url) -> label (url) مگر اینکه برچسب با URL یکسان باشد.

اسپویلرها

نشانگرهای اسپویلر (||spoiler||) فقط برای Signal پارس می‌شوند، جایی که به بازه‌های سبک SPOILER نگاشت می‌شوند. کانال‌های دیگر با آن‌ها مانند متن ساده رفتار می‌کنند.

نحوه افزودن یا به‌روزرسانی قالب‌بند کانال

  1. یک‌بار پارس کنید: از کمک‌تابع مشترک markdownToIR(...) با گزینه‌های مناسب کانال (autolink، سبک heading، پیشوند blockquote) استفاده کنید.
  2. رندر کنید: یک رندرکننده با renderMarkdownWithMarkers(...) و یک نگاشت نشانگر سبک (یا بازه‌های سبک Signal) پیاده‌سازی کنید.
  3. قطعه‌بندی کنید: پیش از رندر chunkMarkdownIR(...) را فراخوانی کنید؛ هر قطعه را رندر کنید.
  4. آداپتر را متصل کنید: آداپتر خروجی کانال را به‌روزرسانی کنید تا از قطعه‌بند و رندرکننده جدید استفاده کند.
  5. آزمایش کنید: آزمون‌های قالب‌بندی را اضافه یا به‌روزرسانی کنید و اگر کانال از قطعه‌بندی استفاده می‌کند، یک آزمون تحویل خروجی اضافه کنید.

خطاهای رایج

  • توکن‌های زاویه‌براکتی Slack (<@U123>, <#C123>, <https://...>) باید حفظ شوند؛ HTML خام را با ایمنی escape کنید.
  • HTML در Telegram برای جلوگیری از markup خراب، نیاز دارد متن بیرون تگ‌ها escape شود.
  • بازه‌های سبک Signal به آفست‌های UTF-16 وابسته‌اند؛ از آفست‌های نقطه کد استفاده نکنید.
  • نویسه‌های خط جدید پایانی را برای بلوک‌های کد حصاردار حفظ کنید تا نشانگرهای بسته‌شدن روی خط خودشان قرار بگیرند.

مرتبط

Was this useful?