Solved link bug with subitems

This commit is contained in:
Kevin Veen-Birkenbach 2025-01-10 13:56:37 +01:00
parent dc058d16df
commit 28cd3e1f2f
3 changed files with 89 additions and 75 deletions

View File

@ -171,25 +171,7 @@ navigation:
url: mailto:kevin@veen.world url: mailto:kevin@veen.world
identifier: kevin@veen.world identifier: kevin@veen.world
alternatives: alternatives:
- link: navigation.header.contact.matrix - link: navigation.header.contact.messenger.matrix
- name: Matrix
description: Chat with me on Matrix
icon:
class: fa-solid fa-cubes
identifier: "@kevinveenbirkenbach:veen.world"
info: |
#### Why Use Matrix?
Matrix is a secure, decentralized communication platform that ensures privacy and control over your data. Learn more about [Matrix](https://matrix.org/).
#### Privacy and Security
End-to-end encryption keeps your conversations private and secure.
#### Decentralized and Open
Matrix's federated network means you can host your own server or use any provider while staying connected.
#### A Movement for Digital Freedom
By using Matrix, you support open, transparent, and secure communication.
- name: Mobile - name: Mobile
description: Call me description: Call me
icon: icon:
@ -215,40 +197,61 @@ navigation:
#### Stand for Security #### Stand for Security
Using PGP is more than a tool—it's a statement about valuing freedom, privacy, and the security of digital communication. Explore the principles of secure communication with [privacy guides](https://privacyguides.org/). Using PGP is more than a tool—it's a statement about valuing freedom, privacy, and the security of digital communication. Explore the principles of secure communication with [privacy guides](https://privacyguides.org/).
- name: Messenger
description: Social and developer networks
icon:
class: fa-brands fa-meta
subitems:
- name: Matrix
description: Chat with me on Matrix
icon:
class: fa-solid fa-cubes
identifier: "@kevinveenbirkenbach:veen.world"
info: |
#### Why Use Matrix?
Matrix is a secure, decentralized communication platform that ensures privacy and control over your data. Learn more about [Matrix](https://matrix.org/).
- name: Signal #### Privacy and Security
description: Message me on Signal End-to-end encryption keeps your conversations private and secure.
icon:
class: fa-brands fa-signal-messenger #### Decentralized and Open
identifier: "+491781798023" Matrix's federated network means you can host your own server or use any provider while staying connected.
warning: Signal is not hosted by me!
alternatives: #### A Movement for Digital Freedom
- link: navigation.header.contact.matrix By using Matrix, you support open, transparent, and secure communication.
- name: Telegram - name: Signal
description: Message me on Telegram description: Message me on Signal
icon: icon:
class: fa-brands fa-telegram class: fa-brands fa-signal-messenger
target: _blank identifier: "+491781798023"
url: https://t.me/kevinveenbirkenbach warning: Signal is not hosted by me!
identifier: kevinveenbirkenbach alternatives:
warning: Telegram is not hosted by me! - link: navigation.header.contact.messenger.matrix
alternatives: - name: Telegram
- link: navigation.header.contact.matrix description: Message me on Telegram
- name: WhatsApp icon:
description: Chat with me on WhatsApp class: fa-brands fa-telegram
icon: target: _blank
class: fa-brands fa-whatsapp url: https://t.me/kevinveenbirkenbach
url: https://wa.me/491781798023 identifier: kevinveenbirkenbach
identifier: "+491781798023" warning: Telegram is not hosted by me!
warning: Using software and platforms from the Meta corporation (e.g., Facebook, Instagram, WhatsApp) may compromise your data privacy and digital freedom due to centralized control, extensive data collection practices, and inconsistent moderation policies. These platforms often fail to adequately address harmful content, misinformation, and abuse. alternatives:
info: Consider using decentralized and privacy-respecting alternatives to maintain control over your data, improve security, and foster healthier online interactions. - link: navigation.header.contact.messenger.matrix
alternatives: - name: WhatsApp
- link: navigation.header.contact.matrix description: Chat with me on WhatsApp
- link: navigation.header.contact.signal icon:
- link: navigation.header.contact.telegram class: fa-brands fa-whatsapp
url: https://wa.me/491781798023
identifier: "+491781798023"
warning: Using software and platforms from the Meta corporation (e.g., Facebook, Instagram, WhatsApp) may compromise your data privacy and digital freedom due to centralized control, extensive data collection practices, and inconsistent moderation policies. These platforms often fail to adequately address harmful content, misinformation, and abuse.
info: Consider using decentralized and privacy-respecting alternatives to maintain control over your data, improve security, and foster healthier online interactions.
alternatives:
- link: navigation.header.contact.messenger.matrix
- link: navigation.header.contact.messenger.signal
- link: navigation.header.contact.messenger.telegram
footer: footer:
- name: External Accounts - name: Accounts
description: Me on other plattforms description: Me on other plattforms
icon: icon:
class: fa-solid fa-external-link-alt class: fa-solid fa-external-link-alt
@ -269,14 +272,7 @@ navigation:
icon: icon:
class: fa-brands fa-facebook class: fa-brands fa-facebook
url: https://www.facebook.com/kevinveenbirkenbach url: https://www.facebook.com/kevinveenbirkenbach
- name: Communication - link: navigation.header.contact.messenger
description: Social and developer networks
icon:
class: fa-brands fa-meta
subitems:
- link: navigation.header.contact.whatsapp
- link: navigation.header.contact.signal
- link: navigation.header.contact.telegram
- name: Carreer Profiles - name: Carreer Profiles
icon: icon:
class: fa-solid fa-user-tie class: fa-solid fa-user-tie

View File

@ -4,7 +4,11 @@
{% if subitem.subitems %} {% if subitem.subitems %}
<li class="dropdown-submenu position-relative"> <li class="dropdown-submenu position-relative">
<a class="dropdown-item dropdown-toggle" href="#" title="{{ subitem.description }}"> <a class="dropdown-item dropdown-toggle" href="#" title="{{ subitem.description }}">
<i class="{{ subitem.icon.class }}"></i> {{ subitem.name }} {% if subitem.icon is defined and subitem.icon.class is defined %}
<i class="{{ subitem.icon.class }}"></i> {{ subitem.name }}
{% else %}
<p>Missing icon in subitem: {{ subitem }}</p>
{% endif %}
</a> </a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
{{ render_subitems(subitem.subitems) }} {{ render_subitems(subitem.subitems) }}

View File

@ -1,3 +1,4 @@
from pprint import pprint
class ConfigurationResolver: class ConfigurationResolver:
""" """
A class to resolve `link` entries in a nested configuration structure. A class to resolve `link` entries in a nested configuration structure.
@ -21,7 +22,10 @@ class ConfigurationResolver:
for key, value in list(current_config.items()): for key, value in list(current_config.items()):
if key == "link": if key == "link":
try: try:
target = self._find_entry(root_config, value.lower()) target = self._find_entry(root_config, value.lower(), True)
if isinstance(target, list) and len(target) > 2:
target = self._find_entry(root_config, value.lower(), False)
current_config.clear() current_config.clear()
current_config.update(target) current_config.update(target)
except Exception as e: except Exception as e:
@ -35,7 +39,18 @@ class ConfigurationResolver:
for item in current_config: for item in current_config:
self._recursive_resolve(item, root_config) self._recursive_resolve(item, root_config)
def _find_entry(self, config, path): def _get_subitems(self,current):
if isinstance(current, dict) and ("subitems" in current and current["subitems"]):
current = current["subitems"]
return current
def _find_by_name(self,current, part):
return next(
(item for item in current if isinstance(item, dict) and item.get("name", "").lower() == part),
None
)
def _find_entry(self, config, path, subitems):
""" """
Finds an entry in the configuration by a dot-separated path. Finds an entry in the configuration by a dot-separated path.
Supports both dictionaries and lists with `subitems` navigation. Supports both dictionaries and lists with `subitems` navigation.
@ -45,10 +60,7 @@ class ConfigurationResolver:
for part in parts: for part in parts:
if isinstance(current, list): if isinstance(current, list):
# Look for a matching name in the list # Look for a matching name in the list
found = next( found = self._find_by_name(current,part)
(item for item in current if isinstance(item, dict) and item.get("name", "").lower() == part),
None
)
if found: if found:
print( print(
f"Matching entry for '{part}' in list. Path so far: {' > '.join(parts[:parts.index(part)+1])}. " f"Matching entry for '{part}' in list. Path so far: {' > '.join(parts[:parts.index(part)+1])}. "
@ -64,20 +76,22 @@ class ConfigurationResolver:
# Case-insensitive dictionary lookup # Case-insensitive dictionary lookup
key = next((k for k in current if k.lower() == part), None) key = next((k for k in current if k.lower() == part), None)
if key is None: if key is None:
raise KeyError( current = self._find_by_name(current["subitems"],part)
f"Key '{part}' not found in dictionary. Path so far: {' > '.join(parts[:parts.index(part)+1])}. " if not current:
f"Current dictionary: {current}" raise KeyError(
) f"Key '{part}' not found in dictionary. Path so far: {' > '.join(parts[:parts.index(part)+1])}. "
current = current[key] f"Current dictionary: {current}"
)
else:
current = current[key]
else: else:
raise ValueError( raise ValueError(
f"Invalid path segment '{part}'. Current type: {type(current)}. " f"Invalid path segment '{part}'. Current type: {type(current)}. "
f"Path so far: {' > '.join(parts[:parts.index(part)+1])}" f"Path so far: {' > '.join(parts[:parts.index(part)+1])}"
) )
if subitems:
# Navigate into `subitems` if present current = self._get_subitems(current)
if isinstance(current, dict) and ("subitems" in current and current["subitems"]):
current = current["subitems"]
return current return current