درس ۲۴ از ۴۹ · زبان صفحه

زبان صفحه: مشترک برای وب و بومی

زبان صفحه (DSL چیدمان) در سلام یک زبان توصیفی برای ساخت رابط است: هم می‌تواند خروجی وب (HTML/CSS/JS) بسازد و هم می‌تواند همان ساختار را به‌صورت برنامه‌ی بومی با رابط گرافیکی سلام اجرا کند. این درس چیزهای مشترک را توضیح می‌دهد؛ جزئیات مخصوص وب در صفحه‌های وب و جزئیات مخصوص دسکتاپ بومی در برنامه‌ی بومی آمده است.

چه چیزهایی مشترک است؟

در هر دو هدف، رابط را به شکل درختی از عنصرها می‌نویسید. بلوک صفحه: ریشه است، هر عنصر با نام و دونقطه باز می‌شود و با پایان بسته می‌شود، و ویژگی‌ها و سبک‌ها به شکل نام = مقدار داخل عنصر نوشته می‌شوند. متن معمولاً در محتوا می‌آید، عنصرها می‌توانند تودرتو باشند، و ساختار صفحه با همان قواعد خوانا باقی می‌ماند.

تنظیم‌های بالای صفحه مانند عنوان، زبان و جهت متعلق به خود صفحه‌اند. در پرونده‌های فارسی معمولاً صفحه راست‌به‌چپ است و در پرونده‌های انگلیسی چپ‌به‌راست؛ در صورت نیاز می‌توانید این مقدارها را صریح بنویسید.

layout-page.salam
صفحه:
    عنوان = "برنامه‌ی من"
    زبان = "فارسی"
    جهت = "راست به چپ"
    سرصفحه:
        پس‌زمینه = #2563eb
        رنگ = "سفید"
        فاصله داخلی = "24px"
        سرتیتر: اندازه = 1 محتوا = "به سلام خوش آمدید" پایان
    پایان
    جعبه:
        فاصله داخلی = "20px"
        پاراگراف: محتوا = "این صفحه از کد سلام ساخته شده است." پایان
    پایان
پایان

مقدارهای ساده‌تر (جدید)

در ویژگی‌های سبک/صفحه می‌توانید مقدارها را کوتاه‌تر و خواناتر بنویسید: درصدها مانند 50% و 100% بدون گیومه، رنگ‌های شانزدهی مانند #0f766e بدون گیومه، و یکاها/فهرست‌های مقداری در جای مناسب. برای نمونه:

جعبه:
    عرض = 50%
    بیشینه عرض = 480
    فاصله = 16, 24
    پس زمینه = #f8fafc
    رنگ = #0f766e
    کادر = 1, solid, #0f766e
پایان

عدد ساده معمولاً به پیکسل تعبیر می‌شود؛ وقتی یکای دیگری لازم است همان‌طور روشن بنویسید. رشته‌ها (مثل متن محتوا، نشانی‌ها یا مقدارهای متنی خاص) همچنان در گیومه می‌مانند.

عنصرها، ویژگی‌ها و سبک‌ها

نام‌های عنصر و ویژگی خوانا و دوزبانه‌اند (فارسی/انگلیسی). برای نمونه جعبه، پاراگراف، سرتیتر، پیوند، تصویر، فهرست، مورد، فرم، ورودی و دکمه. ویژگی بولی درست معنا دارد و نادرست معمولاً حذف می‌شود. سبک‌های CSS نیز به همین شکل کنار عنصر نوشته می‌شوند.

layout-form.salam
صفحه:
    عنوان = "تماس با ما"
    زبان = "فارسی"
    جهت = "راست به چپ"
    ناوبری:
        پیوند: نشانی = "/" محتوا = "خانه" پایان
        پیوند: نشانی = "/blog" محتوا = "وبلاگ" پایان
        پیوند: نشانی = "https://github.com/SalamLang/Salam" هدف = "پنجره جدید" محتوا = "کد منبع" پایان
    پایان
    تصویر: نشانی = "/logo.png" جایگزین = "نشان سلام" پایان
    فرم:
        شناسه = "تماس"
        برچسب: برای = "رایانامه" محتوا = "رایانامه‌ی شما" پایان
        ورودی: شناسه = "رایانامه" نوع = "ایمیل" نام = "email" جانگهدار = "you@example.com" الزامی = درست پایان
        برچسب: برای = "پیام" محتوا = "پیام" پایان
        ورودی: شناسه = "پیام" نوع = "متن" نام = "message" پایان
        دکمه: نوع = "ارسال" محتوا = "بفرست" پایان
    پایان
    فهرست:
        مورد: محتوا = "در کمتر از یک روز پاسخ می‌دهیم" پایان
        مورد: محتوا = "نیازی به ساختن حساب نیست" پایان
    پایان
