Topic embedding يحتاج إلى بعض الاهتمام

تم تذكيري بهذا اليوم بعد النقر على زر “إظهار المنشور بالكامل” لـ Introducing Discourse AI. المنشور الكامل الذي يتم عرضه على Discourse يفتقد جميع الصور والعديد من العناوين. مما يزيد الارتباك، يتم عرض تسميات توضيحية للصور، ولكن بدون الصور المرتبطة بها.

قد يكون من الممكن إصلاح المشكلة في Meta لمدونتها (Ghost؟) عن طريق ضبط إعداد الموقع allowed embed selectors: Configuring allowed embed selectors. من الخبرة السابقة، أعرف أن الحصول على هذا الإعداد يمكن أن يكون عملية صعبة. إذا حاولت تعديله، انتبه جيدًا للنتائج.

يمتلك Discourse الكثير من الإمكانات للعمل كنظام تعليقات للمنشورات الخارجية، ولكن للقيام بعمل جيد في هذا، يحتاج النقر على زر “إظهار المنشور بالكامل” إلى جلب جميع عناصر المنشور الخارجي بشكل موثوق. أعتقد أن المشكلة هي أن جوهرة Ruby Readability المستخدمة لتحليل المنشورات الخارجية ليست مخصصة للوظيفة التي يستخدمها Discourse لها. كما أنها لا تتم صيانتها بنشاط: GitHub - cantino/ruby-readability: Port of arc90's readability project to Ruby.

3 إعجابات

نعم، في هذه المرحلة إما أن ننتقل إلى شيء آخر يجعله أفضل قليلاً أو نغير استراتيجية التضمين لجعل Show Full Post إلى Read Full Post الذي هو رابط بسيط للمنشور الأصلي. قد يكون من العبث محاربة جميع مشاكل التضمين الممكنة في كل موقع على الويب في نهاية المطاف.

4 إعجابات

@sam لقد قمت بإصلاح هذا للتو، ألقِ نظرة.

3 إعجابات

نحن نستعد لإطلاق مدونتنا على Ghost والاستفادة من عمليات تكامل Ghost > Discourse. يسعدنا حقًا رؤية هذا التغيير!

4 إعجابات

تم سحب الصور الآن. لست بارعًا في ألغاز “اكتشف الاختلافات”، لكنني ما زلت أرى بعض الاختلافات:

  • عنوان المواضيع ذات الصلة دلاليًا مفقود
  • عنوان معنويات المجتمع مفقود
  • قائمة غير مرتبة مفقودة في قسم مزودو الوحدات
  • عنوان تثبيت Discourse AI على مجتمعك مفقود

من الناحية المثالية، يجب استبعاد عبارة “اشترك في النشرة الإخبارية” من المنشور المضمن.

تعد القدرة على اقتباس المنشور المضمن بسهولة أمرًا مهمًا. بالتفكير في ذلك الآن، لست متأكدًا من السلوك المتوقع عند النقر على أزرار “توسيع/طي” و “الانتقال إلى المنشور” لاقتباسات المنشور المضمن.

إنها مشكلة صعبة. يجب أن يكون الأمر بسيطًا مثل تنقية HTML الموجود في عنصر article أو main الخاص بالمنشور، لكنني أشك في أنه لا تزال هناك مشكلات مع هذا النهج. على سبيل المثال، سيتطلب بعض المعالجة الخاصة لمنع تكرار عنصر h1 الخاص بمنشور مدونة إذا كان header موجودًا داخل article.

إعجاب واحد (1)

أعتقد أن كل هذا يحدث أيضًا في readability.js، هذه هي طريقة عرض القراءة في فايرفوكس:

<h2>
      <strong>تثبيت Discourse AI على مجتمعك</strong>
    </h2>

سأرى ما إذا كانت هناك طريقة سهلة لإصلاح هذا…

لست متأكدًا من هذا… ولكن إذا كنا نريد حقًا فعل ذلك، فيمكننا إضافة .discourse-newsletter-signup إلى blocked_embed_selectors

4 إعجابات

نعم، readablity.js يعتمد على نفس الشيفرة مثل https://github.com/cantino/ruby-readability، لذلك من المحتمل أن يتم استخدام نفس المنطق لإزالة تلك العناصر. بشكل عام، يقوم readablity.js بعمل أفضل من Ruby Readability.

عبارة الحث على اتخاذ إجراء (CTA) الخاصة بالبريد الإلكتروني مربكة لأن حقل إدخال البريد الإلكتروني يتم تجريده من المنشور المضمن. من الناحية الفنية، لست متأكدًا مما إذا كانت عبارة الحث على اتخاذ إجراء تنتمي إلى داخل article.

إعجاب واحد (1)

مجرد رفع هذا، حيث أتفق مع @simon على أنه يجب إعادة التفكير في هذا الأمر في وقت ما.

جزء كبير من طلبات الدعم لمكون WP Discourse الإضافي هي في الواقع مشاكل زحف القراءة لأحد الأشكال أو غيرها.

أعتقد أن هذا يلخص شعوري بشأن هذا الأمر.

ومع ذلك، ليس لدي حل رائع في الوقت الحالي بخلاف هذا.

لكنني حريص على المساهمة في حل أفضل من الوضع الراهن، حيث سيقلل ذلك من عبء عمل دعم WP Discourse.

إعجاب واحد (1)

إنهم ينظرون إلى المشكلات، لكنهم بطيئون في إصلاحها…

إن إعداد MiniRacer لتغليف قابلية القراءة ليس بالأمر الصعب… لقد قمت بنموذج أولي لهذا.

من الممكن أن ننتقل إلى هذا التنفيذ، لكننا ابتعدنا بالفعل لذا سننتهي بالتخلي عن الميزات

هذه ليست مشكلة سهلة الحل.

إعجابَين (2)

نعم، هذا عادل، ومع ذلك أشعر أن هذه ستكون لعبة لا نهاية لها من “ضرب الخلد”. سيكون هناك دائمًا بعض الإصدارات من:

المنشور على موقعي يبدو مثل X وعندما أنقر على “إظهار المنشور بالكامل” يبدو مثل Y وأريد أن يكونا متطابقين.

أعتقد أن سؤالي الأعمق هو هل هناك فائدة حقيقية لهذه الوظيفة، التي لن تكون مثالية أبدًا، مقارنة بـ

من خلال جعله زر “إظهار المنشور بالكامل”، يتوقع الناس دقة لا يمكن لـ Discourse تقديمها بالكامل أبدًا. قلقي يتعلق أكثر بإدارة التوقعات.

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

إعجاب واحد (1)

ليس بالضرورة. أقول إنه يجب أن تكون هناك إدارة أفضل للتوقعات.

لن يعرف 99٪ من الأشخاص الذين يديرون موقعًا إلكترونيًا ما إذا كان HTML الخاص بهم دلاليًا بما يكفي ليتم تحليله بسهولة بواسطة جوهرة مثل readability، أو حتى أن هذا هو ما يحدد كيفية عمل الميزة. الافتراض الافتراضي للمستخدمين هو وجود مشكلة “في Discourse” (أو في كثير من الأحيان في المكون الإضافي WP Discourse) عندما لا يكون هناك تطابق بنسبة 100٪ بين المنشور على موقعهم والمحتوى الذي يظهر عندما ينقر المستخدم على “عرض المنشور بالكامل”.

إن جعل خيار مثل وجود دعوة لاتخاذ إجراء “قراءة المنشور بالكامل” سهل التمكين، وربما يكون افتراضيًا، سيساعد أعتقد.

إعجابَين (2)

ما قصدته بهذا هو أن Ruby Readability هي “أداة لاستخراج المحتوى المقروء الأساسي لصفحة الويب”. بالنسبة لحالة موقع ينشر منشورات على Discourse، أعتقد أنه من الآمن افتراض أن المحتوى المقروء الأساسي لصفحة الويب معروف ويمكن تحديده بواسطة محدد CSS خارجي. على سبيل المثال، article، .entry-content، .post، إلخ.

النوع من الأدوات التي أتخيلها سيسمح ببساطة للمواقع بتحديد محدد خارجي لمحتوى منشورهم، ثم تنقية HTML الموجود داخل هذا المحدد. نسخة أكثر تطوراً قليلاً ستسمح للمواقع بتحديد محددات داخلية يرغبون في استبعادها من Discourse.

على موقع WordPress الخاص بي، لدي منشور بعلامات قياسية تمامًا. أود نشر كل ما هو موجود في div .entry-content إلى Discourse. هذا يعمل تقريبًا، لكن لا يمكنني معرفة كيفية تكوين إعداد allowed embed selector على Discourse لسحب عناصر القائمة في المنشور. هذا هو نوع المشكلة التي رأيت المواقع تعاني منها. بدون القدرة على تشغيل Rails.cache.clear، من الصعب جدًا التكوين.

نشر المنشور كـ onebox هو حل معقول لهذا.

تعديل: خيار debug مفيد لفهم ما يحدث: GitHub - cantino/ruby-readability: Port of arc90's readability project to Ruby. بالنسبة لحالة القوائم المستبعدة في منشور WordPress الخاص بي:

يتم تنظيف ul#. بشكل مشروط بوزن 0 ودرجة محتوى 0 لأنها تحتوي على الكثير من الروابط بالنسبة لوزنها (0).

إنها قائمة شرعية تمامًا على الرغم من ذلك.

ميزة مطلوبة كثيرًا مع تضمينات موسعة هي السماح لـ Youtube videos بالظهور في المحتوى الموسع. منع حدوث ذلك مبرمج بشكل ثابت في الجوهرة: ruby-readability/lib/readability.rb at master · cantino/ruby-readability · GitHub. لست متأكدًا مما إذا كان الأمر يستحق تقديم PR للسماح بتجاوز هذه القائمة بخيار.

إعجابَين (2)

لن أبالغ في هذا الأمر، لكنني كنت أستخدم Nokogiri لشيء آخر في عطلة نهاية الأسبوع. إنه نوع من الإدمان. اعتقدت أنني سألقي نظرة على كود التضمين بينما لا يزال Nokogiri في ذهني.

اهتمامي بهذا هو أنني أود أن أرى Discourse يُستخدم على نطاق أوسع من قبل مواقع الأخبار والمدونات. إذا حدث ذلك، يمكنني أن أتخيل أصحاب المواقع الجدد يصابون بالإحباط من وظيفة التضمين الحالية. إليك فكرة لتحسينها:

أضف سمتين جديدتين اختياريتين إلى نموذج EmbeddableHost:

  • target_selector: المحدد الخارجي لـ CSS الذي يحتوي على المحتوى المراد تضمينه
  • exclude_selectors: قائمة بمحددات CSS التي يجب استبعادها من المحتوى المحدد بواسطة target_selector.

يجب إضافة زر “تكوين” إلى كل صف مضيف مضمن في صفحة المسؤول / التضمين. يؤدي النقر فوق هذا الزر إلى فتح صفحة مشابهة لصفحة ملخص معاينة رسائل البريد الإلكتروني.

ستحتوي صفحة تكوين المضيف على نموذج به حقول لإدخال إعدادات target_selector و exclude_selectors للمضيف، وحقل عنوان URL يسمح باختبار القيم المقدمة مقابل صفحة ويب معينة. سيقوم الاختبار بشكل أساسي بتشغيل TopicEmbed.parse_html باستخدام قيم target_selector و exclude_selectors المقدمة، ثم عرض النتائج.


من السهل اختبار التغييرات في كود parse_html. إليك نهج محتمل. لاحظ أن هذا الكود هو مجرد إثبات للمفهوم:

تم تحريره في topic_embed.rb (discourse/app/models/topic_embed.rb at main · discourse/discourse · GitHub)

