Show the reference tables collapsed and the task guide on expand, from one file
This commit is contained in:
@@ -532,6 +532,9 @@ body.vv-fullscreen #displaybox { padding-left: 1rem !important; padding-top: .5r
|
||||
padding: 4px 6px 4px 0; vertical-align: top; }
|
||||
.vv-doc-code { background: #0d0d0d; border: 1px solid #222; border-radius: 3px; padding: 7px 9px;
|
||||
font-size: 11px; color: #9ab; overflow-x: auto; break-inside: avoid; }
|
||||
/* The always-visible reference tier. Sits below the collapsible guide, so the rule reads as a
|
||||
separator when the guide is open and as a header underline when it is shut. */
|
||||
.vv-doc-quick { border-top: 1px solid #1c1c1c; padding-top: 9px; }
|
||||
|
||||
.vv-info-divider { font-size: 10px; text-transform: uppercase; letter-spacing: 0.1em; color: #444;
|
||||
padding: 10px 12px 4px; border-top: 1px solid #2a2a2a; margin-top: 2px; }
|
||||
|
||||
@@ -72,7 +72,11 @@ function vv_docs_tree(): array {
|
||||
return $tree;
|
||||
}
|
||||
|
||||
function vv_docs_render(string $rel, array $vars): string {
|
||||
// $keep, when given, selects which `##` sections are rendered. It receives the section heading —
|
||||
// or null for the title and any preamble before the first one — and returns whether to include
|
||||
// it. That is what lets one file drive both tiers of a disclosure without a second copy, and
|
||||
// without inventing markdown syntax to mark the split: the section titles already carry it.
|
||||
function vv_docs_render(string $rel, array $vars, ?callable $keep = null): string {
|
||||
// Containment check — $rel is expected to come from a request parameter once this is
|
||||
// wired to a page. Resolve it and require the result to stay inside SCRIPTS_DIR and to
|
||||
// still be a .md file, so a traversal sequence cannot reach arbitrary files.
|
||||
@@ -83,7 +87,7 @@ function vv_docs_render(string $rel, array $vars): string {
|
||||
if (strtolower(pathinfo($path, PATHINFO_EXTENSION)) !== 'md') return '<p>File not found.</p>';
|
||||
if (!is_file($path)) return '<p>File not found.</p>';
|
||||
|
||||
return vv_docs_markdown(file_get_contents($path), $vars);
|
||||
return vv_docs_markdown(file_get_contents($path), $vars, $keep);
|
||||
}
|
||||
|
||||
// Markdown → HTML for the subset these docs actually use: headings, paragraphs, bullet and
|
||||
@@ -102,7 +106,7 @@ function vv_docs_render(string $rel, array $vars): string {
|
||||
// here, after escaping. Injecting <code> into the markdown before rendering, as this file used to
|
||||
// do, meant both Parsedown's safe mode and the <pre> fallback escaped the tags and printed them
|
||||
// as literal text. The feature never worked; nothing called it, so nothing reported it.
|
||||
function vv_docs_markdown(string $md, array $vars): string {
|
||||
function vv_docs_markdown(string $md, array $vars, ?callable $keep = null): string {
|
||||
if (file_exists(PARSEDOWN_PATH)) {
|
||||
require_once PARSEDOWN_PATH;
|
||||
$pd = new Parsedown();
|
||||
@@ -161,17 +165,39 @@ function vv_docs_markdown(string $md, array $vars): string {
|
||||
if ($inTable) { $out .= "</tbody></table>\n"; $inTable = false; }
|
||||
};
|
||||
|
||||
// Content before the first heading belongs to the same null-headed group as the title.
|
||||
$skip = $keep !== null && !$keep(null);
|
||||
|
||||
foreach (explode("\n", str_replace("\r\n", "\n", $md)) as $line) {
|
||||
// Fence state is tracked even inside a skipped section, or a ``` that is being dropped
|
||||
// would leave the parser convinced every following line is code.
|
||||
if (preg_match('/^```/', $line)) {
|
||||
$flushPara(); $closeList(); $closeTable();
|
||||
$out .= $inCode ? "</code></pre>\n" : '<pre class="vv-doc-code"><code>';
|
||||
if (!$skip) {
|
||||
$flushPara(); $closeList(); $closeTable();
|
||||
$out .= $inCode ? "</code></pre>\n" : '<pre class="vv-doc-code"><code>';
|
||||
}
|
||||
$inCode = !$inCode;
|
||||
continue;
|
||||
}
|
||||
if ($inCode) { $out .= htmlspecialchars($line, ENT_QUOTES, 'UTF-8') . "\n"; continue; }
|
||||
if ($inCode) {
|
||||
if (!$skip) $out .= htmlspecialchars($line, ENT_QUOTES, 'UTF-8') . "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
$t = trim($line);
|
||||
|
||||
// Headings are resolved before the skip test, because a heading is what changes it.
|
||||
if (preg_match('/^(#{1,6})\s+(.*)$/', $t, $m)) {
|
||||
$flushQuote(); $flushPara(); $closeList(); $closeTable();
|
||||
$n = strlen($m[1]);
|
||||
// A level-1 heading is the document title, not a section — it and the preamble that
|
||||
// follows are offered to $keep as null so a caller can take or leave them as a unit.
|
||||
$skip = $keep !== null && !$keep($n === 1 ? null : $m[2]);
|
||||
if (!$skip) $out .= "<h$n>" . $inline($m[2]) . "</h$n>\n";
|
||||
continue;
|
||||
}
|
||||
if ($skip) continue;
|
||||
|
||||
// One guard rather than a flush in every branch: the quote ends the moment a line is
|
||||
// not a quote line, whatever that next line turns out to be.
|
||||
if ($quote && !str_starts_with($t, '>')) $flushQuote();
|
||||
@@ -179,13 +205,6 @@ function vv_docs_markdown(string $md, array $vars): string {
|
||||
if ($t === '') { $flushPara(); $closeList(); $closeTable(); continue; }
|
||||
if (preg_match('/^(---+|\*\*\*+)$/', $t)) { $flushPara(); $closeList(); $closeTable(); $out .= "<hr>\n"; continue; }
|
||||
|
||||
if (preg_match('/^(#{1,6})\s+(.*)$/', $t, $m)) {
|
||||
$flushPara(); $closeList(); $closeTable();
|
||||
$n = strlen($m[1]);
|
||||
$out .= "<h$n>" . $inline($m[2]) . "</h$n>\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Consecutive > lines are one quote, not one per line — same wrapping convention as
|
||||
// paragraphs, which is how they are written.
|
||||
if (preg_match('/^>\s?(.*)$/', $t, $m)) {
|
||||
|
||||
@@ -507,12 +507,24 @@ $runningScripts = array_unique($runningScripts);
|
||||
<!-- Rendered from pages/readme/scheduler-readme.md, not maintained here. That file is
|
||||
also what the AI tab retrieves, so the panel you read and the answer the
|
||||
assistant gives are the same text and cannot drift — the same argument that
|
||||
makes this page parse script PURPOSE blocks instead of restating them. -->
|
||||
makes this page parse script PURPOSE blocks instead of restating them.
|
||||
Two tiers, one file. Collapsed leaves the reference tables visible: that is the
|
||||
terse per-control lookup this panel has always been, and it is what you want
|
||||
open while actually working. Expanding adds the task guide above it — the
|
||||
walkthroughs you need once and then stop reading. The split is taken from the
|
||||
section titles, so neither tier is a second copy of anything.
|
||||
vvToggleSug() toggles the header's immediate next sibling, so the guide must
|
||||
stay directly after the header and the quick tier must sit outside it. -->
|
||||
<div class="vv-sug-body vv-info-body">
|
||||
<div class="vv-doc">
|
||||
<?= vv_docs_render('Plugin/unraid/pages/readme/scheduler-readme.md', $_vv_doc_vars) ?>
|
||||
<?= vv_docs_render('Plugin/unraid/pages/readme/scheduler-readme.md', $_vv_doc_vars,
|
||||
fn($h) => !is_string($h) || !str_starts_with($h, 'Reference —')) ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="vv-info-body vv-doc vv-doc-quick">
|
||||
<?= vv_docs_render('Plugin/unraid/pages/readme/scheduler-readme.md', $_vv_doc_vars,
|
||||
fn($h) => is_string($h) && str_starts_with($h, 'Reference —')) ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── Next Runs ── -->
|
||||
|
||||
Reference in New Issue
Block a user