توسعهی وب با زبان برنامهنویسی سلام از قابلیتی شروع میشود که بیشتر زبانها آن را به موتورهای قالب و چارچوبها میسپارند. زبان صفحهی سلام یک زبان اعلانی است که درون خود کامپایلر ساخته شده: صفحهی وب را به شکل درختی از عنصرها با ویژگیها و سبکهایشان مینویسید، کامپایلر هر عنصر، هر ویژگی و هر مقدار CSS را با قاعدههای HTML و CSS میسنجد و فرمان salam page build از آن HTML و CSS میسازد، و اگر صفحه رویدادگیر داشته باشد، جاوااسکریپت هم. همین زبان صفحههایی را هم توصیف میکند که یک سرور وب سلام برای هر درخواست میسازد، و هم به فارسی کار میکند و هم به انگلیسی.
این مقاله کل مسیر را پوشش میدهد: یک صفحهی ایستا، آنچه کامپایلر بررسی میکند، بخشها، تعامل، رندر سمت سرور، ساختن و استقرار، و محدودیتهایی که پیش از انتخاب این ابزار باید بدانید. همهی برنامههای این صفحه هنگام ساختن سایت کامپایل میشوند: صفحههای ایستا با salam page build و بقیه با کامپایلر معمولی.
نخستین صفحهی وب با زبان سلام
بلوک صفحه: یک درخت است. هر عنصر با نامش و یک دونقطه باز و با پایان بسته میشود؛ ویژگیها و خاصیتهای CSS درون آن به شکل جفتهای نام = مقدار میآیند، بدون ویرگول میانشان. ثابتهایی که بالای صفحه تعریف میشوند در هر مقداری به کار میروند، و بخش (component) تکهای قابل استفادهی دوباره از صفحه است که پارامتر میگیرد:
پایا برند := "#0f766e"
بخش ویژگی(نام، شرح):
جعبه:
فاصله = "16px"
کادر = "1px solid #e2e8f0"
گردی کادر = "12px"
سرتیتر: اندازه = ۳ محتوا = نام رنگ = برند پایان
پاراگراف: محتوا = شرح پایان
پایان
پایان
صفحه:
عنوان = "یادداشتیار"
سراسری: گزینشگر = "body" فضا = "0" خانواده قلم = "Vazirmatn, system-ui, sans-serif" پایان
سرصفحه:
پسزمینه = برند
رنگ = "سفید"
فاصله = "24px"
سرتیتر: اندازه = ۱ محتوا = "یادداشتیار" پایان
ناوبری:
پیوند: نشانی = "/" محتوا = "خانه" رنگ = "سفید" پایان
پیوند: نشانی = "/pricing" محتوا = "تعرفهها" رنگ = "سفید" فضا = "0 12px" پایان
پایان
پایان
اصلی:
فاصله = "24px"
نمایش = "grid"
ستون های شبکه = "repeat(auto-fit, minmax(220px, 1fr))"
شکاف = "16px"
ویژگی: نام = "سریع" شرح = "در یک چشم به هم زدن باز میشود." پایان
ویژگی: نام = "خصوصی" شرح = "یادداشتهایتان روی دستگاه خودتان میماند." پایان
ویژگی: نام = "دوزبانه" شرح = "به فارسی یا انگلیسی بنویسید." پایان
پایان
پاورقی:
فاصله = "24px"
پاراگراف: محتوا = "ساختهشده با سلام" پایان
پایان
پایانفرمان salam page build site.salam دو پروندهی site.html و site.css را مینویسد. HTML ساختهشده برای این صفحه این است:
<!doctype html>
<html lang="fa" dir="rtl">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>یادداشتیار</title>
<link rel="stylesheet" href="site.css" />
</head>
<body>
<header class="b">
<h1>یادداشتیار</h1>
<nav>
<a href="/" class="c">خانه</a><a href="/pricing" class="d">تعرفهها</a>
</nav>
</header>
<main class="e">
<div class="f">
<h3 class="g">سریع</h3>
<p>در یک چشم به هم زدن باز میشود.</p>
</div>
<div class="f">
<h3 class="g">خصوصی</h3>
<p>یادداشتهایتان روی دستگاه خودتان میماند.</p>
</div>
<div class="f">
<h3 class="g">دوزبانه</h3>
<p>به فارسی یا انگلیسی بنویسید.</p>
</div>
</main>
<footer class="h"><p>ساختهشده با سلام</p></footer>
</body>
</html>و برگهی سبک:
body {
margin: 0px;
font-family: Vazirmatn, system-ui, sans-serif;
}
.b {
background: #0f766e;
color: white;
padding: 24px;
}
.c {
color: white;
}
.d {
color: white;
margin: 0px 12px;
}
.e {
padding: 24px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 16px;
}
.f {
padding: 16px;
border: 1px solid #e2e8f0;
border-radius: 12px;
}
.g {
color: #0f766e;
}
.h {
padding: 24px;
}در این مسیر چند اتفاق افتاده است. جعبه به div تبدیل شد، پیوند به a و نشانی به href. مقدار فارسی "سفید" در CSS به white رسید. صفحه چون در پروندهی فارسی نوشته شده، خودش lang="fa" و dir="rtl" گرفت. سبکها روی خود عنصرها نماندند: هر عنصر سبکدار یک کلاس کوتاه ساختگی گرفت و سبکهای یکسان یک کلاس مشترک دارند؛ برای همین هر سه کارت ویژگی از .f استفاده میکنند. ثابت برند هم در زمان کامپایل درون CSS نشست. با گزینهی --inline کل CSS درون پروندهی HTML میرود و یک صفحهی خودبسنده به دست میآید که هر میزبان ایستایی میتواند آن را ارائه کند. درس زبان صفحه همهی اینها را گام به گام آموزش میدهد.
بررسی صفحه در زمان کامپایل
قالبها در بیشتر پشتههای وب متن تولید میکنند، و غلط تایپی در نام یک تگ یا خاصیت CSS فقط در مرورگر پیدا میشود، آن هم اگر کسی متوجهش شود. زبان صفحهی سلام همهی عنصرهای HTML و همهی خاصیتهای CSS را میشناسد و هنگام کامپایل آنها را بررسی میکند. این صفحه چهار اشتباه دارد:
صفحه:
عنوان = "خراب"
تصویر: جایگزین = "نشان" پایان
ورودی: شناسه = "q" راهنما = "جستوجو" پایان
مورد: محتوا = "بیصاحب" پایان
جعبه: رنگه = "قرمز" پایان
پایانsalam page build آن را رد میکند و هیچ پروندهای نمینویسد:
E005: عنصر 'تصویر' فاقد ویژگی الزامی 'نشانی' است (bad.salam:3:5)
E112: ویژگی ناشناخته 'راهنما' روی 'ورودی'؛ منظورتان 'داده نما' یا 'راهنمای کلید ورود' بود؟ (bad.salam:4:34)
E004: عنصر 'مورد' را نمیتوان داخل 'صفحه' قرار داد (bad.salam:5:5)
E112: ویژگی ناشناخته 'رنگه' روی 'جعبه'؛ منظورتان 'رنگ' بود؟ (bad.salam:6:15)پیامها فارسیاند، چون پرونده فارسی است، و کدهای خطا همان کدهای نسخهی انگلیسیاند. بررسیها از نامها فراتر میروند. جای هر عنصر سنجیده میشود (مورد باید درون فهرست باشد و پیوند نمیتواند پیوند دیگری را در بر بگیرد)، ویژگیهای الزامی باید حاضر باشند، شناسههایی که ویژگی for به آنها اشاره میکند باید وجود داشته باشند و تکراری نباشند، و تقریباً هر خاصیت CSS مقدارش را بهعنوان طول، رنگ، زمان، زاویه یا واژهی کلیدی بررسی میکند، از جمله خاصیتهای خلاصه مثل border و transition. ویژگیهای نشانی، javascript: و طرحهای مشابه را نمیپذیرند. جدول کامل عنصرها با نامهای فارسی و قاعدههای جایگیریشان در LAYOUT_ELEMENTS.md آمده است.
نامهای خوانا و فارسی برای HTML و CSS
زبان صفحه جایی که HTML مختصرنویسی میکند نام خوانا به کار میبرد: پاراگراف، سرتیتر با اندازه، فهرست و مورد، فهرست شمارهدار، متن بلند و نقل قول بلند. نام تگهای HTML هم کار میکنند (div، p، a، img، li)، پس هر کدام را که میشناسید میتوانید بنویسید. بعضی نامها به جایشان بستگی دارند: درون جدول، عنصرهای سرصفحه، اصلی و پاورقی به thead، tbody و tfoot تبدیل میشوند، و ستون در ردیف سرصفحه خانهی عنوان (th) است و در جاهای دیگر خانهی داده (td). خاصیتهای CSS به جای خط تیره با فاصله نوشته میشوند (گردی کادر، خانواده قلم) و پیشوندی مثل اشاره یک سبک را فقط وقتی اعمال میکند که نشانگر ماوس روی عنصر باشد.
درسهای ۲۵ تا ۳۰ عنصرها را گروه به گروه آموزش میدهند: متن، ساختار صفحه، رسانه، جدولها، فرمها و سر صفحه با اسکریپتها و ویژگیهای همگانی. درسهای ۳۱ تا ۳۸ همین کار را برای CSS میکنند، از الگوی جعبه تا چیدمان با فلکس و شبکه، صفحهی واکنشگرا و پویانمایی.
هر نام یک املای انگلیسی هم دارد، و صفحهای که به انگلیسی نوشته شود بی آنکه چیزی بگویید چپبهراست و با lang="en" ساخته میشود. همان نوع صفحه به انگلیسی این شکل است:
component Feature(name, text):
box:
padding = "16px"
border = "1px solid #e2e8f0"
border radius = "12px"
heading: size = 3 content = name end
paragraph: content = text end
end
end
page:
title = "My notes"
heading: size = 1 content = "My notes" end
Feature: name = "Fast" text = "Opens in a blink." end
Feature: name = "Bilingual" text = "Write in English or Persian." end
endاین صفحه به <html lang="en" dir="ltr"> تبدیل میشود و کلاسها به همان شیوه ساخته میشوند. خاصیتهای منطقی CSS مثل کادر خطی آغاز (border-inline-start) از جهت صفحه پیروی میکنند، پس بیشتر سبکها میان صفحهی راستبهچپ و چپبهراست تغییری لازم ندارند. مقالهی برنامهنویسی راستبهچپ متن دوسویه را عمیقتر بررسی میکند.
بخشها و تکههای مشترک صفحه
بخش یک بار تعریف میشود و مثل یک عنصر تازه به کار میرود. پارامترهایش مثل ویژگیها مقدار میگیرند، و خط محتوا: پایان درون آن جای خالی را نشان میدهد: هر چه هنگام استفاده درون بخش بگذارید همانجا مینشیند. برای اینکه بخشها را در چند صفحه به کار ببرید، آنها را در پروندهای جدا بگذارید و بالای صفحه بنویسید بگنجان = "parts.salam". در فارسی عنصر HTML به نام section هم بخش نام دارد: درون بلوک صفحه بخش: همان عنصر است و بیرون آن، تعریف یک بخش تازه.
بخشها CSS ساختهشده را کوچک نگه میدارند، چون دو استفاده با سبک یکسان یک کلاس مشترک میگیرند. یک قاعده هم با خود میآورند که دانستنش میارزد: اگر دو عنصر یک کلاس یکسان ولی سبکهای متفاوت داشته باشند، کامپایلر با خطای E136 میایستد تا یکی بیصدا دیگری را بازنویسی نکند. روی عنصرهای سبکدار کلاس ننویسید، یا کلاس مشترک را یک بار با یک قاعدهی سراسری سبک بدهید.
تعاملی کردن صفحه با رویدادها
ویژگیای که نامش یکی از رویدادهای مرورگر است، مثل کلیک، ارسال، تغییر یا فشردن کلید، به جای مقدار یک تابع سلام یا یک تابع درونخطی میگیرد. رویدادگیر از راه پشتوانهی جاوااسکریپت سلام (JavaScript Backend) در اسکریپت صفحه کامپایل میشود، پس رفتار صفحه هم به سلام نوشته میشود، نه به جاوااسکریپت دستنویس. بستهی دام (dom) به رویدادگیرها دسترسی به صفحه میدهد (دام.با شناسه، دام.تنظیم متن، دام.تنظیم سبک و بسیاری دیگر)، و شناسههایی که به شکل متن ساده در دام.با شناسه("...") نوشته شوند در زمان کامپایل با شناسههای همان صفحه مقایسه میشوند.
بخشها حالت (state) هم نگه میدارند. متغیری که بالای بدنهی یک بخش تعریف شود مال هر نمونه از آن بخش است؛ وقتی رویدادگیری آن را تغییر دهد، کامپایلر فقط نمونههایی را دوباره رسم میکند که آن متغیر را میخوانند:
بخش نامزد(نام: رشته):
رایها := ۰
جعبه:
دکمه: کلیک = (): رایها++ پایان محتوا = "رأی به " + نام پایان
تکه: محتوا = " " + رایها پایان
پایان
پایان
صفحه:
عنوان = "نظرسنجی کوتاه"
سرتیتر: اندازه = ۲ محتوا = "چای یا قهوه؟" پایان
نامزد: نام = "چای" پایان
نامزد: نام = "قهوه" پایان
پایانهر نامزد رأیهای خودش را میشمارد و کلیک روی یکی فقط همان جعبه را دوباره رسم میکند، پس تمرکز و متنی که جای دیگری تایپ شده دست نمیخورد. همین صفحه با salam run poll.salam --ui=native در پنجرهای بومی هم اجرا میشود که خود سلام آن را رسم میکند، و salam check --ui=native بخشهایی را گزارش میدهد که پنجرهی بومی نمیتواند نشان دهد. درسهای ۳۹ تا ۴۳ همهی رویدادها و الگوی حالت را پوشش میدهند، و مقالهی رابط کاربری تعاملی در سلام به بخشها، حالت و رویدادها عمیقتر میپردازد.
صفحهی پارامتردار: رندر سمت سرور با زبان سلام
بلوک صفحه: هنگام کامپایل ثابت میشود. اگر به صفحه نام و پارامترهای گونهدار بدهید، به تابعی تبدیل میشود که کل سند را به شکل یک رشتهی HTML برمیگرداند. ساختار و CSS همچنان در زمان کامپایل ساخته میشوند؛ در زمان اجرا تابع فقط مقدارها را پر میکند و هر مقدار گریز HTML (HTML escape) داده میشود:
صفحه نمایه(نام: رشته، مهارتها: وکتور<رشته>، مدیر: منطقی):
عنوان = نام + " | نمایه"
سرتیتر: اندازه = ۱ محتوا = نام پایان
اگر مدیر:
پاراگراف: محتوا = "مدیر سامانه" پایان
پایان
فهرست:
هر ش، مهارت در مهارتها:
مورد: محتوا = (ش + ۱) + ". " + مهارت پایان
پایان
پایان
پایان
تابع ریشه:
ناپایا مهارتها := وکتور {} برگردان وکتور<رشته>
دیرکن مهارتها.آزادکن()
مهارتها.بیفزا("سلام")
مهارتها.بیفزا("SQL & <HTML>")
سرچاپ نمایه("سارا"، مهارتها، درست)
پایاندر زمان اجرا نه مفسر قالبی در کار است و نه گونهای برای «HTML خام» که ممکن است گریز دادنش فراموش شود. تابع صفحه ناب (pure) است: نمیتواند پرونده بخواند، به شبکه وصل شود یا متغیرهای سراسری را تغییر دهد، پس رویدادگیر داده را جمع میکند و به صفحه میدهد. مقداری که در نشانی یا خاصیت CSS مینشیند نمیتواند یک رشتهی ساده باشد؛ باید اول به وب.نشانی وب، وب.رنگ وب یا وب.اندازه وب خوانده شود که ورودی ناامن را رد میکنند. چون صفحه یک تابع است، سرور وب سلام میتواند برای هر درخواست آن را صدا بزند:
واردسازی شبکه.اچ تی تی پی
واردسازی شبکه.مسیریاب
صفحه خوشامد(نام: رشته):
عنوان = "درود بر " + نام
سرتیتر: اندازه = ۱ محتوا = "درود، " + نام پایان
پاراگراف: محتوا = "این صفحه را یک سرور سلام ساخته است." پایان
پایان
تابع خانه(زمینه: صحیح۶۴):
ناپایا نام := اچ تی تی پی.پرسمان(زمینه، "name")
اگر نام == "":
نام = "مهمان"
پایان
اچ تی تی پی.اچ تی ام ال(زمینه، خوشامد(نام))
پایان
تابع ریشه:
ناپایا م := مسیریاب.مسیریاب جدید()
مسیریاب.دریافت(م، "/"، خانه)
ناپایا س := اچ تی تی پی.سرور جدید(۸۰۸۰)
اچ تی تی پی.استفاده(س، م)
اچ تی تی پی.اجرا(س)
پایاناین سرور تا وقتی متوقفش نکنید روشن میماند، برای همین فقط بررسی گونه میشود و اجرا نمیشود. باز کردن http://localhost:8080/?name=Ada خوشامد را برمیگرداند، و بازدیدکنندهای که ?name=<b> بفرستد خود نویسهها را میبیند، نه متن پررنگ. سمت سرور در مقالهی ساخت سرور وب سریع با سلام آمده و مقالهی توسعهی فولاستک با سلام این دو نیمه را کنار هم میگذارد.
ساختن، اجرا و استقرار سایت
فرمانها کماند:
salam page build site.salam # site.html و site.css (و site.js اگر رویدادگیر باشد)
salam page build site.salam --inline # یک پروندهی HTML خودبسنده
salam page build home.salam about.salam # برای هر صفحه یک HTML و یک style.css مشترک
salam web app.salam # یک صفحه به همراه اسکریپتهای سلامی که به کار میبرد
salam serve # ارائهی پوشهی جاری روی HTTPصفحهی ایستا همانطور که هست کامل است: HTML و CSS را روی هر میزبان وبی کپی کنید. سایتی که سرور لازم دارد یک برنامهی معمولی سلام است که با salam build به یک فایل اجرایی تبدیل میشود. برای میزبانی چند سایت، تغییر مسیرها و پشتوانههای FastCGI مثل PHP، فرمان salam serve --config سرور وبی را اجرا میکند که در یک پروندهی پیکربندی سلام توصیف شده است (درس salam serve). برنامهای که با net/http نوشته شده را هم میتوان به WebAssembly ساخت و روی Cloudflare Workers مستقر کرد.
محدودیتها و اینکه کی سراغ ابزار دیگری برویم
زبان صفحه جوان است و جای هر پشتهی وبی را نمیگیرد:
- اکوسیستم چارچوب ندارد. کتابخانهی بخش، سامانهی طراحی یا کتابخانهی مسیریابی شخص ثالثی برایش وجود ندارد. برای یک برنامهی تکصفحهای بزرگ با حالت پیچیده در سمت کاربر، یک چارچوب TypeScript انتخاب عملیتری است (مقالهی سلام در برابر TypeScript را ببینید).
- ساختار صفحهی سمت سرور در زمان کامپایل ثابت است.
اگروهربخشهایی را انتخاب یا تکرار میکنند، ولی عمداً نمیتوانید HTML دلخواه را از رشتهها بسازید. - حالت سمت کاربر به جاوااسکریپت نیاز دارد. بخشهای حالتدار را اسکریپت صفحه رسم میکند، پس فقط وقتی جاوااسکریپت روشن است دیده میشوند؛ محتوای ایستا به آن وابسته نیست.
- پشتوانهی جاوااسکریپت با سلام بومی تفاوتهایی دارد. برای نمونه یک
صحیح۶۴در مرورگر فقط ۵۳ بیت دقت دارد، چون عددهای جاوااسکریپت اعشاری دودقتیاند. - راههای گریز وجود دارند ولی بررسی نمیشوند. عنصر سبک یا اسکریپت سفارشی میتواند CSS یا جاوااسکریپت خام نگه دارد و رویدادگیر میتواند یک رشتهی سادهی جاوااسکریپت باشد، اما کامپایلر نمیتواند درونشان را بررسی کند.
جایی که این ابزار خوب مینشیند: سایتهای مستندات، صفحههای فرود، داشبوردها، فرمها، صفحههای مدیریت و برنامههایی که سمت سرور رندر میشوند و در آنها درستی نشانهگذاری و گریز امن مهمتر از غنای سمت کاربر است. برای سایت فارسی، اینکه راستبهچپ و lang="fa" بیزحمت درست میشوند خودش یک امتیاز است.
مسیر یادگیری طراحی وب با سلام
آموزش رایگان این سایت پس از بخش زبان عمومی، زبان صفحه را در بیستویک درس آموزش میدهد:
- زبان صفحه: گشتی کلی، از نخستین صفحه تا رندر سمت سرور.
- صفحه و متن، ساختار صفحه، رسانه، جدولها، فرمها و سر صفحه: همهی عنصرها.
- سبک و الگوی جعبه تا بقیهی CSS: همهی خاصیتها.
- رویدادهای ماوس تا حالت، DOM و زمانسنجها: تعامل.
- شش پروژهی کامل وب: صفحهی فرود، نوشتهی وبلاگ، فرم ثبتنام، داشبورد، فهرست کارها و گالری.
پرسشهای پرتکرار
آیا زبان صفحهی سلام یک موتور قالب است؟
نه. موتور قالب در زمان اجرا متن را درون متن میگذارد. زبان صفحهی سلام بخشی از کامپایلر است: HTML و CSS را میشناسد، صفحه را هنگام کامپایل بررسی میکند و صفحهی پارامتردار را به تابعی ناب تبدیل میکند که فقط مقدارهای گریز دادهشده را پر میکند.
برای کار با آن باید HTML و CSS بلد باشم؟
کمک میکند، چون زبان صفحه مستقیم بر عنصرهای HTML و خاصیتهای CSS منطبق است و هر چه دربارهی آنها میدانید اینجا هم به کار میآید. آموزش سایت هر دو را از صفر و از راه زبان صفحه درس میدهد، پس میتوانید آنها را همزمان یاد بگیرید.
آیا با زبان سلام میشود برنامهی تکصفحهای (SPA) ساخت؟
صفحههای تعاملی با بخشها، حالت و رویدادها میسازید که به جاوااسکریپت کامپایل میشوند. برای برنامههای بزرگ با مسیریابی و حالت پیچیده در سمت کاربر، اکوسیستمهای React، Vue یا Svelte پختهترند.
آیا میتوانم با زبان برنامهنویسی سلام صفحهی وب فارسی بنویسم؟
بله. هر عنصر، ویژگی و خاصیت CSS نام فارسی دارد، صفحهای که به فارسی نوشته شود خودکار راستبهچپ و با lang="fa" ساخته میشود و رقمهای فارسی در مقدارها کار میکنند.