###########################################################################
    # من الناحية المثالية، سيتم العثور على `target_selector` و `exclude_selectors` من سجل `EmbeddableHost` الخاص بالمجال
    # تم استخدام هذه الإعدادات المحددة للاختبار مقابل boingboing.net
    target_selector = 'article'
    exclude_selectors = ['.article-header, .share-comments-container', '.boing-single-post-rev-content', '.next-post-list-container', '.boing-end-of-article-container-on-single-post-pages']

    if defined?(target_selector) && target_selector.present?
      read_doc = article_content(html, target_selector, exclude_selectors)
    else
      # الرجوع إلى Readability إذا لم يتم تعيين `target_selector` للمضيف
      read_doc = Readability::Document.new(html, opts)
    end
    ###########################################################################

للاختبار دون إنشاء فئة جديدة، إليك طريقة article_content أساسية تمت إضافتها إلى فئة TopicEmbed:

  def self.article_content(html, target_selector, exclude_selectors = [])
    doc = Nokogiri::HTML(html)
    # إزالة التعليقات وعلامات النص البرمجي
    doc.xpath('//comment()').each { |i| i.remove }
    doc.css("script, style").each { |i| i.remove }

    # الحصول على مجموعة العقد لـ target_selector
    # ربما الرجوع إلى Readability هنا إذا كانت المجموعة المرجعة فارغة
    selected_nodes = doc.css(target_selector)

    # استبعاد العقد
    unless exclude_selectors.empty?
      selected_nodes.css(*exclude_selectors).each do |node|
        node.remove
      end
    end

    # التعامل مع أحجام الصور، قد تحتاج إلى تحسين
    selected_nodes.css('img').each do |img|
      img.remove_attribute('width')
      img.remove_attribute('height')
    end

    # فقط من أجل المتعة، السماح بإطارات iframe إذا كان مصدرها مسموحًا به
    # استخدم `[data-sanitized="true"]` لمنع إزالة إطارات iframe في خطوة remove_empty_nodes
    allowed_iframe_sources = SiteSetting.allowed_iframes.split('|')
    selected_nodes.css('iframe').each do |iframe|
      allowed = allowed_iframe_sources.any? do |allowed_source|
        iframe['src'].start_with?(allowed_source)
      end

      if allowed
        iframe['data-sanitized'] = 'true'
        iframe['width'] = '690'
        iframe['height'] = '388'
      else
        iframe.remove
      end
    end

    # إزالة عقد 'p' و 'div' الفارغة
    selected_nodes.css('p', 'div').each do |node|
      node.remove if node.content.strip.empty? && !node.at_css('iframe[data-sanitized="true"]')
    end

    # تحويل العقد إلى سلسلة وإرجاع كائن يحتوي على طريقة `content`
    content = selected_nodes.to_s
    OpenStruct.new(content: content)
  end

أنا متأكد تمامًا من أن الأمر سيستغرق القليل من التعديل على نطاقات متعددة للحصول عليه بشكل صحيح. النتائج التي كنت أحصل عليها لـ BBS جيدة حتى الآن.

الهدف هو التوصل إلى شيء يمكن لأصحاب المواقع فهمه وتكوينه بسهولة بأنفسهم. مع هذا النهج، كلما كان target_selector أكثر تحديدًا، كان من الأسهل تكوين exclude_selectors. على سبيل المثال، بالنسبة لموقع WordPress، إذا تم تحديد .entry-content كـ target_selector، فلن تكون هناك حاجة إلى مزيد من التكوين. إذا أراد أصحاب المواقع الحصول على أكثر من محتوى HTML الأساسي .entry-content، فيمكنهم معرفة كيفية القيام بذلك في صفحة تكوين المضيف.

القضية الحقيقية الوحيدة التي يمكنني رؤيتها هي للمضيفين الذين لديهم HTML غير متناسق للغاية. يمكن التعامل مع هذه الحالة عن طريق الاحتفاظ بـ Ruby Readability كحل بديل.