dashboard: render markdown file previews in the side panel
clicking a .md / .markdown path reference now opens a marked-rendered view in the slide-in panel instead of raw text; other files stay raw in a <pre>. serves the vendored marked bundle at /static/marked.js and scopes a .md stylesheet to the panel body.
This commit is contained in:
parent
f13c3dff8f
commit
0c62bbf1cd
4 changed files with 67 additions and 4 deletions
|
|
@ -85,13 +85,25 @@
|
|||
return text;
|
||||
}
|
||||
// Lazy-load `path` from /api/state-file into the side panel.
|
||||
// Markdown files render through `marked` into a `.md` block; every
|
||||
// other file stays raw text in a <pre>.
|
||||
async function openFilePanel(path) {
|
||||
const pre = el('pre', { class: 'path-preview-body' }, '(fetching…)');
|
||||
Panel.open('↳ ' + path, pre);
|
||||
const isMd = /\.(md|markdown)$/i.test(path);
|
||||
const view = isMd
|
||||
? el('div', { class: 'md' })
|
||||
: el('pre', { class: 'path-preview-body' });
|
||||
view.textContent = '(fetching…)';
|
||||
Panel.open('↳ ' + path, view);
|
||||
try {
|
||||
pre.textContent = await fetchStateFile(path);
|
||||
const text = await fetchStateFile(path);
|
||||
if (isMd && window.marked && typeof window.marked.parse === 'function') {
|
||||
marked.setOptions({ breaks: true, gfm: true });
|
||||
view.innerHTML = marked.parse(text);
|
||||
} else {
|
||||
view.textContent = text;
|
||||
}
|
||||
} catch (e) {
|
||||
pre.textContent = 'error: ' + (e.message || e);
|
||||
view.textContent = 'error: ' + (e.message || e);
|
||||
}
|
||||
}
|
||||
function makePathLink(path) {
|
||||
|
|
|
|||
|
|
@ -805,3 +805,43 @@ footer a { color: var(--purple); }
|
|||
overflow: auto;
|
||||
padding: 1em;
|
||||
}
|
||||
/* Markdown file previews rendered by `marked`. TERMINAL_CSS scopes
|
||||
its own `.md` rules to `.live .row`, so the panel needs its own. */
|
||||
.side-panel-body .md { color: var(--fg); line-height: 1.5; }
|
||||
.side-panel-body .md > :first-child { margin-top: 0; }
|
||||
.side-panel-body .md > :last-child { margin-bottom: 0; }
|
||||
.side-panel-body .md p { margin: 0.5em 0; }
|
||||
.side-panel-body .md h1,
|
||||
.side-panel-body .md h2,
|
||||
.side-panel-body .md h3,
|
||||
.side-panel-body .md h4 { color: var(--purple); margin: 0.9em 0 0.4em; }
|
||||
.side-panel-body .md code {
|
||||
background: var(--bg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 3px;
|
||||
padding: 0.05em 0.3em;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.side-panel-body .md pre {
|
||||
background: var(--bg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 3px;
|
||||
padding: 0.6em 0.8em;
|
||||
overflow-x: auto;
|
||||
}
|
||||
.side-panel-body .md pre code { background: none; border: none; padding: 0; }
|
||||
.side-panel-body .md a { color: var(--cyan); }
|
||||
.side-panel-body .md ul,
|
||||
.side-panel-body .md ol { margin: 0.4em 0; padding-left: 1.5em; }
|
||||
.side-panel-body .md blockquote {
|
||||
margin: 0.5em 0;
|
||||
padding-left: 0.8em;
|
||||
border-left: 2px solid var(--border);
|
||||
color: var(--muted);
|
||||
}
|
||||
.side-panel-body .md table { border-collapse: collapse; margin: 0.5em 0; }
|
||||
.side-panel-body .md th,
|
||||
.side-panel-body .md td {
|
||||
border: 1px solid var(--border);
|
||||
padding: 0.2em 0.5em;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@
|
|||
</div>
|
||||
|
||||
<script src="/static/hive-fr0nt.js" defer></script>
|
||||
<script src="/static/marked.js" defer></script>
|
||||
<script src="/static/app.js" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue