Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions d3fendtools/as_mermaid/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ class RDF2Mermaid:
K8S.Namespace,
K8S.Registry,
K8S.Application,
K8S.Service,
# DC are groups.
K8S.DeploymentConfig,
K8S.Deployment,
Expand Down Expand Up @@ -333,11 +334,11 @@ def render(self):
return ret

@staticmethod
def create_tree(tree):
def create_tree(tree: dict):
"""Create a tree of subgraphs according to mermaid syntax."""
rendered = set()

def _render_tree(parent, data):
def _render_tree(parent, data, is_namespace=False):
label = data.get("label") or ""
parent_type = data.get("type")
children = data.get("children") or []
Expand All @@ -352,7 +353,7 @@ def _render_tree(parent, data):
continue
if child == parent:
continue
if parent_type == K8S.Namespace:
if (is_namespace, parent_type) == (False, K8S.Namespace):

Copilot AI Jun 11, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The tuple comparison for namespace handling is non-intuitive; consider rewriting as if not is_namespace and parent_type == K8S.Namespace to express intent more clearly.

Suggested change
if (is_namespace, parent_type) == (False, K8S.Namespace):
if not is_namespace and parent_type == K8S.Namespace:

Copilot uses AI. Check for mistakes.
# Namespace should be processed last.
# Deployment* and Service* should be processed
# under Application.
Expand Down Expand Up @@ -402,5 +403,7 @@ def _render_tree(parent, data):
tree_namespace.append((parent, data))
continue
yield from _render_tree(parent, data)

# Render namespaces last.
for parent, data in tree_namespace:
yield from _render_tree(parent, data)
yield from _render_tree(parent, data, is_namespace=True)
4 changes: 3 additions & 1 deletion d3fendtools/as_mermaid/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@

@click.command()
@click.argument("files", nargs=-1, type=click.Path(exists=True))
@click.option("--output", "-o", help="Output markdown file")
@click.option("--output", "-o", required=True, help="Output markdown file")
def main(files, output):
if not files:
raise click.UsageError("At least one file is required")
output_md = Path(output)
resource_paths = []
for file in files:
Expand Down
3 changes: 3 additions & 0 deletions d3fendtools/kuberdf/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,9 @@ def __init__(self, manifest: dict | None = None, ns: str = None) -> None:
self.kind = manifest["kind"]
self.metadata = manifest["metadata"]
self.name = self.metadata["name"]
from urllib.parse import quote

Copilot AI Jun 11, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider moving the urllib.parse.quote import to the top of the module to avoid repeated imports inside init and improve readability.

Suggested change
from urllib.parse import quote

Copilot uses AI. Check for mistakes.

self.name = quote(self.name, safe="")
self.namespace = manifest["metadata"].get("namespace", ns or "default")
self.ns = URIRef(f"https://k8s.local/{self.namespace}")
self.spec = manifest.get("spec", {})
Expand Down
23 changes: 21 additions & 2 deletions docs/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,28 @@
try:
import js
from pyodide.ffi import create_proxy
from pyscript import Element
except ImportError:
pass

log = logging.getLogger(__name__)


class Element:
"""Element class to access the DOM element with id `id_`."""

def __init__(self, id_: str):
self.id_ = id_
self.element = js.document.getElementById(id_)

def write(self, text):
"""Write text to the element."""
self.element.innerHTML = text

def clear(self):
"""Clear the element."""
self.element.innerHTML = ""


HEADERS = ["node", "relation", "artifact", "technique"]

flip_mermaid = mermaidrdf.flip_mermaid
Expand Down Expand Up @@ -223,7 +240,9 @@ def _copy_text_to_clipboard(text):

def event_listener(element_id, event_type):
def decorator(callback):
Element(element_id).element.addEventListener(event_type, create_proxy(callback))
js.document.getElementById(element_id).addEventListener(
event_type, create_proxy(callback)
)

return decorator

Expand Down
8 changes: 6 additions & 2 deletions docs/mermaid.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<html>
<head>
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
<link rel="stylesheet" href="https://pyscript.net/releases/2025.3.1/core.css" />
<script type="module" src="https://pyscript.net/releases/2025.3.1/core.js"></script>
<py-config type="toml">
terminal = false
packages = [
Expand Down Expand Up @@ -306,13 +306,16 @@ <h4>Open Source</h4>
# log.info(f"{pyodide_js.version= }")
from pyodide.ffi import create_proxy
import js

from app import Element

Copilot AI Jun 11, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Consider consolidating the import of Element and the import of the app module: you could reference app.Element instead of importing Element separately to reduce redundancy.

Suggested change
from app import Element

Copilot uses AI. Check for mistakes.
from pathlib import Path

from time import time
import re
import html
import rdflib


# Import local application.
import app

Expand All @@ -332,6 +335,7 @@ <h4>Open Source</h4>
"strip_prefix": True, # "urn:k8s:"
}


ontology = app.initialize_graph(["static/ontology.ttl","static/d3fend-short.ttl"])
# Publish information in the global namespace
# to be accessible from the console.
Expand Down
Loading