custom_components/bahmcloud_store/panel/panel.js aktualisiert
This commit is contained in:
@@ -21,7 +21,7 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
|
||||
this._readmeLoading = false;
|
||||
this._readmeText = null;
|
||||
this._readmeHtml = null; // backend may provide; we don't rely on it anymore
|
||||
this._readmeHtml = null; // backend may provide; client renderer does not rely on it
|
||||
this._readmeError = null;
|
||||
}
|
||||
|
||||
@@ -331,10 +331,17 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
details{ margin-top: 10px; }
|
||||
summary{ cursor:pointer; color: var(--bcs-accent); font-weight: 900; }
|
||||
|
||||
/* Pretty Markdown container spacing (ha-markdown renders inside) */
|
||||
/* Pretty Markdown container */
|
||||
.md { line-height: 1.65; font-size: 14px; }
|
||||
.md :is(h1,h2,h3){ margin: 18px 0 10px; }
|
||||
.md :is(p,ul,ol,pre,blockquote,table){ margin: 10px 0; }
|
||||
.md pre { overflow:auto; padding:12px; border-radius:14px; border:1px solid var(--divider-color); }
|
||||
.md code { padding:2px 6px; border-radius:8px; border:1px solid var(--divider-color); }
|
||||
.md blockquote { border-left:4px solid var(--bcs-accent); padding:8px 12px; border-radius:12px;
|
||||
background: color-mix(in srgb, var(--bcs-accent) 8%, var(--card-background-color)); }
|
||||
.md table{ width:100%; border-collapse: collapse; }
|
||||
.md th,.md td{ border:1px solid var(--divider-color); padding:8px; text-align:left; }
|
||||
.md img{ max-width:100%; height:auto; border-radius:12px; }
|
||||
</style>
|
||||
|
||||
<div class="mobilebar">
|
||||
@@ -659,45 +666,79 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
`;
|
||||
}
|
||||
|
||||
_mdToHtml(markdown) {
|
||||
const md = String(markdown || "");
|
||||
if (!md.trim()) return "";
|
||||
|
||||
// Prefer HA's frontend libs if present
|
||||
const markedObj = window.marked;
|
||||
const domPurify = window.DOMPurify;
|
||||
|
||||
let html = "";
|
||||
|
||||
try {
|
||||
// marked can be a function or an object with parse()
|
||||
if (markedObj && typeof markedObj.parse === "function") {
|
||||
html = markedObj.parse(md, { breaks: true, gfm: true });
|
||||
} else if (typeof markedObj === "function") {
|
||||
html = markedObj(md);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
} catch (_) {
|
||||
return "";
|
||||
}
|
||||
|
||||
try {
|
||||
if (domPurify && typeof domPurify.sanitize === "function") {
|
||||
html = domPurify.sanitize(html);
|
||||
}
|
||||
} catch (_) {}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
_postprocessRenderedMarkdown(container) {
|
||||
if (!container) return;
|
||||
|
||||
// Make links open in new tab
|
||||
try {
|
||||
const links = container.querySelectorAll("a[href]");
|
||||
links.forEach((a) => {
|
||||
a.setAttribute("target", "_blank");
|
||||
a.setAttribute("rel", "noreferrer noopener");
|
||||
});
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
_wireDetail() {
|
||||
const root = this.shadowRoot;
|
||||
const mount = root.getElementById("readmePretty");
|
||||
if (!mount) return;
|
||||
|
||||
// Always prefer HA's frontend markdown renderer to get a professional look.
|
||||
// This uses the same renderer concept as HA's Markdown card (Marked.js). :contentReference[oaicite:1]{index=1}
|
||||
if (this._readmeText) {
|
||||
try {
|
||||
mount.innerHTML = "";
|
||||
const html = this._mdToHtml(this._readmeText);
|
||||
|
||||
const el = document.createElement("ha-markdown");
|
||||
// Ensure it has access to HA context (themes, link handling, etc.)
|
||||
el.hass = this._hass;
|
||||
|
||||
// Different HA versions use either "content" or "markdown" internally;
|
||||
// setting both is harmless and maximizes compatibility.
|
||||
el.content = this._readmeText;
|
||||
el.markdown = this._readmeText;
|
||||
|
||||
// Some versions support these flags; safe to set even if ignored.
|
||||
el.allowHtml = false;
|
||||
el.breaks = true;
|
||||
|
||||
mount.appendChild(el);
|
||||
if (html) {
|
||||
mount.innerHTML = html;
|
||||
this._postprocessRenderedMarkdown(mount);
|
||||
return;
|
||||
} catch (_) {
|
||||
// fall through to html/raw fallback
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: if backend provided sanitized HTML, use it
|
||||
if (this._readmeHtml) {
|
||||
mount.innerHTML = this._readmeHtml;
|
||||
// Fallback: if backend provided sanitized HTML, use it
|
||||
if (this._readmeHtml) {
|
||||
mount.innerHTML = this._readmeHtml;
|
||||
this._postprocessRenderedMarkdown(mount);
|
||||
return;
|
||||
}
|
||||
|
||||
// Last resort
|
||||
mount.innerHTML = `<div class="muted">Markdown renderer not available on this client. Use “Show raw Markdown”.</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
// Last resort: show nothing here (raw is still available via details)
|
||||
mount.innerHTML = `<div class="muted">Unable to render Markdown on this client.</div>`;
|
||||
// No readme text loaded
|
||||
mount.innerHTML = "";
|
||||
}
|
||||
|
||||
_renderFabs() {
|
||||
|
||||
Reference in New Issue
Block a user