البناء
النقل من React
انقلوا واجهة React قائمة إلى NoWayOS: قيسوها بتقرير التغطية في Screen Compiler، واعرفوا ما يتحوّل كما كُتب، وما يجب تغييره، وما ينتقل إلى تطبيقكم، واقرؤوا كل خطأ يمكن أن يُصدره.
لا تبدؤون من الصفر. معظم شاشة React يتحوّل كما كُتب: تخطيطها، ونصوصها، وأزرارها وحقولها، وشروطها وقوائمها، ومكوّناتها الصغيرة الخاصة. أما الباقي فإما إعادة كتابة قصيرة، وإما عمل ينتقل إلى تطبيقكم، وهو مكانه الصحيح على حاسوب ليس له إلا عمل واحد.
قيسوا أولًا
قبل أن تغيّروا سطرًا واحدًا، اسألوا Screen Compiler إلى أي مدى يصل كودكم بالفعل. انسخوا تطبيقكم بجوار المستودعين الواردين في شاشات من React كي تراه حاوية التطوير، ثم شغّلوا تقرير التغطية على شيفرته المصدرية:
cd nowayos-work # holds nowayos and screen-compiler
git clone https://example.com/your-app.git my-app
cd screen-compiler
make run ARGS="audit ../my-app/src"
يقرأ التقرير كل ملف .tsx تحت ذلك المجلد ويعدّ كل بنية يجدها: العناصر، والخصائص، وخصائص النمط، والخطافات، والقوائم، والشروط، والمعاملات، والاستيرادات. وتنال كل بنية حكمًا:
- ضمن المجموعة الفرعية: تتحوّل حيثما استُخدمت كما تسمح المجموعة الفرعية؛
- على الطريق: لا تتحوّل بعد، ويسمّي التقرير الخطوة التي ستحوّلها؛
- مستبعدة بالتصميم: لن تتحوّل أبدًا، ويذكر التقرير السبب؛
- مجهولة: لا يتعرّف عليها Screen Compiler. ولا يُحسب المجهول أبدًا ضمن ما يتحوّل.
ثم تأتي خطوات الطريق مع عدد مرات الحاجة إلى كل منها، ثم كل ملف مع نتيجته. لا يُعدّ الملف «متحوّلًا» إلا إذا قبله check، فالرقم في الأعلى هو الرقم الحقيقي. يسمّي التقرير البنى ولا يقتبس كودكم أبدًا، فيمكنكم مشاركته بأمان. وكما مع المترجم نفسه، لا تشغّلوه إلا على كود تثقون به.
ما يقابل ماذا
| في React DOM | في المجموعة الفرعية |
|---|---|
<div> مُخطَّط بـ flexbox |
<Column> أو <Row>، مع gap وpadding وstyle مُعلَن |
<h1> و<p> و<span> و<label> |
<Text> بدور: title أو heading أو body أو label أو caption أو display |
<button onClick={…}> |
<Button onClick={props.onSave}>: تصبح خاصية الاستدعاء الراجع إجراءً |
<input>، ومربع اختيار، وأزرار اختيار، و<select> |
<TextInput> و<Checkbox> و<RadioGroup> و<Select>، لكلٍّ منها id يقرأ به التطبيق قيمته ويضبطها |
{ready && <X/>} و? : و!ready وstep === "review" |
مجموعات ومفاتيح يضبطها التطبيق |
items.map(…) |
صفوف: قائمة يحملها الملف، أو قائمة خاصية مقتطعة إلى حدٍّ أقصى، props.items.slice(0, 5) |
Hello, {name}! |
كلمات ثابتة تُدمج وقت الترجمة حول خانة يملؤها التطبيق |
| مكوّناتكم الخاصة والمقاطع، في ملف الشاشة أو في ملف بجواره | تُوسَّع وقت البناء، كأن الشاشة كُتبت مسطّحة |
style={{ padding: "16px" }}, color: "var(--text-muted)" |
خصائص النمط المُعلَنة، والأطوال بوحدات التخطيط، والألوان من السمة |
تذكر جداول شاشات من React بالضبط ما يقبله كل مكوّن. وهي تأتي من جداول Screen Compiler نفسه، فلا يمكن أن تبتعد عمّا يقبله.
ما ينتقل إلى تطبيقكم
لا يوجد JavaScript على الجهاز. الشاشة شجرة ثابتة يقودها تطبيقكم عبر إجراءات وحقول وخانات ومجموعات ومفاتيح مُرقّمة. لذلك تبقى بعض الأشياء مستبعدة بالتصميم، ولكلٍّ منها سبب:
- الحالة والخطافات (
useStateوuseEffectوالسياق). التطبيق يحمل الحالة ويضبط ما تعرضه الشاشة. valueوcheckedوonChangeلحقل ما. يقرأ التطبيق الحقل ويضبطه عبرidالخاص به.- الخصائص المنثورة (spread). لا يُعرف ما تحمله إلا عند تشغيل الكود.
- الأنماط المحسوبة، وقيم الألوان، وأوراق الأنماط العامة. النمط ثابت، والألوان ألوان السمة كي تستطيع سمة الخط الكبير إعادة تلوين كل شاشة ويُفحص التباين، ولا يوجد تتالٍ.
- الحركة.
- قائمة بلا حدٍّ أقصى. اقتطعوها،
.slice(0, 5)، كي تعرف الشاشة كم صفًّا يمكنها أن تعرض. - المقارنات غير خاصية
===سلسلة نصية، وifأوswitchفي دالة الشاشة. احسبوا الجواب في التطبيق ومرّروه خاصيةً. - المكوّنات الآتية من الحزم، والملفات الواقعة خارج مجلد الشاشة. لا تقرأ الشاشة إلا مجلدها وما تحته: ضعوا مكوّناتكم بجوارها،
./parts/header. - معالج يفعل أكثر من استدعاء خاصية. يتحوّل
onClick={() => props.onSave()}؛ وما زاد على ذلك عمل التطبيق.
ما يأتي به الطريق بعد ذلك
يسمّي تقرير التغطية هذه الخطوات المخطّط لها حين يحتاج إليها كودكم:
- مزيد من تخطيط CSS: تمدّد flex، و
alignSelf، والارتفاعان الأدنى والأقصى، والحشو على كل جانب، والهوامش؛ - عناصر HTML الشائعة، كلٌّ بقاعدة ثابتة واحدة؛
- وحدات CSS، صنف واحد لكل عنصر؛
- الطبقات: عناصر موضوعة بعضها فوق بعض؛
- الصور والإدخال المُقنَّع.
إلى أن تتحقق خطوة ما، تُرفض بناها بدل أن تُخمَّن. وكل خطوة تلتزم القاعدة نفسها: بدقة، أو لا شيء.
قراءة خطأ
يذكر الخطأ الملف والسطر والعمود، ورمزًا، وما الخلل، وسطرًا من المساعدة:
web-search.tsx:16:28: error[unknown-name]: `query` is not a prop of the component
help: text from the application must be a prop: take it as one, function Screen({ query }) { … }
مع أي خطأ، لا يُكتب شيء. والرموز هي:
| الرمز | معناه | ما العمل |
|---|---|---|
syntax |
الملف ليس TSX صالحًا، أو يخالف قاعدة تلتزمها كل وحدة. | صحّحوا الكود في الموضع المذكور. |
unsupported |
بنية خارج المجموعة الفرعية. | اتبعوا المساعدة: أعيدوا كتابتها ضمن المجموعة الفرعية، أو انقلوا العمل إلى التطبيق. |
unknown-element |
عنصر ليس من عناصر العُدّة، أو غير مستورد. | استوردوه من "nowayos:kit"، أو استخدموا عنصر العُدّة. |
unknown-prop |
خاصية أو خاصية نمط لا يقبلها العنصر. | استخدموا خاصية تذكرها الجداول له. |
invalid-value |
خاصية يقبلها العنصر، بقيمة لا يقبلها. | أعطوا قيمة من النوع الذي تذكره الجداول. |
missing-prop |
خاصية يحتاج إليها العنصر غير معطاة. | أعطوها: تُظهرها الجداول بخط عريض. |
invalid-children |
عنصر يحمل ما لا يمكنه حمله، مثل ابنين في <Screen> أو نص في <Column>. |
غلّفوها، أو ضعوا النص في <Text>. |
unknown-name |
اسم ليس خاصية ولا رمز تصميم ولا استيرادًا. | خذوه خاصيةً، أو أعلنوا عنه. |
duplicate-name |
شيئان سيحملان الاسم نفسه في الكود المُولَّد، مثل isReady وis_ready. |
أعيدوا تسمية أحدهما. |
reserved-name |
اسم تحجزه Rust أو الكود المُولَّد لنفسه، مثل type. |
أعيدوا تسميته. |
limit |
تجاوز حدٍّ للحجم أو العمق أو العدد. | اختصروا، أو قسّموا إلى مكوّنات. |
no-screen |
الملف بلا مكوّن شاشة: دالة تُرجع <Screen>. |
صدّروا واحدًا. |
internal |
عيب في Screen Compiler نفسه. | أبلغوا عنه، مع المُدخل الذي سبّبه. |
إذا كانت بنية تحتاجون إليها على الطريق ولم تُبنَ بعد، أخبرونا مع التقرير: فهو يُظهر أي الخطوات أهم.