تغيير المواضيع لـ Mermaid (Updated) (العربية (Arabic))

تغيير المواضيع لـ Mermaid (Updated)

Thursday, 29 August 2024

//

7 minute read

المقدمة

أنا أستخدم Mermaid.js لخلق رسمات الدواء التي ترونها في بعض المدونات. كما هو الحال في الأسفل لكن ما يزعجني هو أنه لم يكن ' متجاوبًا على تغير المواضيع ( "dark" "M SK2" "light" ) ويبدو أن هناك معلومات سيئة جدًا عن كيفية تحقيق ذلك

هذا هو نتيجة بضع ساعات من البحث والمحاولة لمعرفة كيفية القيام بذلك

يمكنكم العثور على المصدر لـ mdeswitcher هنا: mdeswitcher.js.

ملاحظة: لقد قمت بتحديث هذا بشكل كبير.

الرسم البياني

graph LR
    A[Start] --> B[Initialize Mermaid with Theme]
    B --> C{Are there any elements matching 'div.mermaid'?}
    C --> |No| D[Exit]
    C --> |Yes| E[Save Original Data]
    E --> F{Did saving data succeed?}
    F --> |No| D[Exit]
    F --> |Yes| G[Set up Theme Event Listeners]
    G --> H[Check Local Storage for Dark Mode]
    H --> I{Is Dark Mode enabled?}
    I --> |Yes| J[Load Mermaid with Dark Theme]
    I --> |No| K[Load Mermaid with Default Theme]
    J --> L[Wait for Events]
    K --> L[Wait for Events]
    L --> M{Event Triggered?}
    M --> |Dark Theme Set| N[Reset Processed Data]
    N --> O[Load Mermaid with Dark Theme]
    M --> |Light Theme Set| P[Reset Processed Data]
    P --> Q[Load Mermaid with Default Theme]
    O --> L
    Q --> L
    L --> D[Exit]


المشكلة

المشكلة هي أنك تحتاج إلى إعداد Mermaid لتحديد الموضوع, ويمكنك' لا تغييره بعد ذلكM SK2 في أي حال إذا أردت إعادة تشغيله على الرسم البياني الذي تم خلقه بالفعلMSC3 يمكنهMスク4 لا إعادة رسم الرسم بياني بما أن البيانات ليستMسک5 لا تخزن في DOM

الحل

لذلك بعد حفنة ومحاولة معرفة كيفية القيام بهذا, وجدت حلا في نشر هذا الموضوع في GitHub

ومع ذلك كان لا يزال لديه بعض المشاكل, لذا كان علي تعديله قليلاً لجعله يعمل.

مواضيع

هذا الموقع مبني على موضوع "Tailwind" الذي جاء مع مفتاح موضوع سيء جداً

سوف ترون أن هذا يقوم بأشياء مختلفة حول تغير الموضوع , ضبط الموضوع لما يتم تخزينه في المخزن المحلي

export  function globalSetup() {
    const lightStylesheet = document.getElementById('light-mode');
    const darkStylesheet = document.getElementById('dark-mode');
    const simpleMdeDarkStylesheet = document.getElementById('simplemde-dark');
    const simpleMdeLightStylesheet = document.getElementById('simplemde-light');
    return {
        isMobileMenuOpen: false,
        isDarkMode: false,
        // Function to initialize the theme based on localStorage or system preference
        themeInit() {
            if (
                localStorage.theme === "dark" ||
                (!("theme" in localStorage) &&
                    window.matchMedia("(prefers-color-scheme: dark)").matches)
            ) {
                localStorage.theme = "dark";
                document.documentElement.classList.add("dark");
                document.documentElement.classList.remove("light");
                this.isDarkMode = true;
              
                this.applyTheme(); // Apply dark theme stylesheets
            } else {
                localStorage.theme = "base";
                document.documentElement.classList.remove("dark");
                document.documentElement.classList.add("light");
                this.isDarkMode = false;
                this.applyTheme(); // Apply light theme stylesheets
            }
        },

        // Function to switch the theme and update the stylesheets accordingly
        themeSwitch() {
            if (localStorage.theme === "dark") {
                localStorage.theme = "light";
                document.body.dispatchEvent(new CustomEvent('light-theme-set'));
                document.documentElement.classList.remove("dark");
                document.documentElement.classList.add("light");
                this.isDarkMode = false;
            } else {
                localStorage.theme = "dark";
                document.body.dispatchEvent(new CustomEvent('dark-theme-set'));
                document.documentElement.classList.add("dark");
                document.documentElement.classList.remove("light");
                this.isDarkMode = true;
            }
            this.applyTheme(); // Apply the theme stylesheets after switching
        },

        // Function to apply the appropriate stylesheets based on isDarkMode
        applyTheme() {
         
            if (this.isDarkMode) {
                // Enable dark mode stylesheets
                lightStylesheet.disabled = true;
                darkStylesheet.disabled = false;
                simpleMdeLightStylesheet.disabled = true;
                simpleMdeDarkStylesheet.disabled = false;
            } else {
                // Enable light mode stylesheets
                lightStylesheet.disabled = false;
                darkStylesheet.disabled = true;
                simpleMdeLightStylesheet.disabled = false;
                simpleMdeDarkStylesheet.disabled = true;
            }
        }
    };
}

الإعداد

الإضافات الرئيسية لـ Mermaid theme switcher هي التالي:

  document.body.dispatchEvent(new CustomEvent('dark-theme-set'));
    document.body.dispatchEvent(new CustomEvent('light-theme-set'));

هذه الأحداث تستخدم في مكون ThemeSwitcher لإعادة تشغيل رسومات حورية البحر.

على تحميل / htmx:afterSwap

في main.js أقوم بإعداد مفتاح موضوعي . وأقوم أيضا بتصدير mdeswitch ملف يحتوي على الرمز لتغيير المواضيع.

//Important: Memraid will ALWAYS intialize on window.onload, so we need to make sure we disable this behaviour:
import mermaid from "mermaid";

window.mermaid=mermaid;
mermaid.initialize({startOnLoad:false});

window.mermaidinit = function() {
    mermaid.initialize({ startOnLoad: false });
    try {
        window.initMermaid().then(r => console.log('Mermaid initialized'));
    } catch (e) {
        console.error('Failed to initialize Mermaid:', e);
    }

}

document.body.addEventListener('htmx:afterSwap', function(evt) {
    mermaidinit();
    //This should be called after the mermaid diagrams have been rendered.
    hljs.highlightAll();
});

window.onload = function(ev) {
    if(document.readyState === 'complete') {
        mermaidinit();
        hljs.highlightAll();
    }
};

MDESwtich

هذا هو الملف الذي يحتوي على الرمز لتغيير المواضيع لـ Mermaid. ( الوحشية الرسم البياني الأعلى يظهر سلسلة الأحداث التي تحدث عندما يتم تغير الموضوع)

(function(window) {
    'use strict';

    const elementCode = 'div.mermaid';

    const loadMermaid = async (theme) => {

        mermaid.initialize({startOnLoad: false, theme: theme });
        console.log("Loading mermaid with theme:", theme);
        await mermaid.run({
            querySelector: elementCode,
        });
    };

    const saveOriginalData = async () => {
        try {
            console.log("Saving original data");
            const elements = document.querySelectorAll(elementCode);
            const count = elements.length;

            if (count === 0) return;

            const promises = Array.from(elements).map((element) => {
                if (element.getAttribute('data-processed') != null) {
                    console.log("Element already processed");
                    return;
                }
                element.setAttribute('data-original-code', element.innerHTML);
            });

            await Promise.all(promises);
        } catch (error) {
            console.error(error);
            throw error;
        }
    };

    const resetProcessed = async () => {
        try {
            console.log("Resetting processed data");
            const elements = document.querySelectorAll(elementCode);
            const count = elements.length;

            if (count === 0) return;

            const promises = Array.from(elements).map((element) => {
                if (element.getAttribute('data-original-code') != null) {
                    element.removeAttribute('data-processed');
                    element.innerHTML = element.getAttribute('data-original-code');
                }
                else {
                    console.log("Element already reset");
                }
            });

            await Promise.all(promises);
        } catch (error) {
            console.error(error);
            throw error;
        }
    };

    window.initMermaid = async () => {
        const mermaidElements = document.querySelectorAll(elementCode);
        if (mermaidElements.length === 0) return;

        try {
            await saveOriginalData();
        } catch (error) {
            console.error("Error saving original data:", error);
            return; // Early exit if saveOriginalData fails
        }

        const handleDarkThemeSet = async () => {
            try {
                await resetProcessed();
                await loadMermaid('dark');
                console.log("Dark theme set");
            } catch (error) {
                console.error("Error during dark theme set:", error);
            }
        };

        const handleLightThemeSet = async () => {
            try {
                await resetProcessed();
                await loadMermaid('default');
                console.log("Light theme set");
            } catch (error) {
                console.error("Error during light theme set:", error);
            }
        };
        document.body.removeEventListener('dark-theme-set', handleDarkThemeSet);
        document.body.removeEventListener('light-theme-set', handleLightThemeSet);
        document.body.addEventListener('dark-theme-set', handleDarkThemeSet);
        document.body.addEventListener('light-theme-set', handleLightThemeSet);

        const isDarkMode = localStorage.theme === 'dark';
        await loadMermaid(isDarkMode ? 'dark' : 'default').then(r => console.log('Initial load complete'));


    };

})(window);

أذهب نوعا ما من الأسفل إلى الأعلى هنا

  1. init Function is the main function that is called when the page is loaded

أولاً يحفظ المحتوى الأصلي للرسمات لـ Mermaid ; كان هذا مشكلاً في النسخة التي نسختها منها , استخدموا | ' | internalHTML | ' , التي لم تعمل |' , لأنها لا تعمل بالنسبة لي لأن بعض الرسومات تعتمد على خطوط جديدة التي تمر عليها

ثم يضيف مرتين من المستمعين للأحداث dark-theme-set و light-theme-set الأحداث. عندما يتم إطلاق هذه الأحداث يعيد تشغيل البيانات المعالجة ومن ثم يقوم بإعادة تنشيط رسومات حورية البحر مع الموضوع الجديد.

ومن ثم يتأكد من المخزن المحلي للموضوع ويبدأ رسمات حورية البحر مع الموضوع المناسب

let isDarkMode = localStorage.theme === 'dark';
        if(isDarkMode) {
            loadMermaid('dark');
         }
         else{
             loadMermaid('default')
         }

تحمّل البيانات الأصلية

المفتاح لهذا الشئ كله هو تخزين ثم استعادة المحتوى الذي يحتوي في المحاكاة <div class="mermaid"><div> التي تحتوي على علامة البحر من رسائلنا

سوف ترون هذا فقط يضع وعداً يدور عبر كل العناصر ويحفظ المحتوى الأصلي في data-original-code atribute.

    const saveOriginalData = async () => {
    try {
        console.log("Saving original data");
        const elements = document.querySelectorAll(elementCode);
        const count = elements.length;

        if (count === 0) return;

        const promises = Array.from(elements).map((element) => {
            if (element.getAttribute('data-processed') != null) {
                console.log("Element already processed");
                return;
            }
            element.setAttribute('data-original-code', element.innerHTML);
        });

        await Promise.all(promises);
    } catch (error) {
        console.error(error);
        throw error;
    }
};

resetProcessed هو نفسه باستثناء العكس حيث يأخذ العلامة التجارية من data-original-code attribut and sets it back to the element.

فييت

الآن لدينا كل هذه البيانات يمكننا إعادة تنشيط سمكة البحر لتطبيق موضوعنا الجديد وإعادة رسم الرسم البياني SVG في مخرج HTML

    const elementCode = 'div.mermaid';

const loadMermaid = async (theme) => {

    mermaid.initialize({startOnLoad: false, theme: theme });
    console.log("Loading mermaid with theme:", theme);
    await mermaid.run({
        querySelector: elementCode,
    });
};

في الختام

لقد كان ألماً قليلاً لمعرفة ذلك، لكنني سعيد أنني فعلت، آمل أن يساعد هذا شخص آخر هناك يحاول فعل الشيء نفسه.

Finding related posts...
logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.