Ich verwende decorateCooked im Theme meiner Website, um Code-Blöcke von HighlightJS für eine bestimmte Sprache nachzubearbeiten. Es funktioniert, wenn ``` verwendet wird, um Code in einem Beitrag zu kennzeichnen, schlägt jedoch fehl, wenn Einrückungen verwendet werden, um Code einzuschließen.
Im erfolgreichen Fall sind die HighlightJS-Klassen vorhanden, bevor mein decorateCooked-Code ausgeführt wird, und ich kann mit JQuery Code-Blöcke finden, die meine Sprachklasse (‘applescript’) tragen. Im fehlerhaften Fall scheint HighlightJS seine Magie erst nach der Ausführung meines Plugin-Codes anzuwenden, da die HighlightJS-Klassen (hljs applescript) fehlen. Diese Klassen sind jedoch vorhanden, wenn ich die geladene Seite später inspiziere.
Hier ist mein Code, der im <HEAD>-Bereich meines Themes definiert ist:
<script type="text/discourse-plugin" version="0.1">
if (navigator.appVersion.indexOf('Mac') >= 0) { // Nur auf dem Mac ausführen
api.decorateCooked(
$elem => {
console.log($elem.find('code'));
console.log($elem.find('code').attr('class'));
$elem.find('.lang-applescript, .applescript').filter(function () {
return $(this).parents('.d-editor-preview').length < 1; // Nicht in Editor-Vorschauen ausführen
}).each(function(index) {
var src = encodeURIComponent(this.innerText);
$( '<a class="widget-button btn btn-default" href="sdapplescript://com.apple.scripteditor?action=new&script=' + src + '">In Script Debugger öffnen</a>' ).insertAfter($(this).parent());
});
},
{ id: 'applescript-decorator' }
);
}
</script>
In der Konsolenprotokollausgabe sehe ich, dass ich die <code>-Blöcke in meinen Beiträgen finde, aber das class-Attribut wird als undefined gemeldet.
Gibt es eine Möglichkeit, meinen decorateCooked-Code nach der Ausführung von HighlightJS laufen zu lassen?
Ich habe eine Lösung für dieses Problem mit MutationObserver gefunden, bin mir aber nicht sicher, ob dies der beste Ansatz ist:
<script type="text/discourse-plugin" version="0.1">
if (navigator.appVersion.indexOf('Mac') >= 0) { // Dies nur auf dem Mac ausführen
if (typeof myObserver == 'undefined') {
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
var myObserver = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
var target = $(mutation.target);
if (target.hasClass('applescript')) {
var src = encodeURIComponent(mutation.target.innerText);
$('<a class="widget-button btn btn-default" href="sdapplescript://com.apple.scripteditor?action=new&script=' + src + '">In Script Debugger öffnen</a>').insertAfter(target.parent());
}
});
});
var obsConfig = { childList: false, characterData: false, attributes: true, subtree: false };
}
api.decorateCooked(
$elem => {
$elem.find('.lang-applescript, .applescript').filter(function () {
return $(this).parents('.d-editor-preview').length < 1; // Dies nicht in Editor-Vorschauen ausführen
}).each(function(index) {
var src = encodeURIComponent(this.innerText);
$('<a class="widget-button btn btn-default" href="sdapplescript://com.apple.scripteditor?action=new&script=' + src + '">In Script Debugger öffnen</a>').insertAfter($(this).parent());
});
// Fall abdecken, in dem HighlightJS *nach* dem Aufruf von decorateCooked angewendet wird. Dies tritt bei
// Codeblöcken auf, die durch Einrückung statt durch ``` eingefügt wurden.
$elem.find('code:not(.applescript,.lang-applescript)').filter(function () {
return $(this).parents('.d-editor-preview').length < 1; // Dies nicht in Editor-Vorschauen ausführen
}).each(function () {
myObserver.observe(this, obsConfig);
});
},
{ id: 'applescript-decorator', onlyStream: true }
);
}
</script>
Ich hatte gerade die gleiche Herausforderung, also habe ich eine neue API-Funktion hinzugefügt, um diesen Anwendungsfall zu behandeln: api.registerHighlightJSPlugin.