markdown.it وهو محرك CommonMark الذي يستخدمه Discourse، لديه مجموعة واسعة من المكونات الإضافية
مراسي الرؤوس، وقوائم التعريفات، والسهام الذكية، والقائمة تطول وتطول.
أولاً تحذير
يُقصد بـ CommonMark أن يكون… شائعًا. كلما ابتعدت عن المواصفات، أصبحت Markdown الخاصة بك أقل شيوعًا. قد يجعل هذا من الصعب النقل إلى حلول أخرى، وإذا لم تتوخ الحذر، فقد يتسبب في تناقضات داخلية في التحليل. قبل إعادة تجميع أي شيء، تأكد من الإجابة على السؤال “هل أريد حقًا إعادة تجميع هذا؟”
لقد انتهيت للتو من إعادة تجميع Discourse Footnote ولدي بعض الدروس لمشاركتها حول كيفية القيام بذلك بشكل صحيح.
خطوات للكسول
إذا كنت كسولًا وتريد فقط البدء، فإن أسهل طريقة هي ببساطة استنساخ الحواشي السفلية وتبديل الملفات وأسماء المتغيرات. لقد كنت حريصًا جدًا على التأكد من أنه يتبع أفضل الممارسات، لذلك يجب أن يكون لديك مثال جيد.
الحركات الافتتاحية، إعادة تجميع بسيطة
مما أستطيع أن أراه، يتم شحن غالبية المكونات الإضافية لـ markdown.it كملفات JavaScript عادية. في كثير من الحالات، يتم شحن المكونات الإضافية كملف js واحد فقط، مثل هذا: markdown-it-mark.js.
من الناحية المثالية، تريد ترك الأصل سليمًا، وهذا يعني أنه يمكنك ببساطة نسخ نسخة محدثة من الملف إلى المكون الإضافي الخاص بك دون الحاجة إلى العبث بالمكون الإضافي الحالي.
المشكلة الأولى التي ستصادفها هي أنه يتعين عليك تعليم المكون الإضافي الخاص بك تحميل هذا JavaScript على الخادم لأن محرك Markdown يعمل على الخادم أيضًا. للقيام بذلك، يمكنك ببساطة نسخ الملف كما هو إلى assets/javascripts/vendor/original-plugin.js ثم في ملف plugin.rb الخاص بك ستضيف:
# هذا يعلم محرك markdown الخاص بنا تحميل ملف js العادي الخاص بك
register_asset "javascripts/vendor/original-plugin.js", :vendored_pretty_text
بمجرد تضمين نص المكون الإضافي الفعلي، تحتاج إلى تعليم خط الأنابيب الخاص بنا كيفية تحميله وتهيئته:
أنشئ ملفًا يسمى assets/javascripts/lib/discourse-markdown/your-extension.js
سيتم تحميل هذا الملف تلقائيًا لأنه ينتهي بـ .js وفي دليل discourse-markdown.
مثال بسيط يمكن أن يكون:
export function setup(helper) {
// هذا يسمح لك فقط بتحميل الإضافة الخاصة بك إذا كان إعداد الموقع ممكّنًا
helper.registerOptions((opts, siteSettings) => {
opts.features["your-extension"] = !!siteSettings.enable_my_plugin;
});
// ضع في القائمة البيضاء أي سمات تحتاج إلى دعمها،
// وإلا فسيقوم المنظف لدينا بإزالتها
helper.whiteList(["div.amazingness"]);
// يمكنك أيضًا القيام بأشياء رائعة مثل هذا
helper.whiteList({
custom(tag, name, value) {
if ((tag === "a" || tag === "li") && name === "id") {
return !!value.match(/^fn(ref)?\d+$/);
}
},
});
// أخيرًا، هذا هو السحر الذي ستستخدمه لتسجيل الامتداد في
// خط الأنابيب الخاص بنا. whateverGlobal هو اسم المتغير العام الذي يكشف عنه المكون الإضافي
// يأخذ متغيرًا واحدًا (md) يتم استخدامه بعد ذلك لتعديل خط الأنابيب
helper.registerPlugin(window.whateverGlobal);
}
كن دائمًا في حالة اختبار
أداة bin/rake autospec الخاصة بـ Discourse تدرك المكونات الإضافية ![]()
هذا يعني أنه عند إضافة الملف spec/pretty_text_spec.rb في كل مرة تحفظه فيها، سيتم تشغيل ملف اختبار المكون الإضافي.
أنا أستخدم هذا بشكل مكثف لأنه يجعل العمل أسرع بكثير.
لنفترض أنك أضفت مكونًا إضافيًا يغير كل رقم في منشور إلى 8 دوائر، يمكنك تسميته discourse-magic-8-ball.
إليك كيف سأقوم بهيكلة الاختبارات:
require "rails_helper"
describe PrettyText do
it "can be disabled" do
SiteSetting.enable_magic_8_ball = false
markdown = <<-MD
1 thing
MD
html = <<-HTML
<p>1 thing</p>
HTML
cooked = PrettyText.cook markdown.strip
expect(cooked).to eq(html.strip)
end
it "supports magic 8 ball" do
markdown = <<-MD
1 thing
MD
html = <<-HTML
<p>8 circle thing</p>
HTML
cooked = PrettyText.cook markdown.strip
expect(cooked).to eq(html.strip)
end
end
قد تحتاج إلى “تزيين المنشورات”
في بعض الحالات، تعمل المكونات الإضافية بشكل أفضل عندما تضيف ميزات “ديناميكية” إضافية إلى منشوراتك. من الأمثلة على ذلك المكون الإضافي poll أو المكون الإضافي footnotes الذي يضيف “…” يعرض تلميحًا مرئيًا ديناميكيًا.
إذا كنت بحاجة إلى “تزيين” المنشورات، أضف assets/javascripts/api-initializers/your-initializer.js
import { apiInitializer } from "discourse/lib/api";
export default apiInitializer((api) => {
const siteSettings = api.container.lookup("service:site-settings");
if (!siteSettings.enable_magic_8_ball) {
return;
}
api.decorateCookedElement((elem) => {
// سحرك المذهل يذهب هنا
});
});
قد تحتاج إلى “معالجة لاحقة” للمنشورات
في بعض الحالات، قد تحتاج إلى “معالجة لاحقة” للمنشورات، ومحرك عرض markdown، بحكم تصميمه، لا يدرك معلومات معينة مثل، على سبيل المثال، post_id. في بعض الحالات، قد ترغب في الوصول من جانب الخادم إلى المنشور و HTML “المطبوخ”، يمكن أن يتيح لك ذلك القيام بأشياء مثل تشغيل مهام في الخلفية، أو مزامنة الحقول المخصصة، أو “تصحيح” HTML الذي تم إنشاؤه تلقائيًا.
بالنسبة للحواشي السفلية، احتجت إلى id مميز لكل حاشية سفلية، مما يعني أنني احتجت إلى الوصول إلى post_id، لذلك اضطررت إلى إجراء تغييرات على HTML في معالج المنشور (الذي يعمل في sidekiq)
للتوصيل، ستضيف ما يلي إلى ملف plugin.rb الخاص بك:
DiscourseEvent.on(:before_post_process_cooked) do |doc, post|
doc.css("a.always-bing").each do |a|
# هذا يجب أن يذهب دائمًا إلى بينج
a["href"] = "https://bing.com"
end
end
قد تحتاج إلى بعض CSS المخصص
إذا كنت تريد شحن CSS مخصص، فتأكد من تسجيل الملف في plugin.rb
أضف ملف css الخاص بك إلى assets/stylesheets/magic.scss ثم قم بتشغيل
register_asset "stylesheets/magic.scss"
تذكر أننا “نعيد تحميل” التغييرات حتى تتمكن من تعديل CSS المكون الإضافي الخاص بك ورؤية التغييرات أثناء التنقل في التطوير.
حظًا سعيدًا في مغامرات إعادة التجميع الخاصة بك ![]()
يتم التحكم في إصدار هذا المستند - اقترح تغييرات على github.