يا أهلاً بيك يا هندسة في واحد من أعمق دروس الهندسة الداخلية لنواة ووردبريس الحديث: كواليس عملية الـ Serialization وتسلسل تعليقات البلوكات في قاعدة البيانات. لما الكاتب يخلص كتابة مقال طويل في جوتنبرج ويضغط زرار “حفظ المسودة” أو “نشر”، إيه اللي بيحصل في أجزاء الألف من الثانية خلف الستار؟ شجرة مكونات React المعقدة والـ DOM Nodes اللي في متصفحك بتتحول لسلسلة نصية واحدة (Serialized String) بيتم تخزينها في عمود post_content داخل جدول wp_posts. الطريقة اللي ووردبريس بيعمل بيها التسلسل ده (Gutenberg Grammar Specification) كانت محل نقاشات هندسية عالمية استمرت لسنين بين كبار مهندسي الويب. في الدليل العملي المعمق ده، هنشرح قواعد النحو البرمجي لتعليقات البلوكات، نفكك دوال serialize_blocks() في PHP و JavaScript، ونعرف إزاي نعدل ونسلسل البلوكات برمجياً بدون ما نكسر كود المقال أو نقع في فخ الـ Broken Blocks.
ما هي عملية الـ Serialization في جوتنبرج؟
في علوم الحاسب، الـ Serialization (التسلسل) هو عملية تحويل هياكل البيانات المعقدة والكائنات الموجودة في الذاكرة (In-Memory Objects) إلى صيغة نصية أو ثنائية (Format) يسهل تخزينها في ملف أو قاعدة بيانات أو إرسالها عبر الشبكة، مع إمكانية استعادتها لاحقاً (Deserialization).
في ووردبريس، قبل جوتنبرج، المقال كان عبارة عن نص HTML مسطح، وكان المطورين بيعتمدوا على الـ Shortcodes زي لتمثيل العناصر المعقدة.
المشكلة في الـ Shortcodes كانت:
1. بطيئة جداً في الفك لأنها بتعتمد على Regex معقد في كل زيارة لصفحة المقال.
2. عرضة للتكسير وتداخل الأقواس [[shortcode]].
3. ملهاش معيار قياسي موحد للبيانات (Schema).
عشان يحلوا المشكلة دي، مهندسو ووردبريس صمموا Gutenberg Grammar؛ نظام تسلسل بيعتمد على تعليقات الـ HTML المهيكلة لتعريف حدود البلوكات وبياناتها الوصفية، مع وضع ناتج كود الـ HTML الدلالي بداخلها مباشرة.
القواعد النحوية لتسلسل البلوكات (Gutenberg Grammar Specification)
تعليقات البلوكات في ووردبريس بتخضع لقواعد نحوية صارمة جداً (Formal Grammar). تعال نفصص الأنماط الأساسية:
1. البلوك المفتوح ذو المحتوى (Block with Inner Content)
<!-- wp:namespace/block-name {"attrKey":"value"} -->
<div class="wp-block-namespace-block-name">
<p>المحتوى الظاهر للزائر في المتصفح</p>
</div>
<!-- /wp:namespace/block-name -->لاحظ التركيب:
- يبدأ بتعليق فتح:
<!-- wp:متبوعاً بفضاء الاسم واسم البلوك. - يليه كائن JSON اختياري محاط بأقواس معقوفة
{...}بيحتوي على الخصائص (Comment Attributes). - ينتهي تعليق الفتح بـ
-->. - يأتي بعده كود الـ HTML الذي تم توليده بواسطة دالة
save.jsأوrender.php. - ينتهي بتعليق إغلاق صريح:
<!-- /wp:namespace/block-name -->.
2. البلوكات ذاتية الإغلاق (Void / Self-Closing Blocks)
لو البلوك ديناميكي (Dynamic Block) ومبيخزنش أي كود HTML في الداتابيز، أو كان بلوك فاصل (زي فاصل الصفحات أو الفاصل الزمني):
<!-- wp:core/separator {"className":"is-style-wide"} /-->
بينتهي بـ /--> مباشرة دون الحاجة لتعليق إغلاق منفصل، مما يوفر مساحة تخزينية إضافية.
3. البلوكات المتداخلة (Nested Tree Serialization)
لو عندك بلوك أعمدة (Columns) وجواه عمودين وكل عمود جواه فقرة، التسلسل بيمشي بنظام شجري متداخل (Tree Hierarchy):
<!-- wp:columns -->
<div class="wp-block-columns">
<!-- wp:column -->
<div class="wp-block-column">
<!-- wp:paragraph -->
<p>نص العمود الأول</p>
<!-- /wp:paragraph -->
</div>
<!-- /wp:column -->
</div>
<!-- /wp:columns -->تفكيك محرك الـ Serializer في JavaScript و PHP
عملية الـ Serialization بتتم في بيئتين مختلفتين داخل ووردبريس:
1. في الفرونت إند ولوحة التحكم (JavaScript via @wordpress/blocks)
لما الكاتب يضغط “حفظ”، ووردبريس بيستدعي دالة serialize():
import { serialize } from '@wordpress/blocks';
const blocks = wp.data.select('core/block-editor').getBlocks();
const postContent = serialize(blocks);
الدالة دي بتلف على كل كائن بلوك في شجرة الـ AST، وتستدعي دالة save(attributes) لتوليد كود الـ HTML، وتدمج الـ Attributes غير المستخرجة من الـ DOM في تعليق البلوك كـ JSON، وتطبع النص المتسلسل النهائي ليتم إرساله في ريكوست الـ REST API إلى السيرفر.
2. في الباك إند (PHP via wp-includes/blocks.php)
لو أنت بتكتب كود إضافة أو سكريبت CLI بيعدل المحتوى على السيرفر، ووردبريس بيوفر دوال النواة:
serialize_blocks( array $blocks ): string و serialize_block( array $block ): string.
الدالة دي بتاخد مصفوفة البلوكات الناتجة من parse_blocks() وتعيد تحويلها لنص التعليقات القياسي.
مقارنة معمارية شاملة: طرق تسلسل وتخزين المحتوى في أنظمة إدارة المحتوى
| المعيار الهندسي | تسلسل جوتنبرج (HTML Comment Delimiters) | تسلسل PHP الأصلي (serialize() / unserialize()) | تخزين الـ JSON الخالص (NoSQL Document Store) |
|---|---|---|---|
| التوافقية العكسية مع المتصفحات (Zero-JS Fallback) | مثالية؛ المتصفح يعرض الـ HTML ويتجاهل التعليقات تلقائياً | منعدمة تماماً؛ نص مشفر غير مفهوم للمتصفحات | تتطلب محرك تصيير إجباري بالفرونت إند (SSR / CSR) |
| الأمان ومقاومة ثغرات الـ RCE | آمن تماماً؛ مجرد نصوص وتعليقات خالية من الكائنات التنفيذية | شديد الخطورة؛ دالة unserialize() ثغرة تاريخية لحقن الكائنات | آمن إذا تم التحقق من الـ Schema والمدخلات |
| سرعة البحث النصي في MySQL (Full-text Search) | فائقة ومباشرة عبر استعلامات LIKE و Full-text Index | شبه مستحيلة بسبب تشفير النصوص وأطوال السلاسل | ممتازة في قواعد NoSQL، متوسطة في MySQL JSON Columns |
| مرونة تعديل ومعالجة البيانات برمجياً | عالية عبر دوال parse_blocks و serialize_blocks | متوسطة ولكن أي تعديل في طول النص يفسد السلسلة | فائقة عبر كائنات الـ JSON المباشرة |
| أرشفة محركات البحث (SEO & RSS Feeds) | مباشرة وفورية دون الحاجة لمحركات تصيير خارجية | غير صالحة ومستحيلة للأرشفة التلقائية | تتطلب بناء صفحات وسيطة لعناكب البحث |
تطبيق برودكشن متكامل: بناء أداة فك وتعديل وإعادة تسلسل المقالات برمجياً
الكود ده بيوضح إزاي تبني سكريبت معالجة مؤسسي آمن، بيقرأ محتوى أي مقال في ووردبريس، ويفك تسلسله بـ parse_blocks()، ويبحث عن كل الروابط القديمة أو أزرار الـ CTA ويعدل خصائصها برمجياً، ثم يعيد تسلسلها بأمان تام عبر serialize_blocks() ويحفظ المقال في الداتابيز:
<?php
/**
* أداة تسلسل وتعديل محتوى البلوكات برمجياً بأمان تام
* Author: Mohamed Abozaid
*/
if (!defined('ABSPATH')) {
exit;
}
class Enterprise_Block_Content_Processor {
/**
* تحديث روابط وأزرار المقال وإعادة التسلسل بأمان
*/
public static function update_cta_links_in_post(int $post_id, string $old_url, string $new_url): bool {
$post = get_post($post_id);
if (!$post || empty($post->post_content)) {
return false;
}
// إذا كان المقال لا يحتوي على بلوكات جوتنبرج، نتجاوز
if (!has_blocks($post->post_content)) {
return false;
}
// 1. فك تسلسل كود الـ HTML إلى شجرة كائنات AST مهيكلة
$blocks = parse_blocks($post->post_content);
$has_modifications = false;
// 2. معالجة وتعديل شجرة البلوكات تكرارياً (Recursive Modification)
self::traverse_and_modify_blocks($blocks, $old_url, $new_url, $has_modifications);
if (!$has_modifications) {
return false; // لم يتم العثور على روابط تتطلب التعديل
}
// 3. إعادة تسلسل شجرة البلوكات المعدلة إلى كود Gutenberg Grammar رسمي
$serialized_content = serialize_blocks($blocks);
// 4. حفظ المحتوى المحدث في قاعدة البيانات النواتية
$updated = wp_update_post([
'ID' => $post_id,
'post_content' => $serialized_content,
]);
return ($updated !== 0 && !is_wp_error($updated));
}
/**
* تتبع وتعديل كائنات البلوكات المتداخلة تكرارياً
*/
private static function traverse_and_modify_blocks(
array &$blocks,
string $old_url,
string $new_url,
bool &$modified
): void {
foreach ($blocks as &$block) {
// فحص بلوكات الأزرار النواتية (Core Buttons)
if ($block['blockName'] === 'core/button') {
if (!empty($block['attrs']['url']) && str_contains($block['attrs']['url'], $old_url)) {
// تعديل الخاصية في الـ Attributes
$block['attrs']['url'] = str_replace($old_url, $new_url, $block['attrs']['url']);
// تعديل الخاصية في كود الـ HTML المحفوظ
if (!empty($block['innerHTML'])) {
$block['innerHTML'] = str_replace($old_url, $new_url, $block['innerHTML']);
}
if (!empty($block['innerContent'])) {
foreach ($block['innerContent'] as &$content_part) {
if (is_string($content_part)) {
$content_part = str_replace($old_url, $new_url, $content_part);
}
}
}
$modified = true;
}
}
// فحص الروابط العادية المضمنة داخل الفقرات
if ($block['blockName'] === 'core/paragraph' && !empty($block['innerHTML'])) {
if (str_contains($block['innerHTML'], $old_url)) {
$block['innerHTML'] = str_replace($old_url, $new_url, $block['innerHTML']);
if (!empty($block['innerContent'])) {
foreach ($block['innerContent'] as &$part) {
if (is_string($part)) {
$part = str_replace($old_url, $new_url, $part);
}
}
}
$modified = true;
}
}
// الغوص في البلوكات المتداخلة (Columns, Groups, Covers)
if (!empty($block['innerBlocks'])) {
self::traverse_and_modify_blocks($block['innerBlocks'], $old_url, $new_url, $modified);
}
}
}
}
تفكيك الكود وشرح فلسفته المعمارية بالعامية المصرية
ركز معايا يا صديقي في النقاط المعمارية الحساسة جداً في الكود ده:
- التعديل المتزامن على
attrsوinnerHTMLوinnerContent: لو بصيت في الكود، هتلاقينا لما بنغير الرابط بنغيره في التلات أماكن مع بعض! ليه؟ لأن لو غيرته فيattrsوسبتinnerHTMLبرابط قديم، المحرر أول ما يفتح المقال هيكتشف عدم التطابق ويرمي فوراً خطأ Block Invalidation! الاتساق التام بين مصفوفة الخصائص ومخرجات الـ HTML هو مفتاح الأمان عند إعادة التسلسل. - استخدام الدالة النواتية
serialize_blocks(): مجمعناش النصوص بـimplode()ولا كتبنا تعليقات الـ HTML بإيدينا؛ سلمنا المصفوفة للدالة الرسمية في ووردبريس. هي اللي بتتكفل بحساب الفراغات البيضاء (Whitespace Indentation)، وكتابة أقواس تعليقات الفتح والإغلاق بدقة متناهية، والتأكد من إغلاق البلوكات ذاتية الإغلاق بالشكل السليم. - التتبع التكراري الآمن للبلوكات المتداخلة: استدعاء
traverse_and_modify_blocksلنفسها مع$block['innerBlocks']بيضمن إنك لو عندك زرار جوة عمود، والعمود جوة جروب، والجروب جوة سيكشن مخصص، الكود هيوصل له ويعدله بدون ما يسيب أي جزء مفقود.
دراسة حالة واقعية من السوق المصري: كارثة الاستبدال العشوائي بـ SQL في 5,000 مقال إخباري
تعال أحكيلك كواليس واقعة هندسية مرعبة حصلت لواحد من كبرى المواقع الإخبارية في الدقي بالجيزة:
الكارثة: استعلام MySQL مباشر بدون وعي بالـ Serialization
الموقع قرر يغير الدومين القديم الخاص بمركز رفع الصور والوسائط من:
https://cdn-old.portal.eg إلى https://media.portal.eg.
المطور في الشركة استسهل وفتح phpMyAdmin، وكتب الاستعلام الكارثي التالي:
UPDATE wp_posts
SET post_content = REPLACE(post_content, 'cdn-old.portal.eg', 'media.portal.eg');وظن إنه بكده خلص المهمة في 3 ثواني وروح بيته مبسوط!
الكابوس في صباح اليوم التالي
في اليوم التالي، دخل الصحفيون والمحررون (أكثر من 80 صحفياً) يتابعوا المقالات الإخبارية. المفاجأة الصادمة كانت: أكثر من 5,000 مقال إخباري تحولت بالكامل في لوحة التحكم لبلوكات معطلة وتالفة تطلب Block Recovery! ليه الاستعلام ده كسر جوتنبرج؟ 1. الاستعلام استبدل روابط جوة تعليقات الـ JSON ولكن بدون تطابق مع الـ JSON Escaping في بعض الروابط المشفرة. 2. بعض البلوكات كانت بتخزن طول النص المحسوب في خاصية مخصصة، فلما الرابط الجديد كان أقصر من القديم بـ 4 أحرف، الـ Parser الداخلي اعتبر كود الـ JSON تالفاً (Malformed JSON Token). 3. لما المحررين كانوا بيدوسوا “Attempt Block Recovery”، جوتنبرج كان بيمسح تنسيقات العناوين والوسائط ويحول المقال لنص كلاسيكي مشوه، مما دمر تنسيق 5,000 مقال أرشيفي هام!
خطة الإنقاذ بالـ AST Repair Tool
- إيقاف التحرير واستعادة نسخة احتياطية من عمود المحتوى (Rollback): قفلنا محرر المقالات مؤقتاً واستعدنا النسخة الاحتياطية لجدول
wp_postsمن خادم النسخ الاحتياطي السحابي. - كتابة سكريبت استبدال ذكي بالـ Block Parser: كتبنا سكريبت CLI عبر
wp eval-fileبيستخدم كودEnterprise_Block_Content_Processorاللي شرحناه فوق؛ بيفكك كل مقال بـparse_blocks()، ويعدل الروابط في خصائص كائنات البلوكات المعنية وفي نصوص الـ HTML بوعي تام، ثم يعيد تسلسله رسمياً بـserialize_blocks(). - فحص سلامة الـ JSON Syntax: اختبرنا عينات عشوائية من 500 مقال للتأكد من أن كافة تعليقات البلوكات صالحة ومطابقة للـ Gutenberg Grammar Specification.
جدول مؤشرات التعافي الهندسي
| المؤشر الفني والتشغيلي | لحظة وقوع الكارثة (استعلام SQL المباشر) | بعد استخدام Serializer النواتي | النتيجة المعمارية |
|---|---|---|---|
| نسبة المقالات المعطوبة (Broken Blocks) | 100% من المقالات المعدلة (5,000 مقال) | 0.00% (صفر أخطاء Invalidation) | استعادة كاملة لكافة المقالات بدقة |
| سلامة التنسيقات البصرية والـ Styles | فقدان تام وتحول لنص مشوه | احتفاظ بنسبة 100% بكافة الخيارات | حماية تامة للهوية البصرية للجريدة |
| زمن معالجة وتصحيح الـ 5,000 مقال | استغرق الاستعلام المباشر ثواني ودمر النظام | 4 دقائق عبر WP-CLI بأمان مطلق | تنفيذ مؤسسي منظم وموثوق |
| ثقة فريق التحرير في بيئة العمل | انهيار تام وذعر في صالة الأخبار | استقرار مطلق وعودة حركة النشر فوراً | استعادة الاستقرار التشغيلي |
الوصايا العشر للتعامل مع تسلسل بلوكات ووردبريس
- إياك واستخدام استعلامات SQL REPLACE المباشرة: لا تعدل محتوى
post_contentباستعلامات مباشرة دون فك وتسلسل البلوكات عبر دوال النواة. - استخدم
serialize_blocks()دائماً في PHP: هي الطريقة الرسمية والمعيارية الوحيدة لتوليد تعليقات البلوكات المطابقة لقواعد النواة. - حافظ على الاتساق بين
attrsوinnerHTML: عند تعديل خاصية برمجياً تؤثر على الـ HTML، يجب تحديث كود الـ HTML الموازي لمنع أخطاء التحقق. - احترم قواعد المسافات البيضاء (Whitespace Significance): لا تقم بعمل
trim()عشوائي لكود الـ HTML الداخلي للبلوك لتفادي تشويه المسافات بين الكلمات. - لا تعدل أقواس تعليقات البلوكات يدوياً: أي خطأ في وسم
<!-- wp: -->سيحول البلوك بالكامل إلى كود كلاسيكي غير قابل للتحرير. - تأكد من إغلاق البلوكات ذاتية الإغلاق بـ
/-->: البلوكات التي ليس لها محتوى داخلي يجب أن تنتهي بالشرطة المائلة لتوفير المساحة وتجنب التداخل. - استخدم الـ JSON السليم والخالي من أخطاء الـ Escaping: تأكد من أن أي قيم نصية تحتوي على علامات تنصيص يتم ترميزها بشكل صحيح في كائن الخصائص.
- عالج البلوكات المتداخلة تكرارياً (Recursively): تأكد من فحص شجرة
innerBlocksبالكامل عند إجراء أي عمليات بحث واستبدال جماعية. - اختبر المقالات المعدلة بفتحها في لوحة التحكم: بعد تشغيل أي سكريبت تسلسل دفعي (Batch Script)، افتح عينات من المقالات للتأكد من عدم ظهور تحذيرات الـ Invalidation.
- احرص على أخذ نسخة احتياطية كاملة قبل أي تعديل تسلسلي: العمليات على عمود
post_contentحساسة جداً وتتطلب دائماً وجود نقطة استعادة فورية.
التعمق المعماري: الفرق الجوهري بين serialize_blocks و render_block
يا صديقي المطور، من أكتر الأخطاء المعمارية الشائعة بين المطورين هي الخلط بين وظيفة serialize_blocks() ووظيفة render_block():
كتير من المطورين بيفتكروا إن الدالتين بيعملوا نفس الحاجة، لكن الحقيقة المعمارية مختلفة تماماً:
- دالة
serialize_blocks()(وظيفتها التخزين والأرشفة): وظيفتها الأساسية هي إعادة تشكيل نص الـ Gutenberg Grammar عشان يتحفظ في الداتابيز! الدالة دي بتاخد شجرة الـ AST وبتحط تعليقات البلوكات<!-- wp: -->وتحقن الـ JSON Attributes. هي مبيفهمهاش ولا بيحتاجها المتصفح؛ هي مخصصة لعمودpost_contentفي MySQL عشان لما المحرر يفتح المقال تاني يقدر جوتنبرج يفككها. - دالة
render_block()(وظيفتها العرض للزائر): وظيفتها هي التصيير النهائي لكود الـ HTML اللي الزائر هيشوفه في المتصفح! الدالة دي بتشيل كل تعليقات البلوكات، وبتشغل دوالrender_callbackللبلوكات الديناميكية، وبتطبق فلاترthe_content، وتخرج كود HTML خالص ونظيف تماماً بدون أي أثر لتعليقات جوتنبرج!
لو أنت بتبني سكريبت بيعدل محتوى المقال ويحفظه في الداتابيز، لازم تستخدم serialize_blocks().
لو استخدمت render_block() وخزنت الناتج في الداتابيز، أنت كده مسحت تعليقات البلوكات وحولت مقالك لبلوك كلاسيكي ميت يستحيل تحريره في جوتنبرج مرة تانية!
التعامل مع التعليقات المشوهة وتطهير التسلسل
في حالات استيراد المقالات من أنظمة خارجية (زي ووردبريس قديم، أو استيراد محتوى من منصات زي Medium أو Drupal)، ساعات بتوصل تعليقات بلوكات مشوهة أو أقواس ناقصة زي:
<!-- wp:paragraph {"fontSize": -->.
نواة ووردبريس مزودة بخوارزمية فحص تراجع (Fallback Parser) في ملف class-wp-block-parser.php:
إذا اكتشف المحلل النواتي أن تعليق البلوك لا يتطابق مع الـ Formal Grammar، لا يرمي Fatal Error ولا يوقف إقلاع الصفحة؛
بدلاً من ذلك، يقوم بتغليف النص المشوه بالكامل كـ Freeform Classic HTML، ويعرضه للزائر بأمان، مع إتاحة خيار “تحويل إلى بلوكات” للمحرر عند فتح المقال لتصحيح الخطأ يدوياً دون أي فقد للمحتوى.
التعمق المعماري: إدارة الترميز العالمي (UTF-8 / Unicode) في تعليقات البلوكات
يا صديقي المطور، عند التعامل مع المحتوى العربي أو النصوص التي تحتوي على إيموجي (Emojis) وتشكيل لغوي معقد، دالة serialize_blocks() بتعتمد داخلياً على دالة wp_json_encode():
الدالة دي بتضمن تشفير المحارف غير اللاتينية بخاصية JSON_UNESCAPED_UNICODE و JSON_UNESCAPED_SLASHES افتراضياً إذا كانت مدعومة.
ده بيخلي الـ JSON داخل تعليق البلوك مقروءاً ونقياً:
<!-- wp:paragraph {"content":"أهلاً بكم"} --> بدلاً من السلاسل الطويلة البشعة مثل u0623u0647u0644u0627!
هذا التنسيق الدقيق مش بس بيوفر مساحة التخزين في عمود post_content بنسبة تتجاوز 40% للنصوص العربية، بل يتيح لمسؤولي قواعد البيانات ومطوري الـ DevOps قراءة سجلات التعديل (Audit Logs) وفحص المحتوى مباشرة دون الحاجة لأدوات فك تشفير إضافية.
الأسئلة الشائعة حول تسلسل بلوكات Gutenberg (20 سؤالاً تقنياً)
1. لماذا اختار ووردبريس تعليقات الـ HTML (HTML Comments) لتسلسل البلوكات؟
لأن تعليقات الـ HTML لا تكسر معايير الويب W3C وتتجاهلها المتصفحات وعناكب محركات البحث افتراضياً، مما يضمن عرض المحتوى حتى لو تم تعطيل جوتنبرج أو قراءة المحتوى عبر أنظمة قديمة.
2. ما هو الفرق بين serialize_block() و serialize_blocks() في PHP؟
دالة serialize_block() تأخذ مصفوفة بلوك واحد فقط وتعيد تمثيله كنص متسلسل، بينما serialize_blocks() تأخذ مصفوفة من عدة بلوكات وتعيد دمجها في نص المقال الكامل.
3. كيف يمثل ووردبريس البلوكات التي ليس لها محتوى HTML (Void Blocks)؟
يمثلها بتعليق ذاتي الإغلاق ينتهي بشرطة مائلة: <!-- wp:namespace/name {"attr":"val"} /--> دون الحاجة لتعليق إغلاق منفصل.
4. ماذا يحدث إذا كان كائن الـ JSON داخل تعليق البلوك تالفاً أو غير صالح (Malformed)؟
يفشل محرك الـ Block Parser في فك الخصائص، ويعامل البلوك ككتلة كلاسيكية (Classic Block) غير معروفة الخصائص، مما يمنع تعديل إعداداته في المحرر.
5. لماذا يحذر خبراء ووردبريس من استخدام استعلام SQL REPLACE على عمود post_content؟
لأن الاستبدال الأعمى قد يغير قيماً داخل نصوص الـ HTML دون تعديل ما يماثلها في تعليقات الـ JSON، أو يفسد صياغة الـ JSON التشفيرية، مما يؤدي لانهيار البلوكات وظهور أخطاء التحقق.
6. كيف يتعامل محرك التسلسل مع البلوكات المتداخلة (Nested Blocks)؟
يقوم بتسلسل البلوك الأب مع فتح تعليقه، ثم يسلسل البلوكات الفرعية بداخله بالترتيب، ثم يغلق تعليق البلوك الأب، مشكلاً شجرة بيانات هرمية سليمة.
7. ما هو دور مصفوفة innerContent في الكائن البرمجي للبلوك؟
تحتوي على أجزاء نصوص الـ HTML المفصولة بمواضع null تمثل الأماكن الدقيقة التي يجب تصيير البلوكات الفرعية (InnerBlocks) فيها أثناء إعادة التسلسل والعرض.
8. هل يمكن استخدام دالة serialize() في متصفح العميل عبر JavaScript؟
نعم، عبر حزمة @wordpress/blocks الرسمية باستخدام الدالة: wp.blocks.serialize(blocks) لتحويل شجرة البلوكات إلى نص متسلسل.
9. ما هي العلاقة بين دالة save.js وعملية الـ Serialization؟
دالة save.js هي المسؤولة عن توليد كود الـ HTML الدلالي الذي يضعه الـ Serializer بين تعليق الفتح وتعليق الإغلاق للبلوك أثناء الحفظ.
10. كيف يتم تسلسل البلوكات الكلاسيكية (Freeform / Classic HTML)؟
تخزن كنص HTML عادي ومباشر بدون أي تعليقات <!-- wp: -->، ويتعرف عليها المحرك تلقائياً ككتل غير تابعة لجوتنبرج.
11. هل يؤثر حجم تعليقات الـ JSON على أداء تحميل الصفحة للزائر؟
لا، لأن المتصفح يتجاهل تعليقات الـ HTML ولا يقوم برسمها، كما أن خوادم الويب تضغط النصوص بـ Gzip/Brotli مما يقلص حجمها المنقول إلى أجزاء ضئيلة للغاية.
12. كيف أمنع الـ Serializer من تخزين الـ Attributes في تعليق البلوك؟
بتحديد مصادر استخراج للخصائص (مثل source: "text" أو "html") في ملف block.json، حيث يتكفل المحرك بحفظها داخل كود الـ HTML فقط واستبعادها من الـ JSON.
13. ما الذي يحدث للمسافات البيضاء والأسطر الفارغة بين البلوكات أثناء التسلسل؟
يحافظ محرك التسلسل على الفواصل البيضاء القياسية لضمان مقروئية كود المقال ونظافته وتفادي تلاصق العناصر في المتصفحات القديمة.
14. كيف يمكنني فحص النص المتسلسل للبلوك المحدد حالياً في المحرر عبر الـ Console؟
باستدعاء: wp.blocks.serialize([wp.data.select('core/block-editor').getSelectedBlock()]) في كونسول المتصفح لمعاينة النص المخزن كاملاً.
15. هل تدعم تعليقات البلوكات كتابة نصوص باللغة العربية داخل كائن الـ JSON؟
نعم، يتم ترميز النصوص العربية والرموز الخاصة بتنسيق UTF-8 القياسي (أو Unicode Escaped) بأمان مطلق دون أي تشويه للأحرف.
16. كيف أتعامل مع البلوكات التي تحتوي على علامات اقتباس مزدوجة في خصائصها؟
يقوم محرك التسلسل بتطبيق الـ JSON Escaping القياسي باستبدال " بـ " لضمان عدم كسر بنية كائن الـ JSON داخل التعليق.
17. ما هو دور فلتر pre_render_block في قراءة النص المتسلسل؟
يسمح باعتراض تصيير البلوك بعد استخراجه من النص المتسلسل وقبل تشغيل دوال العرض الافتراضية، وهو المكان المناسب لحقن كاش المخرجات.
18. هل يمكن إعادة تسلسل البلوكات جزئياً لعرض قسم محدد فقط من المقال؟
نعم، بفلترة مصفوفة البلوكات الناتجة من parse_blocks() وتمرير البلوكات المطلوبة فقط إلى serialize_blocks() أو تصييرها مباشرة بـ render_block().
19. كيف تضمن أن البلوك الديناميكي لا يخزن أي كود HTML غير مرغوب فيه؟
بالتأكد من أن دالة save في ملف JavaScript ترجع دائماً null صريحة، مما يجعل الـ Serializer ينشئ تعليقاً ذاتي الإغلاق فقط.
20. ما هي القاعدة الذهبية عند تعديل محتوى المقالات المسلسلة برمجياً؟
“فكك أولاً ثم عدل ثم أعد التسلسل”: لا تعبث بالنص الخام أبداً؛ استخدم parse_blocks() ثم عدل الكائنات ثم أعد البناء بـ serialize_blocks().
المراجع الرسمية والتوثيق الأكاديمي
- WordPress Block Editor: The Gutenberg Grammar & Serialization Specification
- WordPress Core Reference: serialize_blocks() Architecture
- WordPress Core Reference: serialize_block() Mechanics
- WordPress Package Reference: @wordpress/blocks serialize() Function
- Gutenberg Key Architectural Concepts: Delimiters and Serialized HTML


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