أداة إنشاء الرموز البرمجية للكتلة هي دالة تنشئ الرمز البرمجي للكتلة وتُعيده كسلسلة. يعتمد الرمز الذي تنشئه الكتلة على نوعها:
- تحتوي وحدات القيم على اتصال إخراج. تعمل هذه الكتل مثل التعبيرات في لغة مستندة إلى النصوص وتُنشئ سلاسل تحتوي على تعبيرات.
- وحدات العبارة هي وحدات بدون اتصال بمخرج. تعمل هذه الكتل كعبارات في لغة مستندة إلى النصوص، وتُنشئ سلاسل تحتوي على عبارات.
كيفية كتابة أداة إنشاء رموز الكتل
لكلّ مجموعة مخصّصة تنشئها، عليك كتابة أداة إنشاء رموز مجموعات لكلّ لغة تريد إتاحتها. يُرجى العِلم أنّ جميع أدوات إنشاء الرموز البرمجية المكوّنة من وحدات مكتوبة بلغة JavaScript، حتى إذا كانت تُنشئ رمزًا بلغة أخرى.
تُنفِّذ جميع أدوات إنشاء الرموز البرمجية المجمّعة الخطوات التالية:
- استورِد أداة إنشاء رموز اللغات.
- الحصول على قيمة كل حقل وتحويلها إلى سلسلة رموز
- الحصول على سلاسل الرموز التي تم إنشاؤها بواسطة الكتل الداخلية، وهي كتل مرفقة ب inputs للقيمة والعبارة
- إنشاء سلسلة رمز العنصر وإعادتها
أمثلة على الكتل
على سبيل المثال، سنكتب أدوات إنشاء رموز JavaScript للكتل التالية.
custom_compare
هو كتلة قيمة تحتوي على إدخال قيمة باسمLEFT
، وأحد الحقول المنسدلة باسمOPERATOR
، وحقل رقمي باسمRIGHT
. ويقوم بإنشاء سلسلة تعبير من النوع'0 = 0'
.custom_if
هو عبارة عن كتلة عبارة تحتوي على حقل مربّع اختيار باسمNOT
وأحد مربعات إدخال القيمة باسمCONDITION
ومربع إدخال عبارة باسمTHEN
. وهي تنشئ سلسلة بيان من النوع'if (...) {\n...\n};\n'
.
يوضّح هذا المستند كيفية إنشاء منشئي النماذج خطوة بخطوة. يمكنك العثور على المولدات المكتملة في نهاية هذا المستند.
يُرجى العِلم أنّ هذه الكتل مخصّصة فقط لتوضيح عملية إنشاء الرموز البرمجية. في
تطبيق حقيقي، استخدِم الكتل المضمّنة logic_compare
وcontrols_if
.
استيراد أداة إنشاء رموز اللغات
يمكنك استيراد أداة إنشاء رموز اللغات باستخدام إحدى الطريقتَين التاليتَين. استخدِم
أداة الإنشاء المستورَدة لتخزين أدوات إنشاء الرموز البرمجية في العنصر forBlock
.
الوحدات
import {javascriptGenerator} from 'blockly/javascript';
import {pythonGenerator} from 'blockly/python';
import {phpGenerator} from 'blockly/php';
import {luaGenerator} from 'blockly/lua';
import {dartGenerator} from 'blockly/dart';
// Add block-code generators for the custom_if block.
javascriptGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
pythonGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
phpGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
luaGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
dartGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
Unpkg
يجب تضمين أداة إنشاء المحتوى بعد تضمين Blockly.
<script src="https://unpkg.com/blockly"></script>
<script src="https://unpkg.com/blockly/javascript_compressed"></script>
<script src="https://unpkg.com/blockly/python_compressed"></script>
<script src="https://unpkg.com/blockly/php_compressed"></script>
<script src="https://unpkg.com/blockly/lua_compressed"></script>
<script src="https://unpkg.com/blockly/dart_compressed"></script>
// Add block-code generators for the custom_if block.
javascript.javascriptGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
python.pythonGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
php.phpGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
lua.luaGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
dart.dartGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
النصوص البرمجية المحلية
يجب تضمين أداة إنشاء المحتوى بعد تضمين Blockly.
<script src="blockly_compressed.js"></script>
<script src="javascript_compressed.js"></script>
<script src="python_compressed.js"></script>
<script src="php_compressed.js"></script>
<script src="lua_compressed.js"></script>
<script src="dart_compressed.js"></script>
// Add block-code generators for the custom_if block.
javascript.javascriptGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
python.pythonGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
php.phpGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
lua.luaGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
dart.dartGenerator.forBlock['custom_if'] = function (block, generator) { /* ... */ };
الحصول على قيم الحقول
تسمح الحقول للمستخدمين بإدخال قيم مثل السلاسل والأرقام والألوان. للحصول على قيمة
الحقل، استخدِم getFieldValue
. يختلف ما يتم إرجاعه من حقل إلى
حقل. على سبيل المثال، تعرض الحقول النصية النص الدقيق الذي أدخله المستخدم، ولكن تعرض الحقول المنسدلة سلسلة محايدة لغويًا مرتبطة بالعنصر الذي اختاره المستخدم. لمزيد من المعلومات، يُرجى الاطّلاع على مستندات الحقول المضمّنة.
استنادًا إلى الحقل، قد تحتاج إلى تحويل القيمة المعروضة قبل استخدامها في الرمز.
custom_compare
javascriptGenerator.forBlock['custom_compare'] = function (block, generator) {
// Use the value of the OPERATOR dropdown to look up the actual operator.
const OPERATORS = {
EQUALS: '==',
LESS: '<',
GREATER: '>',
};
const operator = OPERATORS[block.getFieldValue('OPERATOR')];
// The value of the RIGHT field is a number and can be used directly when
// building the block's code string.
const right = block.getFieldValue('RIGHT');
...
}
custom_if
javascriptGenerator.forBlock['custom_if'] = function (block, generator) {
// Use the value of the NOT field to get the negation operator (if any).
const checkbox = block.getFieldValue('NOT');
const negate = checkbox === 'TRUE' ? '!' : '';
...
}
لمزيد من المعلومات، يُرجى الاطّلاع على تحويل قيم الحقل.
الحصول على الرمز من الكتل الداخلية
الكتل الداخلية هي الكتل المرفقة بقيمة الكتلة ومدخلات البيان.
على سبيل المثال، يحتوي العنصر custom_if
على عنصر داخلي للقيمة لشرط if،
وعناصر داخلية للعبارة للرمز الذي يتم تنفيذه إذا كان الشرط
صحيحًا.
على عكس قيم الحقول، يكون الرمز الذي تحصل عليه من الكتل الداخلية جاهزًا للاستخدام ولا يحتاج إلى التحويل.
وحدات القيمة الداخلية
للحصول على رمز من قالب داخلي مرفق بإدخال قيمة، استخدِم valueToCode
.
تستدعي هذه الطريقة أداة إنشاء الرموز البرمجية للوحدة الداخلية.
custom_compare
import {javascriptGenerator, Order} from 'blockly/javascript';
javascriptGenerator.forBlock['custom_compare'] = function (block, generator) {
...
const order = operator === '==' ? Order.EQUALITY : Order.RELATIONAL;
const left = generator.valueToCode(block, 'LEFT', order);
...
}
custom_if
import {javascriptGenerator, Order} from 'blockly/javascript';
javascriptGenerator.forBlock['custom_if'] = function (block, generator) {
...
const order = checkbox === 'TRUE' ? Order.LOGICAL_NOT : Order.NONE;
const condition = generator.valueToCode(block, 'CONDITION', order) || 'false';
...
}
عند الاتصال برقم valueToCode
، عليك إخباره بالمشغِّل الأقوى في
الرمز الذي سيتم تطبيقه على رمز الكتلة الداخلية. يتيح ذلك لـ valueToCode
تحديد ما إذا كان يجب تضمين رمز الكتلة الداخلية بين قوسين.
على سبيل المثال، يؤدي وضع علامة في مربّع NOT
في custom_if
إلى تطبيق عامل حسابي منطقي للنفي (!
) على الشرط. في هذه الحالة، يتم تمرير Order.LOGICAL_NOT
، وهي الأولوية الخاصة بعامل التشغيل not، إلى valueToCode
، ويقارن valueToCode
هذه الأولوية بأولوية عامل التشغيل الأضعف في الكتلة الداخلية. ثم يلفّ
الرمز البرمجي للوحدة الداخلية حسب الحاجة:
- إذا كان
CONDITION
عبارة عن كتلة متغيّر، لا تضيفvalueToCode
قوسَين لأنّه يمكن تطبيق عامل التشغيل not مباشرةً على متغيّر (!myBoolean
). - إذا كان
CONDITION
عبارة عن كتلة مقارنة، يضيفvalueToCode
قوسَين لكي ينطبق عامل التشغيل not على المقارنة بأكملها (!(a < b)
) بدلاً من القيمة اليمنى (!a < b
).
لست بحاجة إلى معرفة ما إذا كان valueToCode
قد أضاف الأقواس. ما عليك سوى
تمرير الأولوية إلى valueToCode
وإضافة الرمز المعروض إلى
سلسلة الرموز. لمزيد من المعلومات، يُرجى الاطّلاع على valueToCode
precedence.
وحدات العبارة الداخلية
للحصول على رمز من كتلة داخلية مرفقة بإدخال عبارة، يمكنك استدعاء
statementToCode
. تستدعي هذه الطريقة أداة إنشاء الرموز البرمجية للوحدة الداخلية و
تعالج رمز المسافة البادئة.
custom_compare
لا تحتوي مجموعة custom_compare
على أيّ إدخالات لبيان.
custom_if
javascriptGenerator.forBlock['custom_if'] = function (block, generator) {
...
const statements = generator.statementToCode(block, 'THEN');
...
}
ما عليك سوى استدعاء statementToCode
للكتلة الداخلية المرتبطة مباشرةً
بإدخال عبارة. يعالج statementToCode
أيّ وحدات إضافية مرفقة
بالوحدة الأولى.
إنشاء سلسلة الرمز وإعادتها
بعد الحصول على رمز الحقول والكتل الداخلية، أنشئ سلسلتَي الرموز البرمجية للكتل وأرسِلَهما. يعتمد ما يمكنك إرجاعه بالضبط على نوع المحتوى الذي تم حظره:
كتل القيم: عرض مصفوفة تحتوي على سلسلة الرمز و الأولوية لعامل التشغيل الأضعف في الرمز يستخدم
valueToCode
هذا العنصر لتحديد ما إذا كان يجب تضمين الرمز البرمجي بين قوسَين عندما يتم استخدام العنصر كعنصر داخلي. لمزيد من المعلومات، يُرجى الاطّلاع على أولوية ناتج الدوالّ المتعلّقة بالسلسلة.كتل العبارة: عرض سلسلة الرمز
custom_compare
import {javascriptGenerator, Order} from 'blockly/javascript';
javascriptGenerator.forBlock['custom_compare'] = function (block, generator) {
...
const order = operator === '==' ? Order.EQUALITY : Order.RELATIONAL;
...
const code = left + ' ' + operator + ' ' + right;
return [code, order];
}
custom_if
javascriptGenerator.forBlock['custom_if'] = function (block, generator) {
...
const code = 'if (' + negate + condition + ') {\n' + statements + '}\n';
return code;
}
إذا كنت تستخدم رمزًا لبلوك قيمة داخلية عدة مرات في سلسلة الرمز، يجب تخزين الرمز من ذلك البلوك لتجنُّب الأخطاء الدقيقة والتأثيرات الجانبية غير المرغوب فيها.
أدوات إنشاء الرموز الكاملة
في ما يلي أدوات إنشاء الرموز الكاملة لكلّ قسم، وذلك للرجوع إليها:
custom_compare
import {javascriptGenerator, Order} from 'blockly/javascript';
javascriptGenerator.forBlock['custom_compare'] = function (block, generator) {
const OPERATORS = {
EQUALS: '==',
LESS: '<',
GREATER: '>',
};
const operator = OPERATORS[block.getFieldValue('OPERATOR')];
const order = operator === '==' ? Order.EQUALITY : Order.RELATIONAL;
const left = generator.valueToCode(block, 'LEFT', order);
const right = block.getFieldValue('RIGHT');
const code = left + ' ' + operator + ' ' + right;
return [code, order];
}
custom_if
import {javascriptGenerator, Order} from 'blockly/javascript';
javascriptGenerator.forBlock['custom_if'] = function (block, generator) {
const checkbox = block.getFieldValue('NOT');
const negate = checkbox === 'TRUE' ? '!' : '';
const order = checkbox === 'TRUE' ? Order.LOGICAL_NOT : Order.NONE;
const condition = generator.valueToCode(block, 'CONDITION', order) || 'false';
const statements = generator.statementToCode(block, 'THEN');
const code = 'if (' + negate + condition + ') {\n' + statements + '}\n';
return code;
}