لقد قمت بكتابة Markdown كل يوم عمل لسنوات - البرامج الإضافية READMEs، وقوائم التغيير، والمستندات الخاصة بـ تولز.ديف، قم بإصدار ملاحظات لـ WP Adminify، نصف رسائل الالتزام الخاصة بي. وفي معظم ذلك الوقت تعاملت مع خطوة العرض على أنها سحرية. تكتب العلامات النجمية، ويظهر GitHub بالخط العريض. بخير. تحرك.
ثم قمت ببناء قسم المستندات الذي أخرج Markdown من قاعدة البيانات وجعله في صفحة Next.js، وتحول السحر إلى قائمة بقرارات محددة للغاية كان علي اتخاذها. هل يصبح سطر جديد واحد <br>؟ (تعليقات GitHub تقول نعم. مواصفات Markdown تقول لا) هل <div> في المصدر يتم تقديمه كـ div أو كنص حرفي؟ (يعتمد على من يسأل، وما إذا كنت تثق بالمؤلف.) ما هي الفئة التي يتم وضعها على كتلة التعليمات البرمجية المسيجة حتى يلتقطها الهايلايتر؟ لماذا يتحول محلل واحد **bold**text في جريئة وآخر يتركها وحدها؟
لا شيء من هذا غريب. إنها مجرد الأشياء التي لا يخبرك بها أحد، لأن Markdown يبدو بسيطًا جدًا لدرجة أن الناس يفترضون أنه لا يوجد شيء تحته. هناك الكثير تحته. Markdown إلى HTML يعرض المحول الموجود على Toolz.dev تلك القرارات كمفاتيح بدلاً من إخفائها، وهو إصدار هذه الأداة الذي أردته عندما كنت أقوم بتصحيح أخطاء سبب استمرار اختفاء فواصل الأسطر.
ليرة تركية؛DR: Markdown هو تنسيق الكتابة؛ HTML هو تنسيق العرض. يجب على شيء ما تجميع أحدهما في الآخر. القواعد التي تنقل الأشخاص إلى أعلى: تنضم الأسطر المتتالية إلى فقرة واحدة ما لم تقم بإنهاء سطر بمسافتين (أو تشغيل خيار "؛breaks"؛)، يتم تمرير HTML الخام أو الهروب منه اعتمادًا على إعدادات الثقة للمحلل اللغوي '؛ وتضيف لهجة GitHub'؛s (GFM) الجداول وقوائم المهام والشطب والربط التلقائي لـ URL العاري أعلى كومونمارك خط الأساس. يتم تجميع الكود المسيج إلى
<pre><code class="language-js">، وهو الخطاف المنشور، قم بتسليط الضوء على.js وShiki يبحثان عنه. ال تخفيض السعر إلى محول HTML قم بكل هذا في متصفحك، مع كشف كل مفتاح.
ما هو Markdown، ولماذا يحتاج إلى التحويل على الإطلاق؟
Markdown عبارة عن بناء جملة نص عادي نشره John Gruber في عام 2004، مع هدف تصميمي واحد معلن: يجب أن يكون مستند Markdown قابلاً للنشر كما هو، ويمكن قراءته كنص عادي، دون أن يبدو وكأنه تم تمييزه بالعلامات. ولهذا السبب يستعير بناء الجملة من الاتفاقيات التي استخدمها الأشخاص بالفعل في البريد الإلكتروني - علامات النجمة حول كلمة للتأكيد، وسطر من الشرطات تحت عنوان، أ > للحصول على اقتباس.
والنتيجة هي أن Markdown ليس تنسيق عرض. لا شيء يعرض Markdown. تعرض المتصفحات HTML، وكل مكان لديك على الإطلاق مرئي تم عرض Markdown - GitHub، وهو موقع ثابت، وبوابة المستندات، وتطبيق الدردشة - قام بتشغيل محلل أولاً ووضع HTML على الشاشة.
لذلك يجب أن يحدث التحويل في مكان ما. خياراتك تقريبية:
- في وقت البناء، في منشئ الموقع الثابت أو المجمع. حسنًا عندما يكون المحتوى موجودًا في الريبو الخاص بك.
- في وقت الطلبعلى الخادم. ضروري عندما يأتي المحتوى من قاعدة بيانات، وهو مكلف إذا قمت بذلك عند كل طلب دون تخزين مؤقت.
- في المتصفح، في الوقت الذي تحتاجه. وهو ما تريده عندما تكون الإجابة على "؛ أنا فقط بحاجة إلى HTML لهذا الشيء الوحيد والاقتباس؛ هو نسخ ولصق، وليس خط أنابيب البناء.
هذه الحالة الثالثة أكثر شيوعًا مما تبدو. لصق ملاحظات الإصدار في حقل CMS الذي يأخذ HTML فقط. الحصول على README في قالب البريد الإلكتروني. التحقق من الشكل الذي سيبدو عليه المستند قبل الالتزام به. تحويل مسودة مكتوبة بلغة سبج إلى شيء يمكنك تسليمه إلى المصمم. لا شيء من هذا يبرر توصيل المحلل اللغوي بالمشروع.
ما الفرق بين CommonMark و تخفيضات جيثب بنكهة؟
كانت المواصفات الأصلية لـ Gruber'؛ عبارة عن صفحة نثرية ونص بيرل، وقد تركت غموضًا كافيًا لدرجة أن كل تطبيق اختلف في الحالات الطرفية. كومونمارك هل الإجابة على ذلك هي: مواصفات صارمة وقابلة للاختبار مع مجموعة مطابقة من مئات الأمثلة، بحيث ينتج اثنان من المحللين المتطابقين مخرجات متطابقة لنفس الإدخال. فهو يحدد خط الأساس - العناوين، والفقرات، والتأكيد، والروابط، والصور، والقوائم، وعروض الأسعار، وكتل التعليمات البرمجية، والفواصل الموضوعية، وهروب الشرطة المائلة العكسية، وكتل HTML.
GitHub بنكهة Markdown (GFM) هي مجموعة شاملة رسمية من CommonMark، تم تحديدها بواسطة GitHub، والتي تضيف الأشياء التي ظل الناس يطلبونها:
| ميزة | كومونمارك | جي اف ام | بناء الجملة |
|---|---|---|---|
| الجداول | لا | نعم | | a | b | مع أ | --- | --- | صف المحدد |
| قوائم المهام | لا | نعم | - [x] done / - [ ] todo |
| يتوسطه خط | لا | نعم | ~~gone~~ |
| عناوين URL العارية المرتبطة تلقائيًا | لا | نعم | https://toolz.dev بدون أقواس |
| الحواشي السفلية | لا | نعم (امتداد GitHub) | [^1] |
| العناوين والقوائم والرمز والتأكيد | نعم | نعم | متطابق |
إذا كان Markdown الخاص بك يأتي من GitHub README، أو GitLab wiki، أو تصدير Notion أو معظم المحررين الحديثين، فهو GFM. قم بتشغيل GFM في المحول وإلا سيتم عرض طاولاتك كأنابيب حرفية، وهو رقم واحد "؛ المحول معطل وحاصل؛ دعم سؤال أي شخص يقوم بشحن إحدى هذه الأدوات التي يتلقاها.
لماذا اختفى كسر خطي؟
لأن Markdown، باتباع اصطلاحات البريد الإلكتروني ذي النص العادي، يتعامل مع الأسطر المتتالية غير الفارغة كفقرة واحدة. هذا:
Line one
Line two
ينتج <p>Line one\nLine two</p>- فقرة واحدة، وينهار السطر الجديد إلى مسافة عندما يعرضه المتصفح. إنه ليس خطأ؛ إنها المواصفات، وهي موجودة حتى تتمكن من لف نثرك بقوة في 80 عمودًا في محرر النصوص دون تسرب هذا الغلاف إلى الإخراج.
هناك ثلاث طرق للحصول على استراحة فعلية
- سطر فارغ يبدأ فقرة جديدة. هذا ما تريده في معظم الأوقات.
- مسافتان خلفيتان في نهاية السطر تنتج استراحة صعبة -
<br />. هذه هي الحيلة القياسية، وهي غير مرئية في المحرر الخاص بك، ولهذا السبب يجدها الناس مثيرة للجنون. - شرطة مائلة عكسية في نهاية السطر يفعل الشيء نفسه في CommonMark، ويكون مرئيًا على الأقل.
ثم هناك الطريق الرابع وهو مصدر الارتباك تقوم العديد من الأنظمة الأساسية بتشغيل "؛ فواصل واقتباس؛ وضع حيث يصبح كل سطر جديد <br />. تعليقات ومشكلات GitHub تفعل ذلك. معظم تطبيقات الدردشة تفعل ذلك. ملفات GitHub README لا. لذا فإن نفس النص يظهر بشكل مختلف في إصدار GitHub وفي README لنفس المستودع، وهو تصميم سيء حقًا ونحن جميعًا عالقون فيه الآن.
يعرض المحول هذا كمحول. إذا كان مصدرك مكتوبًا لعارض نمط الدردشة، فقم بتشغيل سطر التشغيل. إذا كان مستندًا، فاتركه واستخدم أسطرًا فارغة كما تنوي المواصفات.
كيف يتم التعامل مع HTML الخام؟
يسمح Markdown بـ HTML المضمن - تنص المواصفات الأصلية صراحةً على أن أي HTML تكتبه يمر مباشرة. هذه ميزة عندما تكون المؤلف (تريدك <details> بلوك، الخاص بك <img> مع سمة العرض، مرساة الخاص بك مع rel)، وهي مسؤولية عندما لا تكون كذلك.
لأنه إذا قمت بعرض Markdown غير موثوق به مع تمكين تمرير HTML، فستكون لديك ثغرة أمنية في XSS. <script>alert(document.cookie)</script> هل Markdown صالح. هكذا هو <img src=x onerror="...">. هكذا هو <a href="javascript:...">. يجب على مربع التعليق، والسيرة الذاتية لملف تعريف المستخدم، والويكي العام - في أي مكان يكتب فيه الغرباء Markdown ويقرأه الآخرون - إما الهروب من HTML أو تعقيم الإخراج باستخدام مطهر حقيقي (DOMPurify هو الإجابة المعتادة، وهو مطهر حقيقي على وجه التحديد لأن regex لا يكفي لإدخال عدائي).
هذا المحول الافتراضي هو الهروب HTML الخام: <div> يظهر في مصدرك النص الحرفي <div> في الإخراج، تماما كما لو كنت قد كتبت <div>. يمكنك تشغيل التمرير عندما يكون المصدر خاصًا بك. وبغض النظر عن هذا الإعداد، فإن شرائط المعاينة المباشرة <script>، <style>، مضمنة on* معالجات الأحداث و javascript: عناوين URL قبل عرضها - دفاع في قياس العمق، لذا فإن لصق شخص آخر '؛s README في جزء المعاينة لا يمكن أن ينفذ التعليمات البرمجية الخاصة به. هذا إجراء سلامة المعاينة، وليس مطهرًا للأغراض العامة: إذا كنت تقوم ببناء منتج يعرض Markdown للمستخدم، فاستخدم مطهرًا مخصصًا من جانب الخادم ولا تثق في regex، بما في ذلك جهازي.
إذا كنت بحاجة للهروب من الشخصية من Markdown بحيث يتم عرضه حرفيًا - علامة النجمة التي يجب أن تظل علامة النجمة، والشرطة السفلية في اسم الملف - تقوم الشرطة المائلة العكسية بذلك \*not emphasis\*. وإذا كنت تتجادل مع كيانات في الاتجاه الآخر، فإن تشفير/فك تشفير كيانات HTML هي الأداة لهذه المهمة.
ما هو HTML الذي يجب أن يصدره المحول الجيد بالفعل؟
HTML دلالي، ممل، خالي من الفئات - مع استثناء واحد.
- تصبح العناوين
<h1>.ح<h6>. مع تمكين معرفات العناوين، يتم أيضًا تباطؤ كل منهاid، يتم إلغاء التكرار عندما يشترك عنوانان في عنوان (#setup،#setup-1). هذا ما يجعل#anchorتعمل الروابط العميقة، وهذا هو ما يتوقف عنه مولد جدول المحتويات. - كتلة مسيجة بسلسلة معلومات -
```js- يصبح<pre><code class="language-js">. *هذا هو الاستثناء.** لغة `-فئة `V` هي الاتفاقية التي يبحث عنها كل من Prism وhighlight.js وShiki، ولهذا السبب يصدر المحول فئة على الإطلاق. المحول لا يقوم بتلوين الكود الخاص بك؛ الهايلايتر الموجود على صفحتك يفعل ذلك، ويحتاج إلى هذا الخطاف. - تصبح القوائم
<ul>/<ol>، وهنا دقة تستحق المعرفة: أ ضيق القائمة (لا توجد أسطر فارغة بين العناصر) تضع النص مباشرة بالداخل<li>، بينما أ فضفاض القائمة (خطوط فارغة بين العناصر) تغلف كل عنصر ومحتوى #39؛s<p>. هذا هو سلوك CommonMark، وليس غرابة، ولهذا السبب تنمو قائمتك فجأة في التباعد الرأسي عند إضافة سطر فارغ بين نقطتين. لم يتم كسر CSS؛ لقد تغير HTML حقًا. - الجداول تصبح حقيقية
<table>/<thead>/<tbody>ترميز، معstyle="text-align:center"على الخلايا عند استخدام صف المحدد:---:. - تصبح قوائم المهام
<input type="checkbox" disabled>داخل<li>وهو بالضبط ما ينبعث منه GitHub.
المحتوى أولاً، لا يوجد أقسام مجمعة، ولا فئات المرافق. يمكنك تصميمه من الخارج باستخدام .prose الفصل أو القواعد الخاصة بك، ويظل الترميز محمولاً.
كيف أستخدم المحول؟
الخطوة 1: لصق العلامة
قم بإسقاط README، وسجل التغيير، وملاحظات الإصدار، والمسودة. تحديثات الإخراج أثناء الكتابة - لا يوجد زر تحويل، ولا يتم تحميل أي شيء.
الخطوة 2: اضبط المفاتيح
بنكهة جيثب إذا كان المصدر يحتوي على جداول أو قوائم مهام أو يتوسطه خط (ربما يكون كذلك). معرفات العنوان على إذا كنت تريد المراسي. فواصل الخط فقط إذا كان المصدر مكتوبًا لعارض نمط الدردشة. السماح بـ HTML الخام فقط إذا كان المصدر لك. وثيقة كاملة في حالة رغبتك في الحصول على صفحة HTML5 كاملة تحتوي على نوع المستند ومجموعة الأحرف ومنفذ العرض و <title> مأخوذة من الأول الخاص بك <h1>- مفيد عندما تريد فتح النتيجة مباشرة في المتصفح أو إسقاطها على مضيف ثابت.
الخطوة 3: تحقق من المعاينة
قم بالتبديل إلى علامة تبويب المعاينة وتأكيد البنية. يخبرك صف الإحصائيات بالكلمات والعناوين والروابط والصور وكتل التعليمات البرمجية ووقت القراءة - من المفيد التحقق من المنشور بالطول الذي اعتقدت أنه كان قبل نشره. للحصول على عدد أكثر شمولاً، عداد الكلمات هل سهولة القراءة وكثافة الكلمات الرئيسية على نفس النص.
الخطوة 4: خذ الإخراج
انسخ HTML، وقم بتنزيله كـ .html قم بملف أو نسخ جدول المحتويات الذي تم إنشاؤه - قائمة متداخلة من Markdown ترتبط بكل مرساة عنوان، جاهزة للصقها مرة أخرى في الجزء العلوي من المستند.
إذا كنت تقوم بلصق النتيجة في صفحة حيث البايتات مهمة، فقم بتشغيلها من خلال مصغر HTML بعد ذلك. يتم وضع مسافة بادئة لمخرج المحول '؛s لسهولة القراءة، وليس للسلك.
حالات الاستخدام الشائعة
الحصول على برنامج README على موقع على شبكة الإنترنت
يكتب مؤلفو المكونات الإضافية والحزم قراءة جيدة، ثم يحتاجون إلى نفس المحتوى على الصفحة المقصودة. Readme هو GFM مع الجداول والشارات؛ الصفحة المقصودة تحتاج إلى HTML. تحويل ولصق ونمط مع CSS الموجود لديك. تمنحك معرفات العناوين شريطًا جانبيًا TOC مجانًا.
النشر إلى نظام إدارة المحتوى الذي يقبل HTML فقط
الكثير من حقول CMS ومنصات البريد الإلكتروني ولوحات الإدارة القديمة تأخذ HTML ولا شيء غير ذلك. إذا قمت بالصفحة في Markdown - ومعظم الأشخاص الذين يكتبون بانتظام يفعلون ذلك - فهذا هو الجسر. تحويل مع وثيقة كاملة قم بإيقاف التشغيل، حتى تحصل على الجزء بدلاً من صفحة كاملة، ثم قم بلصقه في الحقل.
النماذج الأولية لصفحة المستندات
قبل أن تقوم بإرسال المحتوى إلى موقع مستندات، فإن تحويله محليًا يوضح لك التسلسل الهرمي الفعلي للعناوين وما إذا كانت أسوار التعليمات البرمجية الخاصة بك تحمل اللغة الصحيحة. ان h3 كان ينبغي أن يكون h2 واضح في TOC وغير مرئي في المصدر.
تدقيق المحتوى الذي كتبه شخص آخر
الصق أحد المساهمين '؛s Markdown، وانظر إلى HTML المنبعث، ويمكنك أن ترى على الفور ما إذا كانوا يستخدمون عناوين حقيقية أو سطرًا غامقًا لتزييف عنوان - وهي عادة تدمر بنية المستند وإمكانية الوصول إليه. تتنقل قارئات الشاشة حسب العنوان؛ **Big Text** ليس عنوانًا، بل هو فقرة بالخط العريض، والمحول يوضح لك ذلك في سطر واحد من الإخراج.
استخراج جدول المحتويات
تحتاج المستندات الطويلة إلى واحدة، والحفاظ عليها يدويًا يضمن أنها تصبح قديمة. قم بإنشائها من العناوين، والصقها، وتجديدها كلما تغيرت العناوين.
متقدم: ما يفعله هذا المحلل اللغوي وما لا يفعله
إنه محلل مكتوب بخط اليد، ما يقرب من 400 سطر، بدون تبعيات - وهو أمر متعمد، لأن محلل Markdown الذي يسحب تبعية 200 كيلو بايت إلى صفحة يكون بيت القصيد منها سريعًا يعد تداولًا سيئًا.
مغطى: عناوين ATX (# x) وعناوين setext (تم وضع خط تحتها بـ === / ---)، الفقرات والتأكيد والقوية (*، _، **، __)، رمز مضمن مع مطابقة تشغيل الخلفية، رمز مسيج مع سلاسل معلومات، كتل تعليمات برمجية ذات مسافة بادئة، اقتباسات كتلة مع استمرار كسول، قوائم متداخلة (مرتبة وغير مرتبة، ضيقة وفضفاضة)، فواصل موضوعية، روابط وصور مع عناوين، قوس زاوية الروابط التلقائية، والروابط التلقائية للبريد الإلكتروني، وهروب الشرطة المائلة العكسية، ومجموعة GFM: جداول ذات محاذاة، وقوائم مهام، وخط يتوسطه خط، والربط التلقائي لـ URL العاري.
غير مشمول: روابط النمط المرجعي ([text][ref] مع أ [ref]: url التعريف في مكان آخر)، والحواشي السفلية، وقوائم التعريفات، وبعض حالات زاوية CommonMark الغامضة حقًا حول كتل HTML التي تقاطع الفقرات. إذا كنت تقوم بتشغيل مجموعة توافق CommonMark مقابلها، فلن تحصل على 100%. إذا كنت تقوم بتحويل README أو سجل تغيير أو منشور مدونة، فلن تلاحظ ذلك.
هذه تجارة صادقة، وهذا هو السبب وراء تحميل المحول على الفور وعمله مع إيقاف تشغيل الشبكة. بالنسبة لخطوط أنابيب المحتوى حيث تحتاج إلى توافق CommonMark الدقيق، استخدم markdown-it، remark أو cmark في بنيتك؛ هذا هو ما هم من أجله.
أسئلة وأجوبة
كيف أقوم بتحويل Markdown إلى HTML؟
الصق Markdown الخاص بك في المحرر وسيظهر HTML على الفور - لا يوجد زر تحويل ولا ملف للتحميل. قم بتشغيل GitHub Flavored Markdown إذا كان مصدرك يستخدم الجداول أو قوائم المهام، ثم انسخ HTML أو قم بتنزيله كملف.html. كل شيء يعمل في متصفحك، لذا فإن المسودات غير المنشورة والمستندات الداخلية لا تترك جهازك أبدًا.
ما هو تخفيض نكهة جيثب؟
GitHub Flavored Markdown (GFM) عبارة عن مجموعة شاملة محددة رسميًا من CommonMark تضيف الجداول ومربعات اختيار قائمة المهام والخط مع علامات التلدة المزدوجة والربط التلقائي لعناوين URL المجردة. إنها اللهجة التي يستخدمها GitHub لعرض ملفات ومشكلات README، وهي ما ينبعث منه معظم محرري Markdown اليوم. يتم تمكينه افتراضيًا في هذا المحول.
لماذا اختفى كسر سطر واحد؟
يقوم Markdown القياسي بضم الأسطر المتتالية في فقرة واحدة؛ لا يبقى فاصل الأسطر إلا إذا أنهيت السطر بمسافتين، أو استخدمت شرطة مائلة عكسية زائدة، أو تركت سطرًا فارغًا. إذا كنت تريد أن يصبح كل سطر جديد <br />، قم بتمكين خيار فواصل الأسطر - هذا هو السلوك الذي تستخدمه تعليقات GitHub ومعظم تطبيقات الدردشة، ولكن هذا ليس ما تفعله ملفات README.
هل يقوم المحول بتسليط الضوء على الكود الخاص بي؟
إنه يصدر العلامات التي يحتاجها قلم التمييز ولكنه لا يلون الكود نفسه. كتلة رمز مسيجة موسومة باللغة js يصبح <pre><code class="language-js">، وهو اصطلاح الفصل الدراسي Prism، Highlight.js وShiki يبحث عنهما جميعًا. أضف إحدى تلك المكتبات إلى الصفحة التي تلصق فيها المخرجات ويظهر التمييز تلقائيًا.
هل HTML الخام داخل Markdown محفوظ؟
بشكل افتراضي يتم الهروب، لذلك <div> يظهر كنص حرفي بدلاً من علامة. قم بتشغيل خيار السماح لـ RAW-HTML بتمرير العلامات مباشرة، وهو ما تريده عندما يتم مزج Markdown الخاص بك عمدًا في HTML - أ <details> كتلة، أو صورة ذات سمات. قم بتمكينه فقط للمصدر الذي تثق به، لأن HTML الخام من مؤلف غير موثوق به هو متجه XSS.
هل من الآمن لصق Markdown الذي لم أكتبه؟
نعم. يتم الهروب من HTML افتراضيًا، بالإضافة إلى ذلك، تقوم المعاينة المباشرة بتجريد البرنامج النصي وعلامات النمط ومعالجات الأحداث المضمنة وjavascript: عناوين URL قبل العرض. لا يتم نقل أي شيء تقوم بلصقه إلى أي مكان. إذا كنت تقوم بإنشاء منتج يعرض Markdown من الغرباء، فلا يزال يستخدم معقمًا مخصصًا مثل DOMPurify من جانب الخادم - فمرشح المعاينة ليس بديلاً عن واحد.
هل يمكنني إنشاء جدول محتويات من عناويني؟
نعم. مع تمكين معرفات العناوين، يحصل كل عنوان على مرساة بطيئة وغير مكررة، وتقوم الأداة بإنشاء جدول ترميز للمحتويات المرتبطة بكل عنوان. انسخه مرة أخرى إلى أعلى المستند الخاص بك ويتم حل الروابط مقابل المعرفات التي تم إنشاؤها. قم بتجديده كلما تغيرت عناوينك بدلاً من الاحتفاظ به يدويًا.
هل يقوم هذا المحول بتنفيذ CommonMark بالكامل؟
إنه ينفذ التركيبات التي يكتبها الأشخاص فعليًا - عناوين ATX ونصوص المجموعة، والفقرات، والتأكيد، والروابط، والصور، والروابط التلقائية، وعروض أسعار الكتل، والقوائم المتداخلة والفضفاضة، والتعليمات البرمجية المسيجة والمسافة البادئة، والفواصل الموضوعية، وهروب الشرطة المائلة العكسية - بالإضافة إلى امتدادات GFM. لا تتم تغطية روابط النمط المرجعي والحواشي السفلية وبعض حالات حافة كتلة HTML CommonMark النادرة. للتوافق الدقيق للبت في مسار البناء، استخدم علامة تخفيض السعر أو الملاحظة أو العلامة التجارية.
الأدوات ذات الصلة: Markdown إلى HTML · كيانات HTML · مصغر HTML · عداد الكلمات · مولد البزاق
القراءة ذات الصلة: مطور الويب ومجموعة أدوات #39؛s · دليل أدوات النص



