Mit Hilfe von ChatGPT und Claude konnte ich es zum Laufen bringen und sehr anpassbar gestalten:
Wenn Sie dies tun möchten, erstellen Sie eine neue Komponente und fügen Sie Folgendes zum CSS-Tab hinzu:
.sidebar-section-link-prefix .emoji.prefix-emoji {
width: 1rem !important;
height: 1rem !important;
}
In meinem speziellen Fall funktioniert 1rem hervorragend. Passen Sie es an Ihr Forum/Ihre Community an.
Dann im JS-Tab:
import { apiInitializer } from "discourse/lib/api";
import { emojiUrlFor } from "discourse/lib/text";
export default apiInitializer("0.11.1", (api) => {
// Map section names to IDs
const sectionIds = {
"community": 1,
"tiago": 2,
"personal-section": 3,
// Add more sections here
};
// Map of [sectionId, itemName] to emoji names
const iconReplacements = {
// Community section (ID: 1)
"1,admin": "wrench",
"1,review": "triangular_flag_on_post",
"1,everything": "books",
"1,my-posts": "writing_hand",
"1,my-messages": "envelope_with_arrow",
// Tiago section (ID: 2)
"2,Journal": "notebook_with_decorative_cover",
"2,Music": "musical_note",
"2,About": "bust_in_silhouette",
// Personal section (ID: 3)
"3,Backups": "floppy_disk",
"3,Scheduled": "clock3",
"3,Staff": "lock",
"3,Components": "electric_plug",
};
function replaceIcons() {
Object.entries(sectionIds).forEach(([sectionName, sectionId]) => {
Object.entries(iconReplacements).forEach(([key, emojiName]) => {
const [keyId, itemName] = key.split(',');
// Only process if this replacement is for the current section
if (parseInt(keyId) === sectionId) {
const url = emojiUrlFor(emojiName);
// Try multiple selectors to catch both hamburger menu and fixed sidebar
const selectors = [
// Fixed sidebar selector
`div[data-section-name="${sectionName}"] li[data-list-item-name="${itemName}"] .sidebar-section-link-prefix.icon`,
// Hamburger menu selector (more specific)
`.menu-panel div[data-section-name="${sectionName}"] li[data-list-item-name="${itemName}"] .sidebar-section-link-prefix.icon`,
// Generic fallback
`[data-section-name="${sectionName}"] [data-list-item-name="${itemName}"] .sidebar-section-link-prefix.icon`
];
for (const selector of selectors) {
const prefix = document.querySelector(selector);
if (prefix && url) {
// Check if it's already replaced to avoid unnecessary DOM manipulation
if (!prefix.querySelector('.prefix-emoji')) {
prefix.innerHTML = `
<img src="${url}"
title="${emojiName}"
alt="${emojiName}"
class="emoji prefix-emoji">
`;
}
break; // Exit loop once we find and replace the icon
}
}
}
});
});
}
// Run on page change
api.onPageChange(replaceIcons);
// Also run with delay to catch dynamically loaded content
api.onPageChange(() => {
setTimeout(replaceIcons, 100);
setTimeout(replaceIcons, 500);
});
// Enhanced MutationObserver to catch sidebar changes
const observer = new MutationObserver((mutations) => {
let shouldReplace = false;
mutations.forEach((mutation) => {
// Watch for added nodes (original functionality)
mutation.addedNodes.forEach((node) => {
if (node.nodeType === Node.ELEMENT_NODE) {
if (node.classList?.contains('menu-panel') ||
node.querySelector?.('.sidebar-sections') ||
node.classList?.contains('sidebar-sections') ||
node.querySelector?.('[data-section-name]')) {
shouldReplace = true;
}
}
});
// Watch for attribute changes on sidebar sections (collapse/expand)
if (mutation.type === 'attributes' && mutation.target.nodeType === Node.ELEMENT_NODE) {
const target = mutation.target;
if (target.matches('[data-section-name]') ||
target.closest('[data-section-name]') ||
target.matches('.sidebar-section') ||
target.closest('.sidebar-section')) {
shouldReplace = true;
}
}
// Watch for childList changes in sidebar sections
if (mutation.type === 'childList' && mutation.target.nodeType === Node.ELEMENT_NODE) {
const target = mutation.target;
if (target.matches('[data-section-name]') ||
target.closest('[data-section-name]') ||
target.querySelector('[data-section-name]')) {
shouldReplace = true;
}
}
});
if (shouldReplace) {
setTimeout(replaceIcons, 50);
}
});
// Start observing with enhanced options
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true, // Watch for attribute changes
attributeFilter: ['class', 'style', 'aria-expanded'], // Common attributes that change on collapse/expand
});
// Additional event listeners for common sidebar interactions
document.addEventListener('click', (event) => {
// Check if click was on a sidebar section header or toggle button
if (event.target.closest('.sidebar-section-header') ||
event.target.closest('[data-section-name]') ||
event.target.matches('.sidebar-section-toggle')) {
setTimeout(replaceIcons, 100);
}
});
});
Ich habe es so gemacht, dass ich einfach neue benutzerdefinierte Abschnitte nach Namen hinzufügen kann, ihnen eine id zuweisen und dann die Zuordnung für jeden Abschnitt erstellen kann.
Der Grund dafür ist, dass ich möglicherweise 2 Abschnitte mit dem Titel Journal habe, aber vielleicht möchte ich für jeden ein anderes Emoji.
Ich bin mir ziemlich sicher, dass jemand sagen wird, dass es eine Komponente oder ein Plugin dafür gibt
aber es hat trotzdem Spaß gemacht, mit ChatGPT und Claude hin und her zu gehen, bis alles so funktionierte, wie ich es wollte.
Ich hoffe, das hilft anderen Benutzern.
Wenn Sie etwas sehen, das angepasst/verbessert werden kann, teilen Sie es bitte mit 