اخیراً کارمندان دیجیکالا تصمیم گرفتهاند که پستهای وبلاگشان را با فرمت *مارکداون* بنویسند. *مارکداون* یک زبان نشانهگذاری برای قالببندی متن با امکان تبدیل به فرمتهای مختلف از جمله *HTML* است. با استفاده از *مارکداون* بهراحتی میتوان تیتر، متنهای *bold* ، *italic* ، نقلقول و... ایجاد کرد. از *مارکداون* در وبسایتهایی نظیر *GitHub* نیز استفاده میشود. برای کسب اطلاعات بیشتر دربارهی *مارکداون* به [اینجا](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) مراجعه کنید.
از شما میخواهیم کلاسی برای تبدیل *مارکداون* به *HTML* با بهرهگیری از عبارات باقاعده (*Regex*) پیادهسازی کنید.
# ساختار پروژه
پروژهی اولیه را میتوانید از [اینجا](https://quera.ir/qbox/download/ZowBrkBovy/markdown-parser-initial.zip) دانلود کنید.
## اینترفیس `RuleInterface`
برای مدیریت روشهای تبدیل *مارکداون* به *HTML* ، اینترفیسی با نام `RuleInterface` ایجاد کردهایم؛ زیرا ممکن است در آینده با روشی غیر از عبارات باقاعده فرایند تبدیل را انجام دهیم. این اینترفیس شامل یک متد با نام `parse` است که باید رشتهای شامل محتوای *مارکداون* را دریافت کرده و خروجی موردنظر را برگرداند.
## اینترفیس `RegexRuleInterface`
این اینترفیس از اینترفیس `RuleInterface` پیروی کرده و وظیفهی آن، مدیریت قواعد مختلف برای تبدیل *مارکداون* به *HTML* است. متدی با نام `rule` در این اینترفیس وجود دارد که باید رشتهای شامل یک عبارت باقاعده برای تشخیص یکی از عناصر *مارکداون* را برگرداند.
## کلاس انتزاعی `RegexRule`
این کلاس، اینترفیس `RegexRuleInterface` را پیادهسازی میکند. متدی انتزاعی با نام `replacement` در این کلاس موجود است که باید رشتهای شامل عبارتی که قرار است جایگزین نتایج اجرای عبارت باقاعده روی محتوای *مارکداون* شود را برگرداند.
## کلاس `MarkdownParser`
این کلاس با استفاده از نمونههایی از کلاسهای مختلف که از کلاس `RegexRule` ارثبری میکنند، محتوای *مارکداون* را به *HTML* تبدیل میکند. متدی با نام `render` در این کلاس وجود دارد که یک رشتهی *مارکداون* دریافت کرده و خروجی *HTML* آن را برمیگرداند.
# پیادهسازی
در حال حاضر از هفت عنصر مختلف در *مارکداون* استفاده میکنیم که باید قوانین استخراج و جایگزینی آنها را پیادهسازی کنید. همهی این قوانین باید تحت قالب کلاسهایی مجزا که از کلاس `RegexRule` ارثبری میکنند باشند. هر کدام از این کلاسها، دو متد `rule` و `replacement` را خواهند داشت و هر کلاس باید در فایلی همنام با نام کلاس پیادهسازی شود.
1. تیتر (کلاس `Header`): این کلاس باید تیترهای موجود در متن را پردازش کند. تیترها در *مارکداون* از یک الی شش کاراکتر `#` بههمراه فضای خالی در ادامهی آنها (بهصورت اختیاری) و نام تیتر تشکیل شدهاند:
```
# heading
##heading
### heading
#### heading
##### heading
######heading
```
تیترها را توسط کلاس `Header` به تگ `h3` تبدیل کنید:
```html
<h3>heading</h3>
<h3>heading</h3>
<h3>heading</h3>
<h3>heading</h3>
<h3>heading</h3>
<h3>heading</h3>
```
2. متن *bold* (کلاس `Bold`): این کلاس باید متنهای *bold* را پردازش کند. متنهای *bold* در *مارکداون* بین دو `**` یا دو `__` قرار میگیرند:
```
**bold 1**
__bold 2__
```
متنهای *bold* را توسط کلاس `Bold` به تگ `b` تبدیل کنید:
```html
<b>bold 1</b>
<b>bold 2</b>
```
3. متن *italic* (کلاس `Italic`): این کلاس باید متنهای *italic* را پردازش کند. متنهای *italic* در *مارکداون* بین دو `*` یا دو `_` قرار میگیرند:
```
*italic 1*
_italic 2_
```
متنهای *italic* را توسط کلاس `Italic` به تگ `i` تبدیل کنید:
```html
<i>italic 1</i>
<i>italic 2</i>
```
4. لینک (کلاس `Link`): این کلاس باید لینکها را پردازش کند. لینکها در *مارکداون* بهصورت زیر هستند:
```
[Link to Google](https://google.com)
```
لینکها را توسط کلاس `Link` به تگ `a` تبدیل کنید:
```html
<a href="https://google.com">Link to Google</a>
```
5. تصویر (کلاس `Image`): این کلاس باید تصاویر را پردازش کند. تصاویر در *مارکداون* بهصورت زیر هستند:
```
![Quera's Logo](https://cdn.quera.ir/images/logo/logo-q.0-3aee17faf53e.svg)
```
تصاویر را توسط کلاس `Image` به تگ `img` تبدیل کنید:
```html
<img src="https://cdn.quera.ir/images/logo/logo-q.0-3aee17faf53e.svg" alt="Quera's Logo">
```
6. کد (کلاس `Code`): این کلاس باید کدها را پردازش کند. کدها در *مارکداون* بین دو \` قرار میگیرند:
```
`echo "Hello, World!";`
```
کدها را توسط کلاس `Code` به تگ `code` تبدیل کنید:
```html
<code>echo "Hello, World!";</code>
```
7. خط افقی (کلاس `HorizontalRule`): این کلاس باید خطوط افقی را پردازش کنند. خطوط افقی در *مارکداون* از ۳ یا تعداد بیشتری `-` پشت سر هم تشکیل میشوند:
```
---
-----
----
```
خطوط افقی را توسط کلاس `HorizontalRule` به تگ `hr` تبدیل کنید:
```html
<hr>
<hr>
<hr>
```
**نکته:** لزوماً نباید همهی کلاسهای بالا را پیادهسازی کنید. به ازای هر کلاس، امتیاز آن را بهصورت جدا دریافت خواهید کرد.
## آنچه باید آپلود کنید
پس از پیادهسازی کلاسهای بالا، فایلهای زیر را بهصورت *Zip* ارسال کنید:
```
Header.php
Bold.php
Italic.php
Link.php
Image.php
Code.php
HorizontalRule.php
```
---
<details class="blue">
<summary>راهنمایی ۱</summary>
عبارت باقاعده برای تشخیص تیتر (با فرض این که کاراکتر `#` در متن تیتر موجود نیست) بهصورت زیر است:
```
#+\s*(.+)
```
برای تبدیل تیتر به *HTML* ، باید محتویات گروه ۱ را درون تگ `h3` قرار داد و نتیجه را جایگزین گروه ۰ کرد. بنابراین کد کلاس `Header` بهصورت زیر خواهد بود:
```php
<?php
class Header extends RegexRule
{
public function rule()
{
return '/#+\s*(.+)/';
}
public function replacement()
{
return '<h3>$1</h3>';
}
}
```
</details>
<details class="blue">
<summary>راهنمایی ۲</summary>
عبارت باقاعده برای تشخیص متنهای *bold* بهصورت زیر است:
```
(\*\*|__)(.+?)\1
```
برای تبدیل متن *bold* به *HTML* ، باید محتویات گروه ۲ را درون تگ `b` قرار داد و نتیجه را جایگزین گروه ۰ کرد. بنابراین، کد کلاس `Bold` بهصورت زیر خواهد بود:
```php
<?php
class Bold extends RegexRule
{
public function rule()
{
return '/(\*\*|__)(.+?)\1/';
}
public function replacement()
{
return '<b>$2</b>';
}
}
```
</details>
<details class="blue">
<summary>راهنمایی ۳</summary>
عبارت باقاعده برای تشخیص لینک بهصورت زیر است:
```
\[(.+?)\]\((.+?)\)
```
برای تبدیل لینک به *HTML* ، باید محتویات گروه ۱ را درون تگ `a` و محتویات گروه ۲ را درون مشخصهی `href` تگ `a` قرار داد و نتیجه را جایگزین گروه ۰ کرد. بنابراین، کد کلاس `Link` بهصورت زیر خواهد بود:
```php
<?php
class Link extends RegexRule
{
public function rule()
{
return '/\[(.+?)\]\((.+?)\)/';
}
public function replacement()
{
return '<a href="$2">$1</a>';
}
}
```
</details>