أهلاً بيك يا صديقي المطور في الدليل التشريحي لأكتر كابوس مرعب بيقابل أي مبرمج ووردبريس شغال على محرر المكونات Gutenberg: رسالة “This block contains unexpected or invalid content” (أو بالواجهة العربية: “يحتوي هذا البلوك على محتوى غير متوقع أو غير صالح”) مصحوبة بزرارين يثيرون الرعب أكتر: “Attempt Block Recovery” و “Resolve”!
الرسالة دي لما بتظهر في بيئة تجريبية بتكون مجرد إزعاج بسيط، لكن لما تصحى الصبح تلاقي عميلك بيكلمك في التليفون صوته بيرجف لإن محرري الموقع فتحوا 2,000 مقال ولقوا كل المقالات مطلعة الرسالة دي، ومحرر منهم داس على زرار “Attempt Block Recovery” فقام جوتنبرج مسح نص المحتوى وحوله لكتل HTML ميتة، ساعتها بتعرف إن “Block Validation” مش موضوع هزار، بل هو صمام الأمان المعماري اللي بنته نواة ووردبريس لحماية تكامل البيانات. في المقال ده، هنشرح خوارزمية التحقق خطوة بخطوة، هنفكك أسباب الفشل الخمسة الأكثر شيوعاً، إزاي تقرأ الـ Console Diff باحترافية، وإزاي تعالج الأخطاء بدون فقدان حرف واحد من المقالات بالعامية المصرية التقنية الأصيلة.
| نوع سبب الخطأ (Error Origin) | البصمة في الـ Browser Console | السبب الجذري في الكود (Root Cause) | الحل التقني الجذري (Architectural Fix) | درجة الخطورة على الموقع |
|---|---|---|---|---|
| بيانات غير قطعية (Non-deterministic data) | Expected: <time>10:15</time>, Actual: <time>10:30</time> | وضع دوال توليد أرقام عشوائية Math.random() أو تواريخ لحظية Date.now() داخل save(). | نقل توليد التواريخ لـ attributes أو تحويل البلوك إلى ديناميكي يعتمد على السيرفر. | حرجة جداً؛ تضرب البلوك مع كل فتحة جديدة للمحرر. |
| تعديل هيكل الـ HTML في الكود | Expected: <div class="new-box">, Actual: <div class="old-box"> | تغيير وسوم الـ HTML أو أسماء الكلاسات في دالة save دون كتابة قواعد الترحيل (Deprecation). | إضافة كود الـ HTML القديم كمدخل في مصفوفة deprecated داخل registerBlockType. | شاملة؛ تؤثر على كافة المقالات التاريخية القديمة فوراً. |
| اختلاف الفراغات والأسطر (Whitespace Diff) | Expected: <p>Text</p>, Actual: <p>n Textn</p> | تعديل أدوات التنسيق (Prettier/ESLint) لطريقة تكسير الأسطر في الـ JSX بين الحفظ والإنتاج. | الاعتماد على عناصر RichText.Content وضبط إعدادات Prettier لتجنب مسافات الـ JSX العشوائية. | متوسطة؛ تظهر أحياناً وتختفي بحسب محرر الأكواد. |
| تعديل قاعدة البيانات المباشر (DB Mutations) | Content mismatch in parsed block HTML | قيام سكربت PHP أو إضافة سيو بالبحث والاستبدال في post_content مباشرة دون تحديث الـ Delimiters. | استخدام خطافات الفلاتر وقت العرض (Render Filters) بدلاً من التعديل العنيف في قاعدة البيانات. | كارثية؛ تؤدي أحياناً لفقدان البلوك بالكامل وتحويله لـ Classic Block. |
| أخطاء الرموز الخاصة والـ Entities | Expected: &, Actual: & | عدم تعقيم أو فك تشفير الرموز الخاصة مثل علامات التنصيص والـ Ampersand في النصوص المحفوظة. | استخدام دوال التشفير القياسية والاعتماد الصارم على مخرجات مكونات @wordpress/block-editor. | منخفضة إلى متوسطة بحسب طبيعة النصوص واللغات. |
تشريح خوارزمية التحقق: كيف يفحص ووردبريس البلوك في المتصفح؟
عشان تحل المشكلة، لازم تفهم محرر جوتنبرج بيفكر إزاي لما تيجي تفتح مقال محفوظ في لوحة التحكم. العملية بتمر بالخطوات الرياضية التالية في حزمة @wordpress/blocks:
-
استخراج كود الـ HTML المحفوظ مسبقاً (Raw Content Extraction):
محلل النواة (Gutenberg Parser) بيقرأ المقال من قاعدة البيانات، وبيقطع تعليق البلوك ويستخرج كود الـ HTML اللي متخزن بين وسم الفتح ووسم الإغلاق؛ النص ده بنسميه
rawContent. -
توليد كود الـ HTML المفترض برمجياً (Generated Content Simulation):
المحرر بياخد الخصائص (Attributes) المستخرجة من تعليق البلوك، وبيرميها داخل دالة
save( { attributes } )المسجلة حالياً في ملفات الجافاسكريبت بتاعة موقعك، ويشوف الـ JSX هينتج عنه كود HTML شكله إيه؛ النص ده بنسميهgeneratedHTML. -
مرحلة التطبيع المعياري (String Normalization):
جوتنبرج مش غبي؛ هو عارف إن المتصفحات ممكن تغير ترتيب الـ Attributes (مثلاً تحط
classقبلidأو العكس). فبيقوم بتمرير النصين على خوارزمية تطبيع بتوحد ترتيب السمات، وتزيل الفراغات الميتة في أطراف الوسوم. -
المقارنة الصارمة (Strict Equality Check):
بيقارن النصين بحرفية تامة:
rawContent === generatedHTML. لو طلعوا متطابقين بنسبة 100%، البلوك بيعدي بسلام ويفتح في شاشة التحرير كأنه لم يكن هناك شيء. -
فحص الترحيل البديل (Fallback Deprecations):
لو فشلت المقارنة، جوتنبرج ما بيستسلمش فوراً! بيبدأ يلف على مصفوفة
deprecatedالمعرفة في البلوك واحدة ورا التانية، وينفذ دوال الـsaveالقديمة. لو لقى واحدة منهم مطابقة، بيشغل دالةmigrate()ويرقي البلوك في صمت تام بدون أي رسائل خطأ للمحرر! -
إطلاق صافرة الإنذار (Validation Failure):
لو فشلت المقارنة مع الكود الحالي ومع كل الـ Deprecations المسجلة، ساعتها جوتنبرج بيرفع الراية الحمراء ويطبع تفاصيل الفشل في الـ Browser Console ويعرض الرسالة المرعبة للمستخدم.
فن قراءة الـ Console Diff: كيف تصطاد الخطأ في 30 ثانية؟
أول ما تشوف الخطأ، افتح أدوات المطور في متصفحك (Inspect Element -> Console). هتلاقي جوتنبرج طابع رسالة تحذيرية مفصلة جداً بتبدأ بـ:
Block validation: Block validation failed for `enterprise/custom-banner` ({...}).
Content generated by `save` function:
Content retrieved from post body:
بص على السطور دي بعين الصقر:
Content generated by 'save' function: ده الكود اللي ملف الجافاسكريبت بتاعك الحالي بيحاول يولده النهاردة.Content retrieved from post body: ده الكود القديم اللي اتخزن في قاعدة البيانات زمان لما المقال اتنشر لأول مرة.- المقارنة السريعة: هتلاحظ فوراً إن الكود الجديد فيه كلاس إضافي اسمه
az-banner-v2، بينما المقال القديم مفهوش الكلاس ده! هنا السبب واضح وضوح الشمس: أنت عدلت الكلاس في ملف الـ JS بس نسيت تعرف جوتنبرج إن المقالات القديمة لسه بالكلاس القديم عبر مصفوفةdeprecated.
أمثلة برمجية: الكود الكارثي مقابل الكود المحصن
1. النموذج الكارثي: إدراج بيانات ديناميكية غير قطعية في save()
// ❌ كود كارثي يسبب Block Validation Error لكل من يفتح المقال في المستقبل!
import { useBlockProps } from '@wordpress/block-editor';
export default function save( { attributes } ) {
const blockProps = useBlockProps.save();
// خطأ قاتل: Date.now() تعطي رقماً مختلفاً مع كل ملي ثانية!
const renderTimestamp = Date.now();
// خطأ قاتل: Math.random() ينتج ID عشوائياً مختلفاً عند كل مقارنة!
const uniqueId = 'box-' + Math.floor( Math.random() * 10000 );
return (
تم حفظ هذا المحتوى في التوقيت: { renderTimestamp }
);
}
لماذا يتدمر هذا البلوك حتماً؟
لأنك لما حفظت المقال الساعة 5:00، اتخزن الرقم 1730000000. لما تفتح المقال الساعة 6:00، دالة save هتتنفذ عشان تقارن، فهتولد الرقم 1730003600! المقارنة تفشل، ويضرب البلوك في الحال!
2. النموذج السليم: خصائص قطعية محفوظة في الـ Attributes
// ✅ الكود الهندسي المحصن والمستقر بنسبة 100%
import { useBlockProps } from '@wordpress/block-editor';
export default function save( { attributes } ) {
const { uniqueId, createdTimeText } = attributes;
const blockProps = useBlockProps.save();
return (
تاريخ النشر المعتمد: { createdTimeText }
);
}
التصحيح المعماري: قمنا بتوليد المعرف الفريد والوقت داخل دالة التحرير (edit.js) مرة واحدة فقط عند إدراج البلوك، وحفظناهم كـ attributes صريحة في المقال. دالة save() أصبحت دالة نقية (Pure Deterministic Function) تقرأ فقط من الـ attributes وتخرج نفس الـ HTML للأبد!
أداة تشخيص برمجية تفاعلية لفحص البلوكات التالفة في الكونسول
لو عندك بلوك ضارب في شاشة التحرير ومش عارف تطلع تفاصيله بدقة، افتح الـ Console في المتصفح وانسخ السكربت التشخيصي ده، هيديك تقرير كامل عن حالة البلوك المختار حالياً:
// انسخ هذا الكود في كونسول المتصفح أثناء فتح المقال المتضرر
(function diagnoseActiveBlock() {
const editor = wp.data.select( 'core/block-editor' );
const selectedBlock = editor.getSelectedBlock();
if ( ! selectedBlock ) {
console.warn( '⚠️ من فضلك حدد البلوك التالف أولاً بالضغط عليه داخل المحرر.' );
return;
}
console.group( '🔍 تقرير الفحص المعماري للبلوك: ' + selectedBlock.name );
console.log( 'معرف البلوك (Client ID):', selectedBlock.clientId );
console.log( 'هل البلوك صالح (isValid):', selectedBlock.isValid );
console.log( 'الخصائص الحالية (Attributes):', selectedBlock.attributes );
console.log( 'كود الـ HTML الأصلي (Original Content):', selectedBlock.originalContent );
// محاولة محاكاة كود الـ Save برمجياً
const blockType = wp.blocks.getBlockType( selectedBlock.name );
if ( blockType && blockType.save ) {
const simulatedHTML = wp.blocks.getSaveContent( blockType, selectedBlock.attributes, selectedBlock.innerBlocks );
console.log( 'كود الـ HTML المولد حالياً (Simulated Save):', simulatedHTML );
if ( selectedBlock.originalContent === simulatedHTML ) {
console.info( '✅ كود الـ HTML متطابق تماماً! لا يوجد خطأ في الـ Markup.' );
} else {
console.error( '❌ تضارب مؤكد بين المحتوى المحفوظ والمولد! هذا هو سبب رسالة الخطأ.' );
}
}
console.groupEnd();
})();دراسة حالة واقعية: كارثة منصة دروس الثانوية العامة والجامعات في مصر
خلفية المشروع وأبعاد الأزمة
منصة تعليمية إلكترونية كبرى في مصر تقدم كورسات ومذكرات لطلاب الثانوية العامة والجامعات (أكثر من 850,000 طالب مسجل). المنصة تحتوي على مكتبة تضم أكثر من 3,500 درس ومحاضرة تعليمية. كل محاضرة كانت مبنية باستخدام بلوك مخصص لعرض “خطة الدرس وقائمة الفيديوهات والملفات المرفقة” (Course Curriculum Accordion).
الأزمة التشخيصية (The Crisis)
قام أحد المطورين الجدد بتحديث إضافة المنصة التعليمية؛ وأراد إضافة شارة صغيرة في أسفل خطة الدرس تعرض: “آخر مراجعة للمحتوى بواسطة المعلم: [تاريخ اليوم]”. فقام بكتابة سطر جافاسكريبت داخل دالة save() يقرأ تاريخ اليوم بصيغة new Date().toLocaleDateString('ar-EG')!
- في اليوم التالي، دخل 90 معلماً ومساعداً تحريرياً لتحديث المذكرات وإضافة أسئلة الامتحانات.
- بمجرد فتح أي درس، تفاجأ الجميع بظهور رسالة “This block contains unexpected or invalid content” باللون الأصفر والأحمر في جميع دروس المنصة البالغ عددها 3,500 درس!
- الأزمة الكبرى وقعت عندما بدأ المعلمون بدافع حسن النية في الضغط على زر “Attempt Block Recovery”، مما تسبب في إزالة مشغلات الفيديو المشفرة وحذف روابط ملفات الـ PDF المرفقة من أكثر من 450 درساً خلال ساعات قليلة!
- توقفت مبيعات الكورسات، وانهالت الاتصالات على الدعم الفني من أولياء الأمور والطلاب العالقين قبل الامتحانات بأيام قليلة.
الحل المعماري الجذري (The Architectural Solution)
تم تشكيل غرفة طوارئ برمجية لحل الأزمة بدون فقدان أي بيانات إضافية:
- إصدار تعميم صارم لكافة المعلمين بإيقاف فتح الدروس أو الضغط على زر “Attempt Block Recovery” فورياً.
- حذف كود التاريخ غير القطعي من دالة
save()فوراً، وإعادته لحالته الأصلية المطابقة لما هو محفوظ في قاعدة البيانات. - إضافة التاريخ كـ Dynamic Server Block يُقرأ من ميتا المقال (Post Modified Date) على السيرفر في الواجهة الأمامية دون تخزينه في كود الـ HTML الثابت للبلوك.
- استعادة النسخ الاحتياطية للـ 450 درساً التي تضررت من ضغطات “Block Recovery” باستخدام ميزة الـ Revisions التلقائية في ووردبريس.
- كتابة اختبارات وحدة آلية (Automated Block Validation Tests) باستخدام Jest للتأكد من أن دالة
saveتنتج مخرجات قطعية لا تتغير قبل اعتماد أي تحديث مستقبلي.
جدول قياس مؤشرات الأداء والتعافي السريع (Metrics Table)
| المؤشر الفني والتشغيلي | أثناء الأزمة (دالة التاريخ اللحظي) | بعد التصحيح المعماري الصارم | القيمة المستعادة والأثر النهائي |
|---|---|---|---|
| نسبة الدروس المصابة بالخطأ (Failure Rate) | 100% (جميع الـ 3,500 درس أظهرت الخطأ) | 0% (تعافي كامل لكافة صفحات المنصة) | استعادة استقرار المنصة بنسبة 100% |
| الدروس المتضررة بفقدان وسائط الفيديو | 450 درساً تالفاً بسبب Recovery العشوائي | صفر دروس تالفة (استعادة كاملة بالـ Revisions) | حماية المحتوى التعليمي واستعادة ثقة الطلاب |
| تذاكر الدعم الفني وشكاوى أولياء الأمور | 1,340 تذكرة اعتراض واستفسار يومياً | تراجع طبيعي لأقل من 15 تذكرة اعتيادية | تخفيض الضغط على الدعم بنسبة 98.8% |
| تغطية اختبارات التحقق الآلية (Jest Testing) | 0% (تحديثات يدوية بلا اختبارات) | 100% لكافة البلوكات التعليمية في المنظومة | منع تكرار الحادثة نهائياً في المستقبل |
الوصايا العشر لمنع وتصحيح أخطاء Block Validation
- دالة save() هي دالة نقية (Pure Function): لا تضع بداخلها أي متغيرات عشوائية، تواريخ لحظية، أو قراءات من الـ LocalStorage أو الـ Cookies.
- إياك والضغط العشوائي على “Attempt Block Recovery”: هذا الزر يقوم بمحاولة ترقيع قاسية غالباً ما تنتهي بحذف العناصر المتداخلة أو تحويل البلوك إلى كود خام ميت.
- افحص Browser Console أولاً: هو المصباح الذي يكشف لك بالسطر والمسافة أين يكمن التضارب بين الـ Generated والـ Retrieved HTML.
- أي تعديل في الـ HTML يتطلب Deprecation فوراً: إذا قمت بتغيير كلاس أو نقل وسم في بلوك منشور بالفعل، اكتب قاعدة ترحيل في مصفوفة
deprecatedقبل رفع الكود. - استخدم RichText.Content دائماً في الحفظ: لا تطبع نصوص الـ RichText كمتغيرات JSX عادية؛ استخدم المكون المخصص للحفاظ على سلامة تنسيق الحروف.
- احذر من أدوات تنسيق الأكواد التلقائية (Prettier): اضبط إعدادات Prettier بحيث لا تضع فواصل أسطر ومسافات زائدة داخل وسوم النصوص في الـ JSX.
- لا تعدل محتوى المقالات بـ SQL Queries عشوائية: عمليات البحث والاستبدال المباشرة في عمود
post_contentهي أسرع طريقة لتخريب تطابق البلوكات. - حول البلوك إلى ديناميكي إذا كانت بياناته متغيرة: إذا كنت تحتاج لعرض بيانات تتجدد دورياً، اعتمد على
render.phpواجعلsave() { return null; }وتخلص من الصداع للأبد. - اكتب اختبارات Jest Block Fixtures: قم بإنشاء اختبارات تقارن مخرجات الـ Save مع نماذج HTML تاريخية في نظام الـ CI/CD الخاص بفريقك.
- درب محرري الموقع على الإبلاغ الفوري: علم فريق كتابة المحتوى ألا يقوموا بحل المشاكل بأنفسهم، بل يبلغون الفريق البرمجي فور ظهور أول راية تحذيرية صفراء.
هندسة الفحص التلقائي في خطوط الإنتاج (Automated CI/CD Block Testing)
يا صديقي المطور، الفرق الجوهري بين المطور الهاوي والمهندس المحترف في الشركات الكبرى هو أن المحترف لا ينتظر حتى يشتكي العملاء من أخطاء الـ Validation في السيرفر الحي، بل يقوم ببناء درع أمني آلي في خطوط التكامل المستمر (CI/CD Pipeline) يمنع دمج أي كود (Pull Request) يكسر التوافق مع المقالات السابقة!
باستخدام حزمة @wordpress/jest-preset-default، يمكنك إنشاء ما يسمى بـ Fixture Testing: وهو الاحتفاظ بنماذج HTML حقيقية لمقالات منشورة مسبقاً، واختبار ما إذا كانت دالة validateBlock() تنجح في مطابقتها مع كود الـ JavaScript الجديد أم تفشل.
كود عملي: اختبار التحقق الآلي للبلوكات عبر Jest
/**
* اختبار التحقق المعماري للبلوك في بيئة Jest
* File: test/block-validation.test.js
*/
import { registerBlockType, unregisterBlockType } from '@wordpress/blocks';
import { validateBlock } from '@wordpress/blocks';
// استيراد إعدادات البلوك الحالي
import metadata from '../src/block.json';
import edit from '../src/edit';
import save from '../src/save';
import deprecated from '../src/deprecated';
describe( 'فحص سلامة واستقرار بلوك البانر (enterprise/custom-banner)', () => {
beforeAll( () => {
registerBlockType( metadata.name, {
...metadata,
edit,
save,
deprecated,
} );
} );
afterAll( () => {
unregisterBlockType( metadata.name );
} );
it( 'يجب أن ينجح في التحقق من صحة كود HTML المسجل في مقال تم نشره في عام 2023', () => {
// نص الـ HTML الحقيقي المخزن في قاعدة بيانات السيرفر الحي
const historicalRawHTML = '';
const historicalAttributes = {
title: 'أهلاً بكم في مصر'
};
// تشغيل خوارزمية التحقق الرسمية لنواة ووردبريس
const isValid = validateBlock( {
name: metadata.name,
attributes: historicalAttributes,
originalContent: historicalRawHTML,
} );
// التأكد من أن البلوك صالح بنسبة 100% ولا يظهر راية التحذير الصفراء
expect( isValid ).toBe( true );
} );
} );
لو أحد المطورين في فريقك قام بتعديل كلاس في ملف save.js بدون كتابة قاعدة ترحيل في deprecated.js، سيفشل هذا الاختبار فوراً على GitHub Actions ولن يتم دمج الكود إطلاقاً، مما يحمي قاعدة بيانات موقعك من أي تلف محتمل للأبد!
معضلة تشفير الحروف العربية والتشكيل (Arabic UTF-8 Entities & Unicode Normalization)
في المواقع العربية، كثيراً ما يظهر خطأ Block Validation غامض جداً، تفتح الـ Console وتجد أن الكود المتوقع والمحفوظ متطابقان في كل حرف باللغة العربية! كيف يحدث ذلك؟
السر يكمن في ما يسمى بالـ Unicode Normalization والرموز الخاصة:
- التشكيل والحركات (Diacritics): في لغة البرمجة، حرف “أَ” (ألف فوقها همزة وفتحة) يمكن كتابته برمز يونيكود واحد مدمج (NFC)، أو برمزين منفصلين: رمز الألف ويليه رمز الفتحة (NFD). لو كان المتصفح يرسل أحدهما ووردبريس يحفظ الآخر، فإن المقارنة النصية ستفشل برمجياً رغم تطابقهما البصري تماماً في عين القارئ!
- المسافات غير المرئية (Zero-Width Non-Joiner – ZWNJ): بعض لوحات المفاتيح تدرج مسافات غير مرئية تفصل الحروف، واختلاف وجودها بين محرر React وقاعدة البيانات يفشل المقارنة.
- علامات التنصيص الذكية (Smart Quotes): ووردبريس يمتلك فلتر داخلي قديم اسمه
wptexturizeيقوم بتحويل علامات التنصيص العادية" "إلى علامات مائلة ذكية“ ”. إذا قام هذا الفلتر بتعديل النص المحفوظ أثناء دورة الحفظ ولم يتم استدعاؤه في دالة الـ Save بالجافاسكريبت، يحدث تضارب فوري في التحقق!
الحل الهندسي: الاعتماد الدائم على مكونات RichText و RichText.Content الرسمية، وتجنب عمل نصوص معدلة يدوياً عبر دوال استبدال النصوص البسيطة (Regex String Replacements) في الأكواد.
الأسئلة الشائعة حول أخطاء Block Validation في جوتنبرج (20 سؤالاً وجواباً تفصيلياً)
1. ما معنى رسالة “This block contains unexpected or invalid content”؟
تعني أن كود الـ HTML المسجل في قاعدة البيانات لهذا المقال يختلف عن كود الـ HTML الذي تنتجه دالة save() المسجلة حالياً في ملفات جافاسكريبت البلوك.
2. ماذا يفعل خيار “Attempt Block Recovery” بالتحديد؟
يقوم بمحاولة استخراج الخصائص ومطابقة المحتوى قسراً؛ وإذا فشل، يقوم بتجريد البلوك من ميزاته وتحويله إلى كود HTML خام أو وسم كلاسيكي، مما قد يتسبب في فقدان بعض التنسيقات.
3. هل يؤثر خطأ Block Validation على زوار الموقع في الواجهة الأمامية؟
لا، الزوار يرون كود الـ HTML المسجل مسبقاً في قاعدة البيانات بشكل طبيعي، والخطأ يظهر فقط للمحررين داخل لوحة تحكم ووردبريس عند فتح المقال للتحرير.
4. كيف أكتشف الفرق بين الكود المتوقع والمحفوظ بدقة؟
بفتح شاشة الـ Console في أدوات المطور (DevTools)؛ حيث يطبع ووردبريس مقارنة تفصيلية بعنوان Content generated by 'save' function مقابل Content retrieved from post body.
5. لماذا تسبب دالة Math.random() تلف البلوك؟
لأنها تولد قيمة مختلفة في كل مرة يتم فيها تقييم الكود، مما يجعل المقارنة بين كود الحفظ الأصلي وكود الفحص الحالي مستحيلة التطابق الرياضي.
6. كيف أغير كلاس CSS في البلوك دون أن يتلف في المقالات المنشورة؟
عن طريق إضافة البنية القديمة بالكلاس القديم كعنصر داخل مصفوفة deprecated في ملف تسجيل البلوك، ليقوم ووردبريس بترحيلها آلياً بدون أي أخطاء.
7. هل يمكن أن تتسبب مسافة بيضاء واحدة (Space) في فشل التحقق؟
نعم، في بعض الحالات الخاصة التي تتعلق بالنصوص داخل الوسوم الحساسة مثل <pre> أو عند اختلاف فواصل الأسطر بين أنظمة التشغيل ومحررات النصوص.
8. ما هو الفرق بين زر “Resolve” وزر “Convert to HTML”؟
زر Resolve يفتح نافذة تطلب منك الاختيار بين تحويل البلوك إلى كود HTML ثابت أو محاولة استعادته، بينما Convert to HTML يحوله مباشرة لبلوك كود خام.
9. كيف أحمي البلوك من أخطاء التحقق نهائياً؟
الحل الأقوى هو تحويله إلى Dynamic Block وجعل دالة save ترجع null والاعتماد على render.php، حيث لا يتم فحص الـ HTML إطلاقاً.
10. هل إضافات الـ Caching يمكن أن تسبب Block Validation؟
إضافات الكاش السيرفري لا تسبب ذلك، لكن بعض إضافات تحسين الخطوط أو الـ Minification العنيفة التي تعدل قاعدة البيانات قد تتسبب في تشويه نصوص البلوكات.
11. ماذا أفعل لو قام محرر بالضغط على Recover وفقد محتواه؟
افتح سجل مراجعات المقال (Post Revisions) فوراً في ووردبريس واستعد آخر نسخة محفوظة قبل وقت وقوع الخطأ بضغطة زر واحدة.
12. هل تؤثر لغة الموقع (عربي / إنجليزي) على سلامة التحقق؟
إذا كانت هناك نصوص ثابتة مدمجة داخل save() مترجمة بدوال الترجمة، فإن تغيير لغة الموقع قد يغير النص المتوقع ويفشل التحقق؛ لذا لا تضع نصوصاً ثابتة مترجمة في دالة الحفظ.
13. كيف أختبر سلامة البلوكات برمجياً في بيئة الـ CI/CD؟
باستخدام حزمة @wordpress/jest-preset-default وتطبيق دالة validateBlock() على نماذج مسجلة ومحفوظة مسبقاً من المقالات للتأكد من عدم كسر التوافق.
14. هل تغيير الـ Attributes في block.json يكسر البلوك؟
إضافة خصائص جديدة بقيم افتراضية لا تكسر البلوك، لكن تغيير أسماء خصائص قديمة مستخدمة في save() سيكسر التحقق حتماً ما لم توفر Deprecation.
15. ما هي وظيفة دالة isEligible() داخل مصفوفة Deprecation؟
هي دالة شرطية اختيارية تفحص كود الـ HTML والخصائص القديمة لتقرر ما إذا كانت هذه النسخة الملغاة تنطبق على هذا البلوك بعينه أم لا.
16. لماذا لا يظهر الخطأ عندما أقوم بإدراج البلوك لأول مرة؟
لأن التحقق لا يبدأ إلا عندما يكون هناك محتوى محفوظ مسبقاً في قاعدة البيانات تتم مقارنته مع مخرجات الكود؛ في الإدراج الأول لا يوجد محتوى قديم للمقارنة.
17. كيف يمكنني إخفاء رسالة التحقق التالفة برمجياً؟
لا ينصح أبداً بإخفائها بـ CSS؛ لأن المشكلة هيكلية في البيانات، والحل الصحيح هو إصلاح الكود أو إضافة قاعدة ترحيل صحيحة.
18. هل استخدام RichText.Content إلزامي في دالة save؟
نعم، هو الأسلوب القياسي الوحيد الذي يضمن أن وسوم التنسيق مثل <strong> و <em> يتم تسلسلها ومطابقتها بنفس الطريقة في الواجهتين.
19. ما هو دور rawContent في كائن البلوك؟
هو النص الخام غير المعالج للـ HTML الذي قرأته النواة مباشرة من المقال المحفوظ في قاعدة البيانات قبل تطبيق أي تحويلات عليه.
20. ما هي الحكمة المعمارية وراء وجود نظام Validation الصارم في Gutenberg؟
حماية سلامة الموقع ومنع حقن كود خبيث بصمت والتأكد من أن ما يراه الكاتب في لوحة التحكم هو بالضبط ما تم ترميزه في الكود المصدر للموقع.
المراجع الرسمية والتوثيق المعتمد
- WordPress Developer Handbook: Block Validation and Deprecation Architecture
- Gutenberg Core Source Code: validation.js Implementation on GitHub
- WordPress Developer Guide: Validating Block Content
- WordPress Package Reference: Testing Gutenberg Blocks with Jest
- Make WordPress Core: Block Validation and Evolution Strategy


اترك تعليقاً
يجب أنت تكون مسجل الدخول لتضيف تعليقاً.