Skip to content

Instantly share code, notes, and snippets.

@zsviczian
Last active June 18, 2023 00:40

Revisions

  1. zsviczian revised this gist Mar 4, 2023. 1 changed file with 19 additions and 14 deletions.
    33 changes: 19 additions & 14 deletions Excalidraw Dynamic Styling.md
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,6 @@
    <%*
    /*
    https://gist.github.com/zsviczian/c7223c5b4af30d5c88a0cae05300305c/edit
    ```javascript
    */
    const installStyleHook = () => {
    @@ -28,22 +29,26 @@ const installStyleHook = () => {

    const updateCSSClassVariable = (className, payload) => {
    for(stylesheet of doc.styleSheets) {
    for(rule of stylesheet.rules) {
    if (rule.selectorText !== className) continue;
    let cssText = rule.cssText;
    let changed = false;
    payload.forEach(pl => {
    const reg = new RegExp(`${pl.var}:\\s[^;]*`);
    if(cssText.match(reg)) {
    cssText = cssText.replace(reg,`${pl.var}: ${pl.val}`);
    changed = true;
    try { //introduced because of the argdown plugin caused a crash
    for(rule of stylesheet.rules) {
    if (rule.selectorText !== className) continue;
    let cssText = rule.cssText;
    let changed = false;
    payload.forEach(pl => {
    const reg = new RegExp(`${pl.var}:\\s[^;]*`);
    if(cssText.match(reg)) {
    cssText = cssText.replace(reg,`${pl.var}: ${pl.val}`);
    changed = true;
    }
    });
    if(changed) {
    stylesheet.deleteRule(rule);
    stylesheet.insertRule(cssText);
    }
    });
    if(changed) {
    stylesheet.deleteRule(rule);
    stylesheet.insertRule(cssText);
    }
    }
    } catch(e) {
    console.log("Excalidraw Dynamic Styling", e);
    }
    }
    }

  2. zsviczian revised this gist Jan 29, 2023. 1 changed file with 146 additions and 139 deletions.
    285 changes: 146 additions & 139 deletions Excalidraw Dynamic Styling.md
    Original file line number Diff line number Diff line change
    @@ -3,145 +3,152 @@
    ```javascript
    */
    const installStyleHook = () => {
    if(!window.ExcalidrawAutomate) return false;
    ExcalidrawAutomate.onCanvasColorChangeHook = (ea, view, color) => {
    const doc = view.ownerDocument;

    const dark = "#404040";
    const darker = "#202020";
    const light = "#f4f4f4";
    const lighter = "#fbfbfb";
    const step = 5;
    const mixRatio = 0.8;

    const cmBG = () => ea.getCM(color);

    const isDark = cmBG().isDark();

    const accent = () => {
    const s = doc.querySelector("body").style;
    return ea.getCM(`hsl(${s.getPropertyValue("--accent-h")},${
    s.getPropertyValue("--accent-s")},${s.getPropertyValue("--accent-l")})`).mix({color:isDark?dark:light, ratio:0.6});
    }

    const updateCSSClassVariable = (className, payload) => {
    for(stylesheet of doc.styleSheets) {
    for(rule of stylesheet.rules) {
    if (rule.selectorText !== className) continue;
    let cssText = rule.cssText;
    let changed = false;
    payload.forEach(pl => {
    const reg = new RegExp(`${pl.var}:\\s[^;]*`);
    if(cssText.match(reg)) {
    cssText = cssText.replace(reg,`${pl.var}: ${pl.val}`);
    changed = true;
    }
    });
    if(changed) {
    stylesheet.deleteRule(rule);
    stylesheet.insertRule(cssText);
    }
    }
    }
    }

    const str = (cm) => cm.stringHEX({alpha:false});

    const gray1 = cmBG().mix({color:isDark?darker:lighter, ratio:mixRatio});
    const gray2 = cmBG().mix({color:isDark?dark:light, ratio:mixRatio});
    const text = cmBG().mix({color:isDark?lighter:darker, ratio:mixRatio})

    updateCSSClassVariable (
    ".excalidraw",[
    {
    var: "--color-primary",
    val: str(accent())
    },
    {
    var: "--color-primary-darker",
    val: str(accent().darkerBy(step))
    },
    {
    var: "--color-primary-darkest",
    val: str(accent().darkerBy(step))
    },
    {
    var: "--button-gray-1",
    val: str(gray1)
    },
    {
    var: "--button-gray-2",
    val: str(gray2)
    },
    {
    var: "--input-border-color",
    val: str(gray1)
    },
    {
    var: "--input-bg-color",
    val: str(gray2)
    },
    {
    var: "--input-label-color",
    val: str(text)
    },
    {
    var: "--island-bg-color",
    val: gray2.alphaTo(0.93).stringHEX()
    },
    {
    var: "--icon-fill-color",
    val: str(text)
    },
    {
    var: "--text-primary-color",
    val: str(text)
    },
    {
    var: "--overlay-bg-color",
    val: gray2.alphaTo(0.6).stringHEX()
    },
    {
    var: "--popup-bg-color",
    val: str(gray1)
    },
    {
    var: "--color-gray-100",
    val: str(text)
    },
    {
    var: "--sidebar-border-color",
    val: str(gray1)
    },
    {
    var: "--color-primary-light",
    val: str(gray1)
    },
    {
    var: "--button-hover-bg",
    val: str(gray1)
    },
    {
    var: "--sidebar-bg-color",
    val: gray2.alphaTo(0.93).stringHEX()
    },
    {
    var: "--sidebar-shadow",
    val: str(gray1)
    },
    ]
    );
    };
    const view = app.workspace.activeLeaf?.view;
    if(view && view.getViewType() === "excalidraw") {
    if(!view.isLoaded || !view.excalidrawAPI) return true;
    ExcalidrawAutomate.onCanvasColorChangeHook(
    ExcalidrawAutomate,
    app.workspace.activeLeaf.view,
    view.excalidrawAPI.getAppState().viewBackgroundColor
    )
    }
    return true;
    if(!window.ExcalidrawAutomate) return false;

    ExcalidrawAutomate.onCanvasColorChangeHook = (ea, view, color) => {
    const doc = view.ownerDocument;

    const dark = "#404040";
    const darker = "#202020";
    const light = "#f4f4f4";
    const lighter = "#fbfbfb";
    const step = 5;
    const mixRatio = 0.8;

    const cmBG = () => ea.getCM(color);

    const isDark = cmBG().isDark();

    const accent = () => {
    const s = doc.querySelector("body").style;
    return ea.getCM(`hsl(${s.getPropertyValue("--accent-h")},${
    s.getPropertyValue("--accent-s")},${s.getPropertyValue("--accent-l")
    })`).mix({color:isDark?dark:light, ratio:0.6});
    }

    const updateCSSClassVariable = (className, payload) => {
    for(stylesheet of doc.styleSheets) {
    for(rule of stylesheet.rules) {
    if (rule.selectorText !== className) continue;
    let cssText = rule.cssText;
    let changed = false;
    payload.forEach(pl => {
    const reg = new RegExp(`${pl.var}:\\s[^;]*`);
    if(cssText.match(reg)) {
    cssText = cssText.replace(reg,`${pl.var}: ${pl.val}`);
    changed = true;
    }
    });
    if(changed) {
    stylesheet.deleteRule(rule);
    stylesheet.insertRule(cssText);
    }
    }
    }
    }

    const str = (cm) => cm.stringHEX({alpha:false});

    const gray1 = cmBG().mix({color:isDark?darker:lighter, ratio:mixRatio});
    const gray2 = cmBG().mix({color:isDark?dark:light, ratio:mixRatio});
    const text = cmBG().mix({color:isDark?lighter:darker, ratio:mixRatio})

    updateCSSClassVariable (
    ".excalidraw", [
    {
    var: "--color-primary",
    val: str(accent())
    },
    {
    var: "--color-primary-darker",
    val: str(accent().darkerBy(step))
    },
    {
    var: "--color-primary-darkest",
    val: str(accent().darkerBy(step))
    },
    {
    var: "--button-gray-1",
    val: str(gray1)
    },
    {
    var: "--button-gray-2",
    val: str(gray2)
    },
    {
    var: "--input-border-color",
    val: str(gray1)
    },
    {
    var: "--input-bg-color",
    val: str(gray2)
    },
    {
    var: "--input-label-color",
    val: str(text)
    },
    {
    var: "--island-bg-color",
    val: gray2.alphaTo(0.93).stringHEX()
    },
    {
    var: "--icon-fill-color",
    val: str(text)
    },
    {
    var: "--text-primary-color",
    val: str(text)
    },
    {
    var: "--overlay-bg-color",
    val: gray2.alphaTo(0.6).stringHEX()
    },
    {
    var: "--popup-bg-color",
    val: str(gray1)
    },
    {
    var: "--color-gray-100",
    val: str(text)
    },
    {
    var: "--sidebar-border-color",
    val: str(gray1)
    },
    {
    var: "--color-primary-light",
    val: str(gray1)
    },
    {
    var: "--button-hover-bg",
    val: str(gray1)
    },
    {
    var: "--sidebar-bg-color",
    val: gray2.alphaTo(0.93).stringHEX()
    },
    {
    var: "--sidebar-shadow",
    val: str(gray1)
    },
    {
    var: "--popup-text-color",
    val: str(text)
    }
    ]
    );
    };

    const view = app.workspace.activeLeaf?.view;
    if(view && view.getViewType() === "excalidraw") {
    if(!view.isLoaded || !view.excalidrawAPI) return true;
    ExcalidrawAutomate.onCanvasColorChangeHook(
    ExcalidrawAutomate,
    app.workspace.activeLeaf.view,
    view.excalidrawAPI.getAppState().viewBackgroundColor
    )
    }
    return true;
    }

    setTimeout(()=>{
  3. zsviczian revised this gist Jan 15, 2023. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions readme.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,5 @@
    Note that if you are using the Minimal theme, you will need to "patch" the Minimal theme to not interfere with Excalidraw and this dynamic styling. This short video demonstrates the "patching" process: https://youtu.be/LtR04fNTKTM

    Requires [Excalidraw-Obsidian](https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/README.md) 1.7.25 or later.
    Switch to "Raw" (top right button) before copying the script to Obsidian.

  4. zsviczian revised this gist Jan 15, 2023. 1 changed file with 10 additions and 2 deletions.
    12 changes: 10 additions & 2 deletions Excalidraw Dynamic Styling.md
    Original file line number Diff line number Diff line change
    @@ -118,9 +118,17 @@ const installStyleHook = () => {
    val: str(gray1)
    },
    {
    var: "--button-hover",
    var: "--button-hover-bg",
    val: str(gray1)
    }
    },
    {
    var: "--sidebar-bg-color",
    val: gray2.alphaTo(0.93).stringHEX()
    },
    {
    var: "--sidebar-shadow",
    val: str(gray1)
    },
    ]
    );
    };
  5. zsviczian revised this gist Dec 4, 2022. 1 changed file with 6 additions and 2 deletions.
    8 changes: 6 additions & 2 deletions Excalidraw Dynamic Styling.md
    Original file line number Diff line number Diff line change
    @@ -11,7 +11,7 @@ const installStyleHook = () => {
    const darker = "#202020";
    const light = "#f4f4f4";
    const lighter = "#fbfbfb";
    const step = 10;
    const step = 5;
    const mixRatio = 0.8;

    const cmBG = () => ea.getCM(color);
    @@ -116,7 +116,11 @@ const installStyleHook = () => {
    {
    var: "--color-primary-light",
    val: str(gray1)
    }
    },
    {
    var: "--button-hover",
    val: str(gray1)
    }
    ]
    );
    };
  6. zsviczian revised this gist Nov 15, 2022. 1 changed file with 16 additions and 16 deletions.
    32 changes: 16 additions & 16 deletions Excalidraw Dynamic Styling.md
    Original file line number Diff line number Diff line change
    @@ -9,10 +9,10 @@ const installStyleHook = () => {

    const dark = "#404040";
    const darker = "#202020";
    const light = "#d0d0d0";
    const lighter = "#f0f0f0";
    const light = "#f4f4f4";
    const lighter = "#fbfbfb";
    const step = 10;
    const mixRatio = 0.85;
    const mixRatio = 0.8;

    const cmBG = () => ea.getCM(color);

    @@ -87,7 +87,7 @@ const installStyleHook = () => {
    },
    {
    var: "--island-bg-color",
    val: gray2.alphaTo(0.85).stringHEX()
    val: gray2.alphaTo(0.93).stringHEX()
    },
    {
    var: "--icon-fill-color",
    @@ -105,18 +105,18 @@ const installStyleHook = () => {
    var: "--popup-bg-color",
    val: str(gray1)
    },
    {
    var: "--color-gray-100",
    val: str(text)
    },
    {
    var: "--sidebar-border-color",
    val: str(gray1)
    },
    {
    var: "--color-primary-light",
    val: str(gray1)
    }
    {
    var: "--color-gray-100",
    val: str(text)
    },
    {
    var: "--sidebar-border-color",
    val: str(gray1)
    },
    {
    var: "--color-primary-light",
    val: str(gray1)
    }
    ]
    );
    };
  7. zsviczian revised this gist Nov 13, 2022. 1 changed file with 13 additions and 1 deletion.
    14 changes: 13 additions & 1 deletion Excalidraw Dynamic Styling.md
    Original file line number Diff line number Diff line change
    @@ -104,7 +104,19 @@ const installStyleHook = () => {
    {
    var: "--popup-bg-color",
    val: str(gray1)
    }
    },
    {
    var: "--color-gray-100",
    val: str(text)
    },
    {
    var: "--sidebar-border-color",
    val: str(gray1)
    },
    {
    var: "--color-primary-light",
    val: str(gray1)
    }
    ]
    );
    };
  8. zsviczian revised this gist Oct 30, 2022. 1 changed file with 4 additions and 0 deletions.
    4 changes: 4 additions & 0 deletions Excalidraw Dynamic Styling.md
    Original file line number Diff line number Diff line change
    @@ -100,6 +100,10 @@ const installStyleHook = () => {
    {
    var: "--overlay-bg-color",
    val: gray2.alphaTo(0.6).stringHEX()
    },
    {
    var: "--popup-bg-color",
    val: str(gray1)
    }
    ]
    );
  9. zsviczian revised this gist Oct 17, 2022. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions readme.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,5 @@
    Requires [Excalidraw-Obsidian](https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/README.md) 1.7.25 or later.
    Switch to "Raw" (top right button) before copying the script to Obsidian.

    Watch this video:

  10. zsviczian revised this gist Oct 16, 2022. 1 changed file with 4 additions and 0 deletions.
    4 changes: 4 additions & 0 deletions readme.md
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,9 @@
    Requires [Excalidraw-Obsidian](https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/README.md) 1.7.25 or later.

    Watch this video:

    [![Thumbnail - Excalidraw Dynamic Styling (Custom) (1)](https://user-images.githubusercontent.com/14358394/196050310-ac96f9e9-0aaa-495c-b081-f3fca21a84d7.png)](https://youtu.be/LtR04fNTKTM)

    If you need more info on ColorMaster, watch this video as well:

    [![Thumbnail - ColorMaster Scripting (Custom)](https://user-images.githubusercontent.com/14358394/195988535-a133a9b9-d094-45ba-ba64-c994b9a1e0ef.png)](https://youtu.be/7gJDwNgQ6NU)
  11. zsviczian created this gist Oct 16, 2022.
    130 changes: 130 additions & 0 deletions Excalidraw Dynamic Styling.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,130 @@
    <%*
    /*
    ```javascript
    */
    const installStyleHook = () => {
    if(!window.ExcalidrawAutomate) return false;
    ExcalidrawAutomate.onCanvasColorChangeHook = (ea, view, color) => {
    const doc = view.ownerDocument;

    const dark = "#404040";
    const darker = "#202020";
    const light = "#d0d0d0";
    const lighter = "#f0f0f0";
    const step = 10;
    const mixRatio = 0.85;

    const cmBG = () => ea.getCM(color);

    const isDark = cmBG().isDark();

    const accent = () => {
    const s = doc.querySelector("body").style;
    return ea.getCM(`hsl(${s.getPropertyValue("--accent-h")},${
    s.getPropertyValue("--accent-s")},${s.getPropertyValue("--accent-l")})`).mix({color:isDark?dark:light, ratio:0.6});
    }

    const updateCSSClassVariable = (className, payload) => {
    for(stylesheet of doc.styleSheets) {
    for(rule of stylesheet.rules) {
    if (rule.selectorText !== className) continue;
    let cssText = rule.cssText;
    let changed = false;
    payload.forEach(pl => {
    const reg = new RegExp(`${pl.var}:\\s[^;]*`);
    if(cssText.match(reg)) {
    cssText = cssText.replace(reg,`${pl.var}: ${pl.val}`);
    changed = true;
    }
    });
    if(changed) {
    stylesheet.deleteRule(rule);
    stylesheet.insertRule(cssText);
    }
    }
    }
    }

    const str = (cm) => cm.stringHEX({alpha:false});

    const gray1 = cmBG().mix({color:isDark?darker:lighter, ratio:mixRatio});
    const gray2 = cmBG().mix({color:isDark?dark:light, ratio:mixRatio});
    const text = cmBG().mix({color:isDark?lighter:darker, ratio:mixRatio})

    updateCSSClassVariable (
    ".excalidraw",[
    {
    var: "--color-primary",
    val: str(accent())
    },
    {
    var: "--color-primary-darker",
    val: str(accent().darkerBy(step))
    },
    {
    var: "--color-primary-darkest",
    val: str(accent().darkerBy(step))
    },
    {
    var: "--button-gray-1",
    val: str(gray1)
    },
    {
    var: "--button-gray-2",
    val: str(gray2)
    },
    {
    var: "--input-border-color",
    val: str(gray1)
    },
    {
    var: "--input-bg-color",
    val: str(gray2)
    },
    {
    var: "--input-label-color",
    val: str(text)
    },
    {
    var: "--island-bg-color",
    val: gray2.alphaTo(0.85).stringHEX()
    },
    {
    var: "--icon-fill-color",
    val: str(text)
    },
    {
    var: "--text-primary-color",
    val: str(text)
    },
    {
    var: "--overlay-bg-color",
    val: gray2.alphaTo(0.6).stringHEX()
    }
    ]
    );
    };
    const view = app.workspace.activeLeaf?.view;
    if(view && view.getViewType() === "excalidraw") {
    if(!view.isLoaded || !view.excalidrawAPI) return true;
    ExcalidrawAutomate.onCanvasColorChangeHook(
    ExcalidrawAutomate,
    app.workspace.activeLeaf.view,
    view.excalidrawAPI.getAppState().viewBackgroundColor
    )
    }
    return true;
    }

    setTimeout(()=>{
    console.log("Installing Excalidraw style hook...");
    if(installStyleHook()) return;
    console.log("Failed to install style hook...");
    setTimeout(()=>{
    if(installStyleHook()) {
    console.log("Excalidraw style hook installed successfully");
    }
    console.log("Excalidraw style hook NOT installed");
    },10000);
    },5000);
    %>
    5 changes: 5 additions & 0 deletions readme.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,5 @@
    Watch this video:
    [![Thumbnail - Excalidraw Dynamic Styling (Custom) (1)](https://user-images.githubusercontent.com/14358394/196050310-ac96f9e9-0aaa-495c-b081-f3fca21a84d7.png)](https://youtu.be/LtR04fNTKTM)

    If you need more info on ColorMaster, watch this video as well:
    [![Thumbnail - ColorMaster Scripting (Custom)](https://user-images.githubusercontent.com/14358394/195988535-a133a9b9-d094-45ba-ba64-c994b9a1e0ef.png)](https://youtu.be/7gJDwNgQ6NU)