Skip to content

Commit 95b11c9

Browse files
docs structure
1 parent 201658f commit 95b11c9

File tree

8 files changed

+137
-0
lines changed

8 files changed

+137
-0
lines changed

docs/assets/custom.css

Whitespace-only changes.

docs/examples/basic.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Basic Graph Examples
2+
3+
This page demonstrates how to embed interactive graphs generated by `nx-vis-visualizer`
4+
directly into the documentation.
5+
6+
## Example 1: Simple Cycle Graph

docs/examples/customization.md

Whitespace-only changes.

docs/examples/directed.md

Whitespace-only changes.

docs/index.md

Whitespace-only changes.

docs/installation.md

Whitespace-only changes.

docs/main.py

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# docs/main.py
2+
import copy
3+
import json
4+
import os
5+
import uuid
6+
from html import escape # For escaping graph_title in the iframe HTML
7+
from typing import Any
8+
9+
import networkx as nx
10+
11+
from nx_vis_visualizer import DEFAULT_VIS_OPTIONS, nx_to_vis
12+
from nx_vis_visualizer.core import (
13+
_deep_merge_dicts, # Assuming this is still needed
14+
)
15+
16+
# Ensure the output directory for graphs exists
17+
GENERATED_GRAPHS_DIR_NAME: str = "generated_graphs"
18+
# Path relative to the docs directory
19+
DOCS_ASSETS_GRAPHS_DIR: str = os.path.join("assets", GENERATED_GRAPHS_DIR_NAME)
20+
21+
22+
# The 'env' object is specific to mkdocs-macros-plugin.
23+
def define_env(env: Any) -> None:
24+
"""
25+
Hook for defining variables, macros, and filters for MkDocs.
26+
`env.project_dir` is the root of the MkDocs project (where mkdocs.yml is).
27+
`env.conf['docs_dir']` is the path to the docs directory, relative to project_dir.
28+
"""
29+
abs_output_dir: str = os.path.join(
30+
env.project_dir, env.conf["docs_dir"], DOCS_ASSETS_GRAPHS_DIR
31+
)
32+
os.makedirs(abs_output_dir, exist_ok=True)
33+
34+
@env.macro # type: ignore[misc]
35+
def embed_interactive_graph(
36+
nx_graph_code: str,
37+
vis_options_json_str: str = "{}",
38+
iframe_height: str = "500px",
39+
graph_title: str = "Interactive Graph",
40+
) -> str: # Macros typically return HTML strings
41+
"""
42+
Generates a NetworkX graph from Python code, saves it as an HTML file,
43+
and returns an iframe to embed it.
44+
"""
45+
local_scope: dict[str, Any] = {"nx": nx, "G": None}
46+
graph: nx.Graph | None = ( # type: ignore[type-arg]
47+
None
48+
)
49+
50+
try:
51+
# Provide globals for exec, including nx
52+
exec(nx_graph_code, {"nx": nx}, local_scope)
53+
graph_candidate = local_scope.get("G")
54+
if isinstance(
55+
graph_candidate, nx.Graph
56+
): # Check if it's a NetworkX graph instance
57+
graph = graph_candidate # Now graph is known to be nx.Graph
58+
else:
59+
return (
60+
"<p style='color:red; font-weight:bold;'>"
61+
"Error: Provided code did not create a NetworkX graph "
62+
"in variable 'G'.</p>"
63+
)
64+
except Exception as e:
65+
import traceback
66+
67+
print(f"Error executing graph code: {traceback.format_exc()}")
68+
return (
69+
f"<p style='color:red; font-weight:bold;'>"
70+
f"Error executing graph generation code: {escape(str(e))}</p>"
71+
)
72+
73+
user_vis_options: dict[str, Any]
74+
try:
75+
user_vis_options = json.loads(vis_options_json_str)
76+
except json.JSONDecodeError as e:
77+
return (
78+
f"<p style='color:red; font-weight:bold;'>"
79+
f"Error decoding vis_options_json_str: {escape(str(e))}</p>"
80+
f"<pre>{escape(vis_options_json_str)}</pre>"
81+
)
82+
83+
final_vis_options: dict[str, Any] = copy.deepcopy(DEFAULT_VIS_OPTIONS)
84+
_deep_merge_dicts(user_vis_options, final_vis_options)
85+
86+
graph_html_filename: str = f"graph_{uuid.uuid4().hex[:10]}.html"
87+
graph_html_save_path: str = os.path.join(
88+
abs_output_dir, graph_html_filename
89+
)
90+
91+
nx_to_vis(
92+
graph,
93+
output_filename=graph_html_save_path,
94+
html_title=graph_title,
95+
vis_options=final_vis_options,
96+
show_browser=False,
97+
graph_width="100%",
98+
graph_height="100%",
99+
)
100+
101+
path_to_graph_in_docs: str = os.path.join(
102+
DOCS_ASSETS_GRAPHS_DIR, graph_html_filename
103+
)
104+
105+
# Assuming env.filters['url'] exists and is callable
106+
iframe_src: str = env.filters["url"](path_to_graph_in_docs)
107+
escaped_graph_title: str = escape(
108+
graph_title
109+
) # Escape title for HTML context
110+
111+
return f"""
112+
<div class="interactive-graph-wrapper" style="margin-bottom: 1.5em; padding: 1em; border: 1px solid #e0e0e0; border-radius: 4px; background-color: #f9f9f9;">
113+
<h4 style="margin-top: 0; margin-bottom: 0.5em; font-size: 1.1em;">{escaped_graph_title}</h4>
114+
<iframe src="{iframe_src}"
115+
width="100%"
116+
height="{iframe_height}"
117+
style="border: 1px solid #ccc; max-width: 100%; display: block;"
118+
sandbox="allow-scripts allow-same-origin"
119+
loading="lazy">
120+
Your browser does not support iframes. Please update your browser.
121+
</iframe>
122+
</div>
123+
"""
124+
125+
@env.macro # type: ignore[misc]
126+
def show_code_block(
127+
code_string: str, language: str = "python"
128+
) -> str: # Added return type
129+
"""Displays a code block, typically for showing the graph generation code."""
130+
escaped_code: str = code_string.strip()
131+
return f"```{language}\n{escaped_code}\n```"

docs/usage.md

Whitespace-only changes.

0 commit comments

Comments
 (0)