پایان

سبک‌های تکراری را می‌توانید با ثابت‌ها، سراسری و بخش‌ها سازمان بدهید تا کد کوتاه‌تر و یکدست‌تر شود:

layout-style.salam
پایا رنگ‌اصلی := "#0f766e"
پایا فاصله := ۱۶

صفحه:
    عنوان = "تعرفه‌ها"
    زبان = "فارسی"
    جهت = "راست به چپ"
    سراسری: اندازه جعبه = "border-box" پایان
    سراسری: گزینشگر = "body" حاشیه = "0" خانواده قلم = "sans-serif" پایان
    بخش:
        نمایش = "flex"
        شکاف = فاصله + "px"
        فاصله داخلی = فاصله * ۲ + "px"
        جعبه:
            کادر = 1px, solid, #ddd
            گردی کادر = "12px"
            فاصله داخلی = فاصله + "px"
            سرتیتر: اندازه = ۲ محتوا = "رایگان" پایان
            پاراگراف: محتوا = "برای امتحان کردن" پایان
        پایان
        جعبه:
            کادر = 2px, solid + رنگ‌اصلی
            گردی کادر = "12px"
            فاصله داخلی = فاصله + "px"
            سرتیتر: اندازه = ۲ محتوا = "حرفه‌ای" رنگ = رنگ‌اصلی پایان
            دکمه:
                محتوا = "ارتقا"
                پس‌زمینه = رنگ‌اصلی
                رنگ = "سفید"
                اشاره پس‌زمینه = #115e59
                نشانگر = "pointer"
            پایان
        پایان
    پایان
پایان

بخش‌ها و استفاده‌ی دوباره

بخش تکه‌ای قابل استفاده‌ی دوباره است که پارامتر می‌گیرد و مثل یک عنصر تازه به کار می‌رود. محتوا: پایان جایگاه محتوای درونی (slot) را مشخص می‌کند. برای اشتراک بین پرونده‌ها می‌توان از بگنجان = "parts.salam" استفاده کرد (مسیر نسبت به همان پرونده).

layout-component.salam
بخش طرح(نام، بها):
    جعبه:
        کادر = 1px, solid, #ddd
        گردی کادر = "12px"
        فاصله داخلی = "16px"
        سرتیتر: اندازه = ۲ محتوا = نام پایان
        پاراگراف: محتوا = "ماهانه " + بها + " هزار تومان" پایان
        محتوا: پایان
    پایان
پایان

صفحه:
    عنوان = "طرح‌ها"
    زبان = "فارسی"
    جهت = "راست به چپ"
    طرح: نام = "پایه" بها = ۴۹ پایان
    طرح: نام = "حرفه‌ای" بها = ۹۰
        فهرست:
            مورد: محتوا = "پروژه‌های خصوصی" پایان
            مورد: محتوا = "پشتیبانی با رایانامه" پایان
        پایان
    پایان
پایان

صفحه‌ها و بخش‌های پارامتردار

صفحه می‌تواند پارامتر بگیرد (مثل صفحه کارت(نام: رشته، امتیاز: صحیح):) و در زمان اجرا با داده‌های متفاوت فراخوانی شود. درون چنین صفحه‌ای می‌توانید از شرط (اگر/وگرنه) و حلقه (هر) برای ساخت رابط پویا استفاده کنید. متن ورودی هنگام درج در صفحه برای ایمنی مدیریت می‌شود.

layout-runtime.salam
صفحه کارت(نام: رشته، امتیاز: صحیح):
    عنوان = «کارت » + نام
    زبان = «فارسی»
    جهت = «راست به چپ»
    سرتیتر: اندازه = ۲ محتوا = نام پایان
    اگر امتیاز >= ۵۰:
        پاراگراف: محتوا = «قبول» پایان
    وگرنه:
        پاراگراف: محتوا = «مردود» پایان
    پایان
پایان

تابع ریشه:
    سرچاپ کارت(«علی»، ۷۰)
پایان
خروجی<!doctype html><html lang="fa" dir="rtl"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>کارت علی</title></head><body><h2>علی</h2><p>قبول</p></body></html>
layout-inbox.salam
بخش نشان(متن: رشته):
    تکه: محتوا = متن پس‌زمینه = #fde68a پایان
پایان

صفحه صندوق(کاربر: رشته، موضوع‌ها: وکتور<رشته>):
    عنوان = "صندوق " + کاربر
    زبان = "فارسی"
    جهت = "راست به چپ"
    سرتیتر: اندازه = ۱ محتوا = "درود، " + کاربر پایان
    اگر موضوع‌ها.خالی است():
        پاراگراف: محتوا = "پیام تازه‌ای ندارید" پایان
    وگرنه:
        پاراگراف: محتوا = "نخوانده: " + موضوع‌ها.طول() پایان
        فهرست:
            هر ش، م در موضوع‌ها:
                مورد: محتوا = (ش + ۱) + ". " + م پایان
            پایان
        پایان
    پایان
پایان

تابع ریشه:
    ناپایا موضوع‌ها := وکتور {} برگردان وکتور<رشته>
    دیرکن موضوع‌ها.آزادکن()
    موضوع‌ها.بیفزا("جلسه‌ی ساعت ۱۰")
    موضوع‌ها.بیفزا("<b>جایزه</b> رایگان & بیشتر")
    سرچاپ صندوق("سارا"، موضوع‌ها)
    سرچاپ نشان("تازه")
پایان
خروجی<!doctype html><html lang="fa" dir="rtl"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>صندوق سارا</title></head><body><h1>درود، سارا</h1><p>نخوانده: 2</p><ul><li>1. جلسه‌ی ساعت ۱۰</li><li>2. &lt;b&gt;جایزه&lt;/b&gt; رایگان &amp; بیشتر</li></ul></body></html> <style>.نشان-a{background:#fde68a}</style><span class="نشان-a">تازه</span>

دو هدف: وب و بومی

همان DSL می‌تواند برای دو هدف استفاده شود، اما خروجی و امکانات زمان اجرا فرق می‌کنند:

  • وب: با salam page build به HTML/CSS/JS تبدیل می‌شود، در مرورگر اجرا می‌شود، و می‌تواند با سرور/رویدادهای DOM و وب کار کند. جزئیات در زبان صفحه در وب.
  • بومی (دسکتاپ): با salam run --ui=native یا salam build --ui=native به برنامه‌ی پنجره‌ای بومی (موتور رابط سلام) تبدیل می‌شود؛ بدون مرورگر. جزئیات و محدودیت‌ها در زبان صفحه در برنامه‌ی بومی.

برای ساخت برنامه‌ی دسکتاپ مبتنی بر WebView (HTML/CSS/JS داخل پنجره‌ی بومی) به مستندات نمایش وب (gui.webview) هم نگاه کنید؛ آن یک مسیر جدا از رندر بومی DSL است.

بررسی در زمان ترجمه

مترجم نام عنصرها/ویژگی‌ها و بسیاری از مقدارها را بررسی می‌کند و در صورت خطا پیام راهنما می‌دهد. این بررسی‌ها کمک می‌کند هم در وب و هم در بومی، اشتباه‌های رایج زودتر پیدا شوند. هنگام کار با صفحه‌های پارامتردار و مقادیر ورودی، قوانین ایمنی و اعتبارسنجی (به‌ویژه در مسیر وب/سرور) را رعایت کنید.

درس‌های بعدی عنصرها، سبک‌ها، رویدادها و الگوهای وب را با جزئیات بیشتری آموزش می‌دهند. برای شروع وب از زبان صفحه در وب و برای برنامه‌ی پنجره‌ای از زبان صفحه در برنامه‌ی بومی ادامه دهید.