markdown.it le moteur CommonMark utilisé par Discourse dispose d’un large éventail de plugins
Ancres d’en-tête, listes de définition, flèches intelligentes et la liste continue encore et encore.
D’abord un avertissement
CommonMark est censé être… Commun. Plus vous vous éloignez de la spécification, moins votre Markdown devient Commun. Cela peut rendre la portabilité vers d’autres solutions plus difficile et, si vous n’y prenez garde, provoquer des incohérences internes dans l’analyse syntaxique. Avant de reconditionner quoi que ce soit, assurez-vous de répondre à la question « ai-je vraiment besoin de reconditionner ceci ? »
Je viens de terminer le reconditionnement de Discourse Footnote et j’ai quelques leçons à partager sur la façon de le faire correctement.
Étapes pour les paresseux
Si vous êtes paresseux et que vous voulez simplement commencer, le moyen le plus simple est de forker les notes de bas de page et d’échanger les fichiers et les noms de variables. J’ai fait très attention à ce que cela suive les meilleures pratiques, vous devriez donc avoir un exemple solide.
Premiers pas, un reconditionnement minimal
D’après ce que j’ai pu constater, la majorité des plugins markdown.it sont distribués sous forme de fichiers js standards. Dans de nombreux cas, les plugins sont simplement distribués sous la forme d’un seul fichier js, comme ceci : markdown-it-mark.js.
Idéalement, vous souhaitez laisser l’original intact, ce qui signifie que vous pouvez simplement copier une version mise à jour du fichier dans votre plugin sans avoir besoin de modifier le plugin existant.
Le premier problème que vous rencontrerez est que vous devez apprendre à votre plugin à charger ce JavaScript sur le serveur, car le moteur Markdown s’exécute également sur le serveur. Pour ce faire, vous pouvez simplement copier le fichier tel quel dans assets/javascripts/vendor/original-plugin.js, puis dans votre fichier plugin.rb, vous ajouteriez :
# ceci apprend à notre moteur markdown à charger votre fichier js standard
register_asset "javascripts/vendor/original-plugin.js", :vendored_pretty_text
Une fois que vous avez inclus le corps réel du plugin, vous devez apprendre à notre pipeline comment le charger et l’initialiser :
Créez un fichier nommé assets/javascripts/lib/discourse-markdown/your-extension.js
Ce fichier sera chargé automatiquement car il se termine par .js ET se trouve dans le répertoire discourse-markdown.
Un exemple simple peut être :
export function setup(helper) {
// ceci vous permet de charger votre extension uniquement si un paramètre du site est activé
helper.registerOptions((opts, siteSettings) => {
opts.features["your-extension"] = !!siteSettings.enable_my_plugin;
});
// mettre sur liste blanche tous les attributs que vous devez prendre en charge,
// sinon notre assainisseur les supprimera
helper.whiteList(["div.amazingness"]);
// vous pouvez également faire des choses sophistiquées comme ceci
helper.whiteList({
custom(tag, name, value) {
if ((tag === "a" || tag === "li") && name === "id") {
return !!value.match(/^fn(ref)?\d+$/);
}
},
});
// enfin, c'est la magie que vous utiliseriez pour enregistrer l'extension dans
// notre pipeline. whateverGlobal est le nom du global que le plugin expose
// il prend une seule variable (md) qui est ensuite utilisée pour modifier le pipeline
helper.registerPlugin(window.whateverGlobal);
}
Toujours tester
bin/rake autospec de Discourse est conscient des plugins ![]()
Cela signifie que lorsque vous ajoutez le fichier spec/pretty_text_spec.rb, chaque fois que vous l’enregistrez, le fichier de test du plugin s’exécutera.
Je l’utilise intensivement car cela rend le travail beaucoup plus rapide.
Disons que vous avez ajouté un plugin qui change chaque nombre dans un message en 8 cercles, vous pouvez l’appeler discourse-magic-8-ball.
Voici comment je structurerais les tests :
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
Vous pourriez avoir besoin de « décorer les messages »
Dans certains cas, les plugins fonctionnent mieux lorsqu’ils ajoutent des fonctionnalités « dynamiques » supplémentaires à vos messages. Des exemples en sont le plugin poll ou le plugin footnotes qui ajoute un « … » affichant dynamiquement une info-bulle.
si vous avez besoin de « décorer » les messages, ajoutez 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) => {
// votre magie incroyable va ici
});
});
Vous pourriez avoir besoin de « post-traiter » les messages
Dans certains cas, vous pourriez avoir besoin de « post-traiter » les messages, le moteur de rendu markdown, par conception, n’est pas au courant de certaines informations telles que, par exemple, post_id. Dans certains cas, vous souhaiterez un accès côté serveur au message et au HTML « cuit », cela peut vous permettre de faire des choses comme déclencher des tâches d’arrière-plan, synchroniser des champs personnalisés ou « corriger » le HTML généré automatiquement.
Pour les notes de bas de page, j’avais besoin d’un id distinct pour chaque note de bas de page, ce qui signifiait que j’avais besoin d’accéder à post_id, j’ai donc été obligé d’apporter des modifications au HTML dans le post-processeur (qui s’exécute dans sidekiq)
Pour vous connecter, vous ajouteriez ce qui suit à votre fichier plugin.rb :
DiscourseEvent.on(:before_post_process_cooked) do |doc, post|
doc.css("a.always-bing").each do |a|
# ceci doit toujours aller vers bing
a["href"] = "https://bing.com"
end
end
Vous pourriez avoir besoin de CSS personnalisé
Si vous souhaitez fournir du CSS personnalisé, assurez-vous d’enregistrer le fichier dans plugin.rb
Ajoutez votre css à assets/stylesheets/magic.scss puis exécutez
register_asset "stylesheets/magic.scss"
N’oubliez pas que nous « rechargeons automatiquement » les modifications, vous pouvez donc modifier le CSS de votre plugin et voir les changements à la volée en développement.
Bonne chance dans vos aventures de reconditionnement ![]()
Ce document est contrôlé par version - suggérez des modifications sur github.