Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: Configure colors / dark theme / theme that works with both light and dark schemes #100

Open
pawamoy opened this issue Jul 12, 2024 · 3 comments

Comments

@pawamoy
Copy link

pawamoy commented Jul 12, 2024

Hey, thanks for the nice project!

I was wondering if you'd consider adding options to customize colors. The final use-case for me is to display call graphs generated with Code2Flow in pages that can be toggled between light and dark color schemes. If I set the background to transparent instead of white, the dark parts of the graph are then almost impossible to see (black arrows, black dot borders, black text).

If not, any guidance at how to achieve this through programmatic use would be great, too! Looking at the code, it looks like I can probably duplicate most of the code2flow function, to alter file_groups, all_nodes and edges, which probably hardcode their colors?

@pawamoy
Copy link
Author

pawamoy commented Jul 12, 2024

Or maybe I should simply use CSS, since I'm injecting the call graphs as SVG in HTML pages. EDIT: seems like it would be hard since there's no way to easily select relevant objects (black arrows for example).

@pawamoy
Copy link
Author

pawamoy commented Jul 12, 2024

OK looks like I can change the values of TRUNK_COLOR, LEAF_COLOR, EDGE_COLORS and NODE_COLOR in code2flow/model.py.

@pawamoy
Copy link
Author

pawamoy commented Jul 12, 2024

OK here's my code for future readers:

import subprocess
from io import StringIO

from code2flow import code2flow, model

model.TRUNK_COLOR = "#fca311"
model.LEAF_COLOR = "#98c1d9"
model.EDGE_COLORS = ["#b8b8ff"] * 8
model.NODE_COLOR = "#e5e5e5"


def _render_call_graph(module: Path) -> None:
    buffer = StringIO()
    code2flow(str(module), buffer)
    svg = subprocess.check_output(["dot", "-Tsvg"], input=buffer.getvalue(), text=True)  # noqa: S603, S607
    if 'class="node"' not in svg:
        print("")
    else:
        print(f'<div class="call-graph">{svg}</div>')

...

This _render_call_graph is actually used in another code block that is inserted directly in Markdown pages and executed by Markdown Exec. Pages are built with MkDocs and Material for MkDocs.

```python exec="1" idprefix="internal-" session="comment_blocks"
--8<-- "scripts/gen_internal_api.py"

render_internal_api(heading_level=4)
```

I customize CSS of the SVG elements:

<style>
    .call-graph svg {
        /* min-width: 100%; */
        min-height: 200px;
    }
    .graph > polygon {
        fill-opacity: 0.0;
    }

    [data-md-color-scheme="default"] .cluster > polygon {
        stroke: black;
    }
    [data-md-color-scheme="default"] .cluster > text {
        fill: black;
    }

    [data-md-color-scheme="slate"] .cluster > polygon {
        stroke: white;
    }
    [data-md-color-scheme="slate"] .cluster > text {
        fill: white;
    }
</style>

...and even make the SVG zoomable and pannable with the JS library of the same name: https://github.com/bumbu/svg-pan-zoom.

<script>
    document.addEventListener("DOMContentLoaded", function(){
        const callGraphs = document.getElementsByClassName("call-graph");
        for (let i = 0; i < callGraphs.length; i++) {
            if (!callGraphs[i].firstElementChild.id) {
                callGraphs[i].firstElementChild.id = `call-graph-${i}`
            }
            svgPanZoom(`#${callGraphs[i].firstElementChild.id}`, {});
        }
    });
</script>

View from afar:

afarview

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant