diff --git a/custom_components/bahmcloud_store/panel/panel.js b/custom_components/bahmcloud_store/panel/panel.js index 3b39102..1c7cc29 100644 --- a/custom_components/bahmcloud_store/panel/panel.js +++ b/custom_components/bahmcloud_store/panel/panel.js @@ -22,7 +22,6 @@ class BahmcloudStorePanel extends HTMLElement { this._readmeText = null; this._readmeError = null; - // Prevent multiple concurrent markdown mounts this._mdMountToken = 0; } @@ -339,8 +338,14 @@ class BahmcloudStorePanel extends HTMLElement { details{ margin-top: 10px; } summary{ cursor:pointer; color: var(--bcs-accent); font-weight: 800; } - /* Make HA markdown look nice inside our card */ - ha-markdown{ + /* Make the embedded Lovelace markdown card blend into our UI */ + .mdwrap{ + border: 1px solid var(--divider-color); + border-radius: 14px; + overflow: hidden; + background: var(--card-background-color); + } + .mdwrap > *{ display:block; } @@ -660,57 +665,70 @@ class BahmcloudStorePanel extends HTMLElement { } async _mountPrettyMarkdown(container, markdown) { - // token prevents race conditions when switching repos fast const token = ++this._mdMountToken; - container.innerHTML = ""; - // If user switched views/repo while we were waiting - const stillValid = () => token === this._mdMountToken && this._view === "detail" && !!this._readmeText; + const stillValid = () => + token === this._mdMountToken && + this._view === "detail" && + typeof this._readmeText === "string" && + this._readmeText.trim().length > 0; - // Wait until HA registers the component + // 1) BEST: Use Lovelace markdown card (hui-markdown-card) + try { + await customElements.whenDefined("hui-markdown-card"); + if (!stillValid()) return; + + const wrap = document.createElement("div"); + wrap.className = "mdwrap"; + container.appendChild(wrap); + + const card = document.createElement("hui-markdown-card"); + wrap.appendChild(card); + + // Lovelace cards use setConfig + hass + if (typeof card.setConfig === "function") { + card.setConfig({ + type: "markdown", + content: markdown, + }); + } else { + // fallback property name (just in case) + card.config = { type: "markdown", content: markdown }; + } + + // Provide hass after config + try { card.hass = this._hass; } catch (_) {} + + // Nudge a render pass + await new Promise((resolve) => requestAnimationFrame(resolve)); + if (!stillValid()) return; + try { card.hass = this._hass; } catch (_) {} + + return; + } catch (_) { + // Continue to next fallback + } + + // 2) Fallback: ha-markdown try { await customElements.whenDefined("ha-markdown"); - } catch (_) { - // ignored - } - if (!stillValid()) return; + if (!stillValid()) return; - // Create markdown element - let el; - try { - el = document.createElement("ha-markdown"); - } catch (_) { - el = null; - } - - // If creation failed, fallback to plain pre - if (!el) { - const pre = document.createElement("pre"); - pre.className = "readme"; - pre.textContent = markdown; - container.appendChild(pre); + const el = document.createElement("ha-markdown"); + container.appendChild(el); + try { el.hass = this._hass; } catch (_) {} + try { el.content = markdown; } catch (_) { + try { el.markdown = markdown; } catch (_) {} + } return; - } + } catch (_) {} - // Attach first (some HA internals react after connection) - container.appendChild(el); - - // Set hass + content - try { el.hass = this._hass; } catch (_) {} - try { el.content = markdown; } catch (_) { - // some builds used `markdown` property in the past - try { el.markdown = markdown; } catch (_) {} - } - - // Nudge render (some builds need a microtask/frame after setting properties) - await new Promise((resolve) => requestAnimationFrame(resolve)); - if (!stillValid()) return; - - try { el.hass = this._hass; } catch (_) {} - try { el.content = markdown; } catch (_) { - try { el.markdown = markdown; } catch (_) {} - } + // 3) Last fallback: plain text + const pre = document.createElement("pre"); + pre.className = "readme"; + pre.textContent = markdown; + container.appendChild(pre); } _wireDetail() { @@ -719,10 +737,8 @@ class BahmcloudStorePanel extends HTMLElement { if (!container) return; container.innerHTML = ""; - if (!this._readmeText) return; - // Always try pretty markdown; raw fallback is already available in
this._mountPrettyMarkdown(container, this._readmeText); }