From 90a9c4c5504d7d1a62ae9a2cd9a2fb18d6b99f96 Mon Sep 17 00:00:00 2001 From: benomahony Date: Wed, 20 May 2026 17:47:53 +0100 Subject: [PATCH 1/3] fix: omit browser/dynamic-variant attrs when at defaults The web component validates `browser` with ZodMiniBoolean. HTML attributes are always strings, so `getAttribute("browser")` returns "true" (string), which ZodMini rejects. `safeParse` fails and the component falls back to `{viewId: "index"}`, causing every diagram on the page to render the same view. Omitting the attribute when it equals the default means `getAttribute` returns null, which the component converts to undefined via `?? void 0`, allowing Zod's own default to apply correctly. Co-Authored-By: Claude Sonnet 4.6 --- mkdocs_likec4/parser.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/mkdocs_likec4/parser.py b/mkdocs_likec4/parser.py index bb06adb..51bb95e 100644 --- a/mkdocs_likec4/parser.py +++ b/mkdocs_likec4/parser.py @@ -70,7 +70,9 @@ def to_html(cls, opts: ViewOptions) -> str: ) tag = f"{opts.project.lower()}-view" if valid_project else "likec4-view" - return ( - f'<{tag} view-id="{escape(opts.view_id, quote=True)}" ' - f'browser="{opts.browser}" dynamic-variant="{opts.dynamic_variant}">' - ) + attrs = f'view-id="{escape(opts.view_id, quote=True)}"' + if opts.browser != "true": + attrs += f' browser="{opts.browser}"' + if opts.dynamic_variant != "diagram": + attrs += f' dynamic-variant="{opts.dynamic_variant}"' + return f'<{tag} {attrs}>' From 675120c91d4a74f2ca899e2bd462af546dad98b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20H=C3=A4usler?= Date: Fri, 22 May 2026 00:12:52 +0200 Subject: [PATCH 2/3] test: cover default-omission cases in to_html --- tests/test_parser.py | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/tests/test_parser.py b/tests/test_parser.py index 516768b..863fd95 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -251,28 +251,19 @@ def test_basic_html_output(self): """Test basic HTML output without project.""" opts = ViewOptions(view_id="my-view") html = LikeC4Parser.to_html(opts) - assert ( - html - == '' - ) + assert html == '' def test_html_with_project(self): """Test HTML output with valid project.""" opts = ViewOptions(view_id="my-view", project="myproject") html = LikeC4Parser.to_html(opts) - assert ( - html - == '' - ) + assert html == '' def test_html_with_uppercase_project(self): """Test HTML output with uppercase project (should be lowercased).""" opts = ViewOptions(view_id="my-view", project="MyProject") html = LikeC4Parser.to_html(opts) - assert ( - html - == '' - ) + assert html == '' def test_html_with_custom_options(self): """Test HTML output with custom options.""" @@ -288,14 +279,25 @@ def test_html_with_custom_options(self): == '' ) + def test_html_omits_only_default_browser(self): + """Only dynamic-variant is emitted when browser is at default.""" + opts = ViewOptions(view_id="v", dynamic_variant="sequence") + html = LikeC4Parser.to_html(opts) + assert ( + html == '' + ) + + def test_html_omits_only_default_dynamic_variant(self): + """Only browser is emitted when dynamic-variant is at default.""" + opts = ViewOptions(view_id="v", browser="false") + html = LikeC4Parser.to_html(opts) + assert html == '' + def test_html_with_invalid_project_falls_back(self): """Test HTML output with invalid project name falls back to likec4-view.""" opts = ViewOptions(view_id="my-view", project="123invalid") html = LikeC4Parser.to_html(opts) - assert ( - html - == '' - ) + assert html == '' def test_html_escapes_invalid_view_id_with_quotes(self): """Test that invalid view ID with quotes is escaped to prevent XSS.""" From 1ff2cb5f4a2653f047117306f4b0a65cf2fa1442 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20H=C3=A4usler?= Date: Fri, 22 May 2026 00:12:52 +0200 Subject: [PATCH 3/3] style: apply ruff format to parser.py --- mkdocs_likec4/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs_likec4/parser.py b/mkdocs_likec4/parser.py index 51bb95e..bb4abb0 100644 --- a/mkdocs_likec4/parser.py +++ b/mkdocs_likec4/parser.py @@ -75,4 +75,4 @@ def to_html(cls, opts: ViewOptions) -> str: attrs += f' browser="{opts.browser}"' if opts.dynamic_variant != "diagram": attrs += f' dynamic-variant="{opts.dynamic_variant}"' - return f'<{tag} {attrs}>' + return f"<{tag} {attrs}>"