محاكاة قصور في رؤية الألوان في "عارض الألوان"

ماتياس بيننز
ماتياس بيننز

توضّح هذه المقالة سبب وكيفية تنفيذ محاكاة نقص رؤية الألوان في "أدوات مطوري البرامج" و"عارِض الوميض" وكيفية تنفيذ ذلك.

الخلفية: تباين ألوان سيّئ

النص المنخفض التباين هو أكثر مشاكل تسهيل الاستخدام التي يمكن رصدها تلقائيًا على الويب.

قائمة بمشاكل إمكانية الوصول الشائعة على الويب تُعدّ النصوص المنخفضة التباين المشكلة الأكثر شيوعًا إلى حدّ كبير.

وفقًا لتحليل إمكانية الوصول من WebAIM لأفضل مليون موقع إلكتروني، وجدنا أنّ أكثر من 86% من الصفحات الرئيسية تتضمّن تباينًا منخفضًا. في المتوسّط، تحتوي كل صفحة رئيسية على 36 مثيلاً مختلفًا من النص المنخفض التباين.

استخدام أدوات مطوّري البرامج للعثور على مشاكل التباين وفهمها وحلّها

يمكن أن تساعد أدوات مطوري البرامج في Chrome المطورين والمصممين على تحسين التباين واختيار أنظمة ألوان أكثر سهولة لتطبيقات الويب:

أضفنا مؤخرًا أداة جديدة إلى هذه القائمة، وهي مختلفة بعض الشيء عن الأدوات الأخرى. تركز الأدوات المذكورة أعلاه بشكل أساسي على عرض معلومات نسبة التباين وتمنحك خيارات لإصلاحها. أدركنا أنّ "أدوات مطوري البرامج" كانت لا تزال تفتقد وسيلة لمطوّري البرامج للحصول على understanding أعمق لهذه المساحة المتعلقة بالمشاكل. ولحلّ هذه المشكلة، نفّذنا محاكاة قصور في الرؤية في علامة التبويب "العرض" ضمن "أدوات مطوري البرامج".

في Puppeteer، تتيح لك واجهة برمجة التطبيقات page.emulateVisionDeficiency(type) الجديدة تفعيل عمليات المحاكاة هذه آليًا.

قصور في رؤية الألوان

يعاني 1 تقريبًا من كل 20 شخصًا من قصور في رؤية الألوان (يُعرف أيضًا باسم المصطلح الأقل دقة "عمى الألوان"). تجعل حالات العجز هذه من الصعب التمييز بين الألوان المختلفة، ما يمكن أن يؤدي إلى زيادة مستوى التباين.

صورة ملونة لأقلام التلوين الذائبة، مع عدم محاكاة قصور في رؤية الألوان
صورة ملوّنة لأقلام التلوين الذائبة، مع عدم محاكاة قصور في رؤية الألوان.
ALT_TEXT_HERE
تأثير محاكاة عمى الألوان على صورة ملونة لأقلام التلوين الذائبة.
تأثير محاكاة عمى اللون الأخضر على صورة ملونة لأقلام التلوين الذائبة.
تأثير محاكاة عمى اللون الأخضر على الصورة الغنية بالألوان لأقلام التلوين الذائبة.
تأثير محاكاة عمى اللون الأحمر على صورة ملونة لأقلام التلوين الذائبة.
تأثير محاكاة عمى اللون الأحمر على الصورة الملونة لأقلام التلوين الذائبة.
تأثير محاكاة عمى اللون الأزرق على صورة ملونة لأقلام التلوين الذائبة.
تأثير محاكاة عمى اللون الأزرق على الصورة الغنية بالألوان لأقلام التلوين الذائبة.

وكمطوّر برامج لديه رؤية منتظمة، قد ترى أنّ أدوات مطوّري البرامج تعرض نسبة تباين سيئة لأزواج الألوان التي تبدو مناسبة بصريًا لك. يحدث هذا لأن معادلات نسبة التباين تأخذ في الاعتبار أوجه القصور في رؤية الألوان هذه! قد يظل بإمكانك قراءة النص المنخفض التباين في بعض الحالات، ولكن لا يملك الأشخاص الذين يعانون من إعاقات بصرية هذا الامتياز.

من خلال السماح للمصممين والمطوّرين بمحاكاة تأثير أوجه القصور في الرؤية هذه على تطبيقات الويب الخاصة بهم، نسعى إلى تقديم الجزء المفقود: لن يقتصر دور أدوات مطوّري البرامج على مساعدتك في العثور وحلّ مشاكل التباين، بل أصبح بإمكانك الآن أيضًا فهمها.

محاكاة قصور في رؤية الألوان باستخدام HTML وCSS وSVG وC++

قبل أن نتعمق في الأمر حول طريقة عرض Blink Renderer لهذه الميزة، من المفيد فهم كيفية تنفيذ وظائف مكافئة باستخدام تكنولوجيا الويب.

يمكنك التفكير في كل من محاكاة نقص رؤية الألوان هذه كتراكب يغطي الصفحة بأكملها. والنظام الأساسي للويب به طريقة للقيام بذلك: فلاتر CSS! باستخدام سمة filter في CSS، يمكنك استخدام بعض وظائف الفلاتر المحدّدة مسبقًا، مثل blur وcontrast وgrayscale وhue-rotate وغيرها الكثير. لمزيد من التحكّم، تقبل السمة filter أيضًا عنوان URL يمكن أن يشير إلى تعريف مخصّص لفلتر SVG:

<style>
  :root {
    filter: url(#deuteranopia);
  }
</style>
<svg>
  <filter id="deuteranopia">
    <feColorMatrix values="0.367  0.861 -0.228  0.000  0.000
                           0.280  0.673  0.047  0.000  0.000
                          -0.012  0.043  0.969  0.000  0.000
                           0.000  0.000  0.000  1.000  0.000">
    </feColorMatrix>
  </filter>
</svg>

يستخدم المثال أعلاه تعريف فلتر مخصص استنادًا إلى مصفوفة ألوان. يتم ضرب قيمة اللون [Red, Green, Blue, Alpha] لكل بكسل في المصفوفة لإنشاء لون [R′, G′, B′, A′] جديد.

يحتوي كل صف في المصفوفة على 5 قيم: مضاعف (من اليسار إلى اليمين) R وG وB وA، فضلاً عن قيمة خامسة لقيمة متغيّرات ثابتة. يوجد 4 صفوف: يُستخدم الصف الأول من المصفوفة لحساب قيمة Red الجديدة، والصف الثاني Green، والصف الثالث Blue، والصف الأخير Alpha.

قد تتساءل من أين تأتي الأرقام الدقيقة في المثال الذي ذكرناه. ما الذي يجعل مصفوفة الألوان هذه تقريبية جيدة لعمى اللون الأخضر؟ والإجابة هي: العلم! تستند القيم إلى نموذج دقيق من الناحية الفيزيولوجية لمحاكاة نقص رؤية الألوان، أنشأه "ماشادو" و"أوليفيرا" و"فرنانديز".

على أي حال، لدينا فلتر SVG هذا، ويمكننا الآن تطبيقه على العناصر العشوائية في الصفحة باستخدام CSS. يمكننا تكرار نفس النمط مع قصور الرؤية الأخرى. وهذا عرض توضيحي لما يبدو عليه الأمر:

إذا أردنا ذلك، يمكننا إنشاء ميزة "أدوات مطوري البرامج" على النحو التالي: عندما يحاكي المستخدم نقصًا في الرؤية في واجهة مستخدم أدوات مطوّري البرامج، نُدخل فلتر الرسومات الموجّهة التي يمكن تغيير حجمها (SVG) في المستند الذي تم فحصه، ثم نطبّق نمط الفلتر على العنصر الجذر. ومع ذلك، هناك العديد من المشاكل في هذا المنهج:

  • قد تحتوي الصفحة على فلتر على العنصر الجذر، وقد يلغي هذا الرمز البرمجي الذي نستخدمه.
  • قد تتضمّن الصفحة حاليًا عنصرًا يتضمّن id="deuteranopia" يتعارض مع تعريف الفلتر.
  • قد تعتمد الصفحة على بنية DOM معيّنة، وقد يؤدي إدراج <svg> في DOM إلى انتهاك هذه الافتراضات.

بغض النظر عن الحالات الحدّية، تكمن المشكلة الرئيسية في هذا المنهج في أنّنا سنجري تغييرات يمكن رصدها آليًا على الصفحة. إذا فحص أحد مستخدمي "أدوات مطوري البرامج" نموذج كائن المستند (DOM)، قد يظهر فجأة عنصر <svg> لم يضيفه مطلقًا أو رمز CSS filter لم يكتبه من قبل. سيكون ذلك محيرًا! لتنفيذ هذه الوظيفة في "أدوات مطوري البرامج"، نحتاج إلى حلّ لا يتضمّن هذه العيوب.

لنرَ كيف يمكننا جعل هذا الأمر أقل تداخلاً. هناك جزآن في هذا الحلّ يجب إخفاؤهما: 1) نمط CSS الذي يتضمّن السمة filter، و2) تعريف فلتر SVG الذي يشكّل حاليًا جزءًا من نموذج العناصر في المستند (DOM).

<!-- Part 1: the CSS style with the filter property -->
<style>
  :root {
    filter: url(#deuteranopia);
  }
</style>
<!-- Part 2: the SVG filter definition -->
<svg>
  <filter id="deuteranopia">
    <feColorMatrix values="0.367  0.861 -0.228  0.000  0.000
                           0.280  0.673  0.047  0.000  0.000
                          -0.012  0.043  0.969  0.000  0.000
                           0.000  0.000  0.000  1.000  0.000">
    </feColorMatrix>
  </filter>
</svg>

تجنُّب تبعية SVG داخل المستند

فلنبدأ بالجزء الثاني: كيف يمكننا تجنب إضافة SVG إلى DOM؟ والفكرة الأولى هي نقله إلى ملف SVG منفصل. يمكننا نسخ <svg>…</svg> من محتوى HTML أعلاه وحفظه باسم filter.svg، ولكن علينا إجراء بعض التغييرات أولاً. يتبع تنسيق SVG المضمّن في HTML قواعد تحليل HTML. وهذا يعني أنه يمكنك تجنب أمور مثل حذف علامات الاقتباس حول قيم السمات في بعض الحالات. ومع ذلك، من المفترض أن يكون تنسيق SVG في الملفات المنفصلة ملف XML صالحًا، وتحليل XML أكثر صرامة من HTML. إليك مقتطف SVG-in-HTML مرة أخرى:

<svg>
  <filter id="deuteranopia">
    <feColorMatrix values="0.367  0.861 -0.228  0.000  0.000
                           0.280  0.673  0.047  0.000  0.000
                          -0.012  0.043  0.969  0.000  0.000
                           0.000  0.000  0.000  1.000  0.000">
    </feColorMatrix>
  </filter>
</svg>

لجعل صورة SVG المستقلة هذه صالحة (وبالتالي XML)، علينا إجراء بعض التغييرات. هل يمكنك تخمين أيهما؟

<svg xmlns="http://www.w3.org/2000/svg">
 
<filter id="deuteranopia">
   
<feColorMatrix values="0.367  0.861 -0.228  0.000  0.000
                           0.280  0.673  0.047  0.000  0.000
                          -0.012  0.043  0.969  0.000  0.000
                           0.000  0.000  0.000  1.000  0.000"
/>
 
</filter>
</svg>

التغيير الأول هو إعلان مساحة الاسم XML في الأعلى. الإضافة الثانية هي ما يُعرَف باسم "solidus"، وهي الشرطة المائلة التي تشير إلى أنّ العلامة <feColorMatrix> تفتح العنصر وتغلقه. وهذا التغيير ليس ضروريًا في الواقع (ما زال بإمكاننا الالتزام بعلامة الإغلاق </feColorMatrix> الصريحة بدلاً من ذلك)، ولكن بما أنّ كلاً من XML وSVG-in-HTML يتيح استخدام اختصار /> هذا، قد نستخدمه أيضًا.

من خلال هذه التغييرات، يمكننا في النهاية حفظ هذا الملف كملف SVG صالح والإشارة إليه من قيمة السمة filter في CSS في مستند HTML:

<style>
  :root {
    filter: url(filters.svg#deuteranopia);
  }
</style>

لم يعد علينا إدخال SVG في المستند. وهذا أفضل بكثير. لكن... نعتمد الآن على ملف منفصل. لا تزال هذه التبعية. هل يمكننا التخلص منها بطريقة ما؟

كما اتضح، لا نحتاج في الواقع إلى ملف. يمكننا ترميز الملف بأكمله داخل عنوان URL باستخدام عنوان URL للبيانات. ولتحقيق ذلك، نأخذ حرفيًا محتوى ملف SVG الذي كان لدينا من قبل، ونضيف البادئة data: ونضبط نوع MIME المناسب، وحصلنا على عنوان URL صالح للبيانات يمثّل ملف SVG نفسه:

data:image/svg+xml,
  <svg xmlns="http://www.w3.org/2000/svg">
    <filter id="deuteranopia">
      <feColorMatrix values="0.367  0.861 -0.228  0.000  0.000
                             0.280  0.673  0.047  0.000  0.000
                            -0.012  0.043  0.969  0.000  0.000
                             0.000  0.000  0.000  1.000  0.000" />
    </filter>
  </svg>

تكمن الفائدة الآن في أننا لم نعد بحاجة إلى تخزين الملف في أي مكان أو تحميله من القرص أو عبر الشبكة لمجرد استخدامه في مستند HTML. لذا بدلاً من الإشارة إلى اسم الملف كما فعلنا من قبل، يمكننا الآن الإشارة إلى عنوان URL للبيانات:

<style>
  :root {
    filter: url('data:image/svg+xml,\
      <svg xmlns="http://www.w3.org/2000/svg">\
        <filter id="deuteranopia">\
          <feColorMatrix values="0.367  0.861 -0.228  0.000  0.000\
                                 0.280  0.673  0.047  0.000  0.000\
                                -0.012  0.043  0.969  0.000  0.000\
                                 0.000  0.000  0.000  1.000  0.000" />\
        </filter>\
      </svg>#deuteranopia');
  }
</style>

في نهاية عنوان URL، ما زلنا نحدِّد رقم تعريف الفلتر الذي نريد استخدامه، تمامًا كما كان الحال من قبل. وتجدُر الإشارة إلى أنّه ما مِن حاجة إلى ترميز مستند SVG في عنوان URL باستخدام Base64، لأنّ ذلك سيؤثّر فقط في إمكانية القراءة ويزيد من حجم الملف. أضفنا شرطات مائلة للخلف في نهاية كل سطر لضمان عدم إنهاء أحرف السطر الجديد في عنوان URL للبيانات لسلسلة CSS الحرفية.

تحدَّثنا حتى الآن عن كيفية محاكاة قصور في الرؤية باستخدام تكنولوجيا الويب. ما يثير الاهتمام، أنّ عملية التنفيذ النهائية في العارض الوامضات متشابهة إلى حدّ كبير. إليك أداة مساعدة C++ أضفناها لإنشاء عنوان URL للبيانات باستخدام تعريف فلتر معيّن، استنادًا إلى الأسلوب نفسه:

AtomicString CreateFilterDataUrl(const char* piece) {
  AtomicString url =
      "data:image/svg+xml,"
        "<svg xmlns=\"http://www.w3.org/2000/svg\">"
          "<filter id=\"f\">" +
            StringView(piece) +
          "</filter>"
        "</svg>"
      "#f";
  return url;
}

في ما يلي طريقة استخدامه من أجل إنشاء جميع الفلاتر التي نحتاجها:

AtomicString CreateVisionDeficiencyFilterUrl(VisionDeficiency vision_deficiency) {
  switch (vision_deficiency) {
    case VisionDeficiency::kAchromatopsia:
      return CreateFilterDataUrl("…");
    case VisionDeficiency::kBlurredVision:
      return CreateFilterDataUrl("<feGaussianBlur stdDeviation=\"2\"/>");
    case VisionDeficiency::kDeuteranopia:
      return CreateFilterDataUrl(
          "<feColorMatrix values=\""
          " 0.367  0.861 -0.228  0.000  0.000 "
          " 0.280  0.673  0.047  0.000  0.000 "
          "-0.012  0.043  0.969  0.000  0.000 "
          " 0.000  0.000  0.000  1.000  0.000 "
          "\"/>");
    case VisionDeficiency::kProtanopia:
      return CreateFilterDataUrl("…");
    case VisionDeficiency::kTritanopia:
      return CreateFilterDataUrl("…");
    case VisionDeficiency::kNoVisionDeficiency:
      NOTREACHED();
      return "";
  }
}

تجدر الإشارة إلى أنّ هذا الأسلوب يتيح لنا الاستفادة من المزايا الكاملة لفلاتر الرسومات الموجّهة التي يمكن تغيير حجمها (SVG) بدون الحاجة إلى إعادة تنفيذ أي تنفيذ أو إعادة تصميم أي عجلات. نعمل حاليًا على تنفيذ ميزة Blink Renderer، ولكننا نفعل ذلك من خلال الاستفادة من Web Platform.

لقد تعرّفنا على كيفية إنشاء فلاتر SVG وتحويلها إلى عناوين URL للبيانات يمكننا استخدامها في قيمة السمة filter في CSS. هل يمكنك التفكير في أي مشكلة في هذه التقنية؟ لقد تبين أنّه لا يمكننا الاعتماد في الواقع على عنوان URL للبيانات الذي يتم تحميله في جميع الحالات، لأنّ الصفحة المستهدفة قد تحتوي على Content-Security-Policy تحظر عناوين URL للبيانات. إنّ عملية التنفيذ النهائية على مستوى Blink تتطلّب عناية خاصة بتجاوز سياسة CSP لعناوين URL الخاصة بالبيانات "الداخلية" أثناء التحميل.

بغض النظر عن الحالات الحدّية، لقد حقّقنا بعض التقدّم الجيد. بما أنّنا لم نعُد نعتمد على استخدام السمة <svg> المضمَّنة في المستند نفسه، قلّلنا الحلّ الذي نقدّمه إلى تعريف واحد فقط لخاصية CSS filter المستقلة. رائع! والآن لنتخلص من ذلك أيضًا.

تجنب تبعية CSS داخل المستند

للتلخيص، هذا هو ما وصلنا إليه حتى الآن:

<style>
  :root {
    filter: url('data:…');
  }
</style>

ما زلنا نعتمد على سمة filter في CSS، والتي قد تحلّ محلّ filter في المستند الفعلي وتعطّل بعض العناصر. وسيظهر أيضًا عند فحص الأنماط المحسوبة في أدوات مطوّري البرامج، ما قد يكون محيرًا. كيف نتفادى هذه المشكلات؟ نحتاج إلى إيجاد طريقة لإضافة فلتر إلى المستند بدون أن يتمكّن المطوّرون من ملاحظته آليًا.

من بين الأفكار التي تم طرحها هي إنشاء موقع إلكتروني جديد ضمن متصفّح Chrome، والذي يتصرف مثل filter، ولكن يحمل اسمًا مختلفًا، مثل --internal-devtools-filter. ويمكننا بعد ذلك إضافة منطق خاص لضمان عدم ظهور هذه السمة مطلقًا في "أدوات مطوري البرامج" أو في الأنماط المحسوبة في نموذج العناصر في المستند (DOM). يمكننا حتى التأكد من أنه يعمل فقط على العنصر الوحيد الذي نحتاج إليها من أجله: العنصر الجذر. مع ذلك، لن يكون هذا الحل مثاليًا، لأنّنا سنكرر الوظائف المتوفّرة حاليًا في filter، وحتى إذا بذلنا جهدًا كبيرًا لإخفاء هذا الموقع الإلكتروني غير العادي، سيظل بإمكان مطوّري الويب اكتشافه والبدء في استخدامه، ما قد يكون سيئًا للمنصة الإلكترونية على الويب. ونحتاج إلى طريقة أخرى لتطبيق نمط CSS بدون ملاحظته في DOM. هل يمكنني الحصول على أفكار بهذا الخصوص؟

تشتمل مواصفات CSS على قسم يتناول نموذج التنسيق المرئي الذي تستخدمه، وأحد المفاهيم الرئيسية هناك هو إطار العرض. هذا هو العرض المرئي الذي يقوم المستخدمون من خلاله بالرجوع إلى صفحة الويب. والمفهوم الوثيق الصلة هو الحرف الأولي الذي يحتوي على كتلة، وهو يشبه نوعًا ما إطار العرض <div> القابل للنمط الذي لا يتوفّر إلا على مستوى المواصفات. تشير المواصفات إلى مفهوم "إطار العرض" هذا في كل مكان. على سبيل المثال، هل تعرف كيف يعرض المتصفِّح أشرطة التمرير عندما لا يناسب المحتوى المحتوى؟ يتم تحديد كل ذلك في مواصفات CSS بناءً على "إطار العرض" هذا.

يتوفّر viewport هذا أيضًا ضمن عارض Blink، بالإضافة إلى تفاصيل التنفيذ. إليك الرمز الذي يطبّق أنماط إطار العرض التلقائية وفقًا للمواصفات:

scoped_refptr<ComputedStyle> StyleResolver::StyleForViewport() {
  scoped_refptr<ComputedStyle> viewport_style =
      InitialStyleForElement(GetDocument());
  viewport_style->SetZIndex(0);
  viewport_style->SetIsStackingContextWithoutContainment(true);
  viewport_style->SetDisplay(EDisplay::kBlock);
  viewport_style->SetPosition(EPosition::kAbsolute);
  viewport_style->SetOverflowX(EOverflow::kAuto);
  viewport_style->SetOverflowY(EOverflow::kAuto);
  // …
  return viewport_style;
}

لست بحاجة إلى فهم لغة C++ أو تعقيدات محرك Blink لتعرف أن هذا الرمز يتعامل مع إطار العرض (أو بشكل أكثر دقة: أول علامة تحتوي على مجموعة) z-index وdisplay وposition وoverflow لإطار العرض. هذه هي كل المفاهيم التي قد تكون على دراية بها من CSS. هناك بعض الطريقة السحريّة الأخرى المرتبطة بسياقات التجميع، والتي لا يتم ترجمتها مباشرةً إلى خاصية CSS، ولكن يمكنك بشكل عام اعتبار عنصر viewport هذا كشيء يمكن تصميمه باستخدام CSS من داخل Blink، تمامًا مثل عنصر DOM، إلا أنه ليس جزءًا من DOM.

يمنحنا ذلك ما نريده بالضبط. يمكننا تطبيق أنماط filter على الكائن viewport، ما يؤثر بشكل مرئي في العرض، بدون أن يتداخل مع أنماط الصفحة القابلة للملاحظة أو نموذج العناصر في المستند (DOM) بأي شكل من الأشكال.

الخلاصة

ولتلخيص رحلتنا الصغيرة هنا، بدأنا ببناء نموذج أولي باستخدام تقنية الويب بدلاً من C++ ، ثم بدأنا العمل على نقل أجزاء منه إلى Blink Renderer.

  • لقد جعلنا نموذجنا الأوّلي أكثر إفادة من خلال تضمين عناوين URL للبيانات.
  • بعد ذلك، جعلنا عناوين URL للبيانات الداخلية هذه متوافقة مع سياسة أمان المحتوى (CSP)، من خلال وضع حالة خاصة لتحميلها.
  • لقد جعلنا عملية تنفيذ نموذج العناصر في المستند (DOM) غير مرتبطة بنموذج "كائن المستند" (DOM) ولا يمكن رصده آليًا من خلال نقل الأنماط إلى viewport Blink-internal.

ما يميّز هذا التنفيذ هو أن النموذج الأولي بتنسيق HTML/CSS/SVG انتهى بالتأثير على التصميم الفني النهائي. اكتشفنا طريقة لاستخدام النظام الأساسي للويب، حتى داخل عارض Blink.

لمزيد من المعلومات الأساسية، يمكنك الاطّلاع على اقتراح التصميم أو خطأ التتبُّع في Chromium الذي يشير إلى جميع رموز التصحيح ذات الصلة.

تنزيل قنوات المعاينة

يمكنك استخدام إصدار Canary أو إصدار مطوّري البرامج أو الإصدار التجريبي من Chrome ليكون متصفِّح التطوير التلقائي. تتيح لك قنوات المعاينة هذه الوصول إلى أحدث ميزات أدوات مطوّري البرامج، واختبار واجهات برمجة التطبيقات المتطورة للأنظمة الأساسية للويب، والعثور على المشاكل في موقعك الإلكتروني قبل أن يتمكّن المستخدمون من ذلك.

التواصل مع فريق "أدوات مطوري البرامج في Chrome"

يمكنك استخدام الخيارات التالية لمناقشة الميزات والتغييرات الجديدة في المشاركة، أو أي موضوع آخر مرتبط بـ "أدوات مطوري البرامج".

  • يمكنك إرسال اقتراحات أو ملاحظات إلينا عبر crbug.com.
  • يمكنك الإبلاغ عن مشكلة في "أدوات مطوري البرامج" باستخدام خيارات إضافية   المزيد > مساعدة > الإبلاغ عن مشاكل في "أدوات مطوري البرامج" في "أدوات مطوري البرامج".
  • نشر تغريدة على @ChromeDevTools
  • يمكنك إضافة تعليقات على الميزات الجديدة في الفيديوهات على YouTube في "أدوات مطوري البرامج" أو الفيديوهات على YouTube التي تتضمّن نصائح حول أدوات مطوّري البرامج.