lib/renderer
lib/renderer.js
Functions(109)
Signature
badge(label: any, cls: any): any
Signature
anchorId(kind: any, name: any): any
Renders a named lucide-style line icon as inline SVG (design-system
§6.1: pure SVG, `stroke-width:1.75`, rounded caps/joins, 24x24 default
bounding box). Unknown names render nothing rather than throwing --
callers pass a literal string, so a typo should degrade silently, not
break page render.
| Parameter | Type | Optional | Description |
|---|---|---|---|
name | string | - one of ICON_PATHS's keys. | |
size | number | yes | - width/height in px, default 16. |
cls | string | yes | - optional extra CSS class on the <svg>. |
Returns:
string Signature
icon(name: any, size: any, cls: any): any
True when `s` is a `--fix`-generated placeholder, per `lib/fix.js`'s own
literal templates (`TODO_DESCRIPTION`, `TODO_RETURNS_DESCRIPTION`, the
per-param `TODO: describe parameter "x".` template) -- all start with
"TODO:" by design (see `lib/fix.js`'s own comment: "Every one is
prefixed 'TODO:' on purpose"). Matches that exact, existing convention;
invents nothing new (story-file-detail-redesign, ADR Decision 2).
| Parameter | Type | Optional | Description |
|---|---|---|---|
s | string |
Returns:
boolean Signature
isTodoText(s: any): any
Renders a description string, flagging `--fix`-generated TODO
placeholders with a distinct badge + muted italic text instead of
rendering them identically to real authored prose. The underlying text
is unchanged either way -- this is presentation-only.
| Parameter | Type | Optional | Description |
|---|---|---|---|
s | string |
Returns:
string Signature
descText(s: any): any
Signature
metaHtml(item: any): any
Server-side tokenizer for JS/TS @example blocks.
Returns HTML with tok-* spans. Processes strings, comments, numbers, keywords.
| Parameter | Type | Optional | Description |
|---|---|---|---|
raw | any |
Returns:
any Signature
highlightCode(raw: any): any
Signature
descHtml(item: any, symbolMap: any, filePath: any): any
Signature
renderParams(params: any, jsdocParams: any): any
Signature
renderReturns(returnType: any, returnsTag: any): any
Signature
renderThrows(throws: any): any
| Parameter | Type | Optional | Description |
|---|---|---|---|
text | any | ||
symbolMap | any | ||
filePath | any | ||
moduleHtmlPathFn | any | ||
modules | any |
Returns:
any Signature
resolveLinks(text: any, symbolMap: any, filePath: any, moduleHtmlPathFn: any, modules: any): any
Signature
sourceLink(item: any, filePath: any, sourceUrl: any): any
Signature
collapsible(label: any, html: any, open: any): any
Signature
buildFnSig(fn: any): any
Signature
buildClassSig(cls: any): any
Signature
buildIfaceSig(iface: any): any
Signature
card(id: any, kindClass: any, proseHtml: any, codeHtml: any): any
Signature
codePanel(item: any, sigText: any): any
| Parameter | Type | Optional | Description |
|---|---|---|---|
fn | any | ||
filePath | any | ||
sourceUrl | any | ||
symbolMap | any | ||
functionHealthLookup | any |
Returns:
any Signature
renderFunction(fn: any, filePath: any, sourceUrl: any, symbolMap: any, functionHealthLookup: any): any
| Parameter | Type | Optional | Description |
|---|---|---|---|
cls | any | ||
filePath | any | ||
sourceUrl | any | ||
symbolMap | any | ||
functionHealthLookup | any |
Returns:
any Signature
renderClass(cls: any, filePath: any, sourceUrl: any, symbolMap: any, functionHealthLookup: any): any
| Parameter | Type | Optional | Description |
|---|---|---|---|
iface | any | ||
filePath | any | ||
sourceUrl | any | ||
symbolMap | any |
Returns:
any Signature
renderInterface(iface: any, filePath: any, sourceUrl: any, symbolMap: any): any
| Parameter | Type | Optional | Description |
|---|---|---|---|
enm | any | ||
filePath | any | ||
sourceUrl | any | ||
symbolMap | any |
Returns:
any Signature
renderEnum(enm: any, filePath: any, sourceUrl: any, symbolMap: any): any
| Parameter | Type | Optional | Description |
|---|---|---|---|
ta | any | ||
filePath | any | ||
sourceUrl | any | ||
symbolMap | any |
Returns:
any Signature
renderTypeAlias(ta: any, filePath: any, sourceUrl: any, symbolMap: any): any
| Parameter | Type | Optional | Description |
|---|---|---|---|
v | any | ||
filePath | any | ||
sourceUrl | any | ||
symbolMap | any |
Returns:
any Signature
renderVariable(v: any, filePath: any, sourceUrl: any, symbolMap: any): any
| Parameter | Type | Optional | Description |
|---|---|---|---|
title | any | ||
items | any | ||
renderFn | any | ||
filePath | any | ||
sourceUrl | any | ||
symbolMap | any | ||
functionHealthLookup | any |
Returns:
any Signature
section(title: any, items: any, renderFn: any, filePath: any, sourceUrl: any, symbolMap: any, functionHealthLookup: any): any
Signature
commonRoot(modules: any): any
Signature
moduleLabel(filePath: any, modules: any): any
Signature
moduleHtmlPath(filePath: any, modules: any): any
Signature
deeperCommonRoot(labels: any): any
Signature
hasExports(mod: any): any
Builds a synthetic-root N-level tree from module file paths, reusing
deeperCommonRoot as a pre-pass. Single source of truth for buildSidebar
and buildIndexBody (adr-phase-i-tree-nav.md).
| Parameter | Type | Optional | Description |
|---|---|---|---|
modules | object[] |
Returns:
object — synthetic root TreeNode { name, type, children }Signature
pathTree(modules: any): any
Signature
shortLabelFor(label: any): any
Returns the array of ancestor dir TreeNodes (root to, not including, the
leaf) for the given module reference within the given tree.
| Parameter | Type | Optional | Description |
|---|---|---|---|
root | object | ||
targetMod | object |
Returns:
object[] Signature
ancestorChain(root: any, targetMod: any): any
Signature
walk(node: any, path: any): any
Signature
buildBody(item: any): any
Signature
buildSearchIndex(modules: any, prefix: any): any
Signature
push(name: any, kind: any, anchor: any, item: any)
Parses a site-data version-id (the ISO-timestamp segment
`site-data.js`'s `writeSiteData()` already bakes into
`site-data-history/site-data-<id>.json` filenames, dashes standing in for
the colons/dot a raw ISO string can't use in a filename) back into a
fixed, literal locale label -- never an invented relative-time phrase
("2 days ago" is not a preserved fact; story-doc-version-switcher AC4).
Falls back to the raw id string (still a real fact, just less pretty) if
the id doesn't match the expected shape or produces an invalid Date --
e.g. a rare collision-suffixed id like `<ts>-1`.
| Parameter | Type | Optional | Description |
|---|---|---|---|
versionId | string |
Returns:
string Signature
formatVersionLabel(versionId: any): any
Version-switcher control (story-doc-version-switcher): native
`<details>/<summary>` disclosure per ui-ux-designer's spec -- explicitly
NOT a `<select>` (rejected in the spec: needs a JS onchange handler to
navigate, breaking this project's zero/near-zero-script precedent).
Zero-history case renders a plain, non-interactive `<span>` instead of a
`<details>` with an empty menu -- a disclosure that opens to reveal
nothing-new-to-pick is a broken affordance (handoff notes, explicit).
the version-id being viewed when rendering inside a `site-versions/<id>/` snapshot.
rendered back to the output root where `site-versions/` and the live
`index.html` both live (differs from the page's own same-site asset
prefix when the page itself is inside a snapshot -- see buildSite()).
| Parameter | Type | Optional | Description |
|---|---|---|---|
currentVersionId | string|null | - null when rendering the live site; | |
versionIds | string[] | - `site-versions/` directory names, most-recent-first. | |
prefixToOutDirRoot | string | - relative path prefix from the page being |
Returns:
string Signature
buildVersionSwitcher(currentVersionId: any, versionIds: any, prefixToOutDirRoot: any): any
Signature
dirTitle(node: any): any
| Parameter | Type | Optional | Description |
|---|---|---|---|
node | any | ||
depth | any | ||
modules | any | ||
prefix | any | ||
cache | any |
Signature
precomputeDefaultTree(node: any, depth: any, modules: any, prefix: any, cache: any)
| Parameter | Type | Optional | Description |
|---|---|---|---|
node | any | ||
depth | any | ||
modules | any | ||
activePath | any | ||
prefix | any | ||
activeModule | any | ||
ancestorsOfActive | any | ||
defaultCache | any |
Returns:
any Signature
renderTreeLevel(node: any, depth: any, modules: any, activePath: any, prefix: any, activeModule: any, ancestorsOfActive: any, defaultCache: any): any
| Parameter | Type | Optional | Description |
|---|---|---|---|
modules | any | ||
projectName | any | ||
version | any | ||
activePath | any | ||
rootPrefix | any | ||
activeModule | any | ||
precomputedTree | any | ||
opts | any |
Returns:
any Signature
buildSidebar(modules: any, projectName: any, version: any, activePath: any, rootPrefix: any, activeModule: any, precomputedTree: any, opts: any): any
Signature
buildToc(mod: any): any
Signature
buildSymbolMap(modules: any): any
Bounded breadcrumb segments for an index card (task-pi-05c): drops the
filename, keeps at most the last 2 directory segments, prefixing an
ellipsis when the path is deeper than that.
| Parameter | Type | Optional | Description |
|---|---|---|---|
sl | string |
Returns:
string[]|null Signature
cardBreadcrumb(sl: any): any
Signature
buildIndexBody(modules: any): any
Signature
_short(label: any): any
Signature
qColor(score: any, kind: any): any
Signature
qCountColor(n: any): any
Signature
qWarnColor(n: any): any
Signature
qSeverityColor(sev: any): any
Display-only letter grade for the Code Health hero gauge
(story-code-health-redesign, ADR Decision 5). This is a purely cosmetic,
finer-grained scale layered ON TOP OF `qColor`'s existing 3-band
thresholds -- it does NOT replace or compete with them. The gauge's arc
color and score text color must still come from `qColor(score, "health")`;
a "B+" and a "B" can legitimately render in the same color, same as two
scores in the same qColor band always have.
| Parameter | Type | Optional | Description |
|---|---|---|---|
score | number | - 0-100 health score (result.averageHealthScore). |
Returns:
string — a letter grade, or "—" if score isn't a finite number.Signature
scoreToGrade(score: any): any
Renders the Code Health gauge ring as an inline SVG arc (270° sweep
starting at 135°/bottom-left) instead of a CSS `conic-gradient` circle --
matches the jsdoc-scribe design-system reference (`GradeGauge`) exactly,
and gives the filled arc a real drop-shadow glow that `conic-gradient`
can't produce. Purely a ring; grade/score text stays as separate HTML
(`.qhero-grade`/`.qhero-score`) absolutely centered over it via
`.qhero-gauge-inner`, unchanged from before -- only the ring-drawing
mechanism changed.
| Parameter | Type | Optional | Description |
|---|---|---|---|
color | string | - stroke color for the filled portion (a qColor() result). | |
pct | number | - 0-1 fraction filled. | |
size | number | - SVG width/height in px, matches the CSS ring's own diameter. |
Returns:
string Signature
gaugeArcSvg(color: any, pct: any, size: any): any
Signature
polar(angleDeg: any): any
Signature
arc(startAngle: any, endAngle: any): any
Signature
qStatCard(label: any, value: any, color: any): any
Renders one qcard-row (shared between a card's always-visible preview and
its inline "view more" expansion — same lightweight [label, value, color?]
shape used since story-code-health-drilldown, deliberately NOT the richer
detail-page `<table>` row shape, so smell ids etc. stay detail-page-only,
see story-code-health-redesign's requirement #6).
| Parameter | Type | Optional | Description |
|---|---|---|---|
r | [string, string|number|null, string|null] |
Returns:
string Signature
qCardRow(r: any): any
Renders one focus-area card for the index page's Code Health section
(story-code-health-redesign, restyling story-code-health-drilldown's
original card). Shows up to 5 rows inline; any remaining rows are
reachable via a native `<details>` expand (zero client JS — see ADR
Decision 3) rather than only via the standalone detail page. The
standalone detail-page link ("open full page") remains, unconditionally,
per requirement #6 — this is additive, not a replacement.
| Parameter | Type | Optional | Description |
|---|---|---|---|
opts | {title: string, statLineHtml?: string, rows: Array<[string, string|number|null, string|null]>, moreHref: string, moreLabel: string, tag: string, tagBg: string, tagText: string, tagColor: string, bigValue: string, bigCaption: string} |
Returns:
string Signature
qCard(opts: any): any
Score-of helper for a code-multivitals Snapshot (story-code-health-redesign
ADR Decision 6). Snapshot shape per `node_modules/code-multivitals/dist/snapshots.d.ts`:
`{path, timestamp, result}` — `result` is a full AnalysisResult, same shape
runQuality() returns, so `.averageHealthScore` is already there, no new field.
| Parameter | Type | Optional | Description |
|---|---|---|---|
snapshot | {result?: {averageHealthScore?: number}} |
Returns:
number|null Signature
qSnapshotScore(snapshot: any): any
Renders the hero panel's trend sparkline + delta badge (story-code-health-redesign,
ADR Decision 6). `loadQualitySnapshots()` returns snapshots sorted oldest-first;
this renders up to the last 6. Fewer than 2 usable snapshots -> an honest
"not enough history yet" message, never a fabricated/flat line.
| Parameter | Type | Optional | Description |
|---|---|---|---|
snapshots | Array<object> | - `quality.snapshots` (may be empty/undefined). |
Returns:
string Signature
buildHealthSparkline(snapshots: any): any
Renders the Code Health hero panel (story-code-health-redesign): a
circular CSS `conic-gradient` gauge (grade + score, both derived from
`result.averageHealthScore` and colored via the existing `qColor` bands —
ADR Decision 5), the 6 non-gauge stat entries previously shown as separate
`.qstat-card`s, and the trend sparkline/delta badge (ADR Decision 6).
| Parameter | Type | Optional | Description |
|---|---|---|---|
result | object | - runQuality() AnalysisResult. | |
snapshots | Array<object> | - `quality.snapshots`, may be empty/undefined. |
Returns:
string Signature
buildHealthHero(result: any, snapshots: any): any
Signature
attentionList(result: any): any
Signature
attentionRowsHtml(list: any): any
Signature
cloneRowsHtml(clones: any): any
Signature
importRowsHtml(entries: any): any
Signature
orphanRowsHtml(orphans: any): any
Converts an absolute file path to a cwd-relative one for display in the
Code Health dashboard's "Most-imported files" / "Orphan files" cards and
their detail pages. lib/import-graph.js intentionally works in absolute
paths internally (needed for matching against the resolved file set) --
this is presentation-only, bringing these two cards in line with the
"Files needing attention" / "Duplicate code" cards, whose paths are
already cwd-relative courtesy of code-multivitals. Falls back to the
original string for anything path.relative() can't shorten (already
relative input, a different drive on Windows, etc.) rather than risk
showing an even less readable path.
| Parameter | Type | Optional | Description |
|---|---|---|---|
filePath | string |
Returns:
string Signature
toDisplayPath(filePath: any): any
Renders the code-multivitals health summary as an inline section for the
doc site's index page (story-code-health-drilldown, 2026-07-06): 7 stat
cards unchanged, followed by 4 summary cards (previously 4 full inline
tables) each linking to its own uncapped detail page — see
buildHealthDetailPages(). Detail-page hrefs are plain root-relative
filenames, valid whether this section renders on index.html directly or
is exercised standalone in tests.
| Parameter | Type | Optional | Description |
|---|---|---|---|
quality | {result: object, graph?: object, orphans?: string[]} |
Returns:
string — HTML for a <div class="section"> block.Signature
buildQualitySection(quality: any): any
`seoBaseUrl`/`seoDescription` (both optional, added alongside buildSite()'s
`baseUrl`/`description` options): when `seoBaseUrl` is given, each detail
page gets a canonical link (`seoBaseUrl + slug`) plus matching OpenGraph
tags via `page()`'s `seo` param; `seoDescription` is reused as-is for every
detail page's meta description (these are drill-down tables, not distinct
content, so a shared description is accurate rather than a compromise).
Trailing/optional -- omitted entirely, output is unchanged from before.
| Parameter | Type | Optional | Description |
|---|---|---|---|
quality | any | ||
modules | any | ||
projectName | any | ||
version | any | ||
tree | any | ||
switcherHtml | any | ||
defaultCache | any | ||
parentsLinked | any | ||
architectureHref | any | ||
seoBaseUrl | any | ||
seoDescription | any |
Returns:
any Signature
buildHealthDetailPages(quality: any, modules: any, projectName: any, version: any, tree: any, switcherHtml: any, defaultCache: any, parentsLinked: any, architectureHref: any, seoBaseUrl: any, seoDescription: any): any
Signature
wrap(slug: any, title: any, tableHtml: any)
Wraps `s` in an escaped `<code>` span -- the lightweight "code voice" used
throughout the phrasing table in UX §2.5 for file/dir/dependency names.
| Parameter | Type | Optional | Description |
|---|---|---|---|
s | string |
Returns:
string Signature
codeSpan(s: any): any
Builds the one-sentence, evidence-backed body copy for an architecture-
pattern-signal `.qcard` (UX §2.5's first phrasing table), keyed off the
exact evidence-string shapes `getArchitectureSignals()` produces today.
Evidence not matching any table row (a future signal shape, e.g. this
repo's own "Frontend application" signal, which shares the "framework
dependency: ..." shape with "Backend/API service" but has no table row of
its own) falls back to UX §2.5's general rule: name the actual evidence,
never paraphrase away specifics, never show it raw/un-wrapped.
| Parameter | Type | Optional | Description |
|---|---|---|---|
signal | {name: string, evidence: string} |
Returns:
string — HTML (already escaped where needed).Signature
architectureSignalSentence(signal: any): any
Builds the one-sentence, evidence-backed body copy for a framework-signal
`.qcard` (UX §2.5's second phrasing table), covering both confidence
shapes `getFrameworkSignals()` produces.
| Parameter | Type | Optional | Description |
|---|---|---|---|
signal | {name: string, confidence: ("dependency"|"file-heuristic"), evidence: string} |
Returns:
string — HTML (already escaped where needed).Signature
frameworkSignalSentence(signal: any): any
Signature
archSignalCard(signal: any): any
Renders one getArchitecturePatterns() entry as a card: name, the
concrete evidence that matched, a 3-4 line plain-language description,
and a "Learn more" link out to the pattern's canonical external
reference (Wikipedia or its originating/official source). Distinct from
archSignalCard() above -- architectureSignals answers "what kind of
project is this" (CLI tool, monorepo, ...); architecturePatterns answers
the deeper "which architecture style does this codebase's own folder
structure actually look like" question, so it always carries a
description + reference link even though both reuse the same .qcard shell.
| Parameter | Type | Optional | Description |
|---|---|---|---|
pattern | {name: string, description: string, link: string, evidence: string} |
Returns:
string Signature
archPatternCard(pattern: any): any
Signature
frameworkSignalCard(signal: any): any
Renders a `getWorkspacePackages()` result as the "Workspace packages"
sub-heading (UX §2.6), reusing `.module-grid`/`.module-card` -- plain
`<div>` cards, not `<a>` links, since there's no per-package page to link
to (unlike the index page's module cards).
| Parameter | Type | Optional | Description |
|---|---|---|---|
workspacePackages | {name: string, path: string, description: (string|null)}[] |
Returns:
string Signature
buildWorkspacePackagesSubsection(workspacePackages: any): any
Buckets a directory node's own (non-recursive) per-extension file counts
-- project-facts.js's summarizeFileExtensions() only counts a directory's
own immediate files, never descendants -- into the 4 headline categories
above, plus a catch-all "other" total for every extension that doesn't
match any of them (.md/.html/.yml/.svg/etc).
| Parameter | Type | Optional | Description |
|---|---|---|---|
filesMap | any |
Returns:
any Signature
categorizeStructureFiles(filesMap: any): any
Signature
structBadge(color: any, text: any): any
Renders one directory node's own badge row: a folder-count badge (if it
has subdirectories) followed by one colored badge per non-zero file
category, plus a muted "other" badge for anything uncategorized. Every
level of the tree gets its own row computed the same way, since
renderStructureNode below calls this once per recursive invocation --
that's what makes the badges recursive down every subtree, not just the
top level.
| Parameter | Type | Optional | Description |
|---|---|---|---|
node | any |
Returns:
any Signature
structureBadgesHtml(node: any): any
Recursively renders one `getProjectStructure()` node as a native
`<details>`/`<summary>` using the already-shipped `.collapse-toggle`/
`.collapse-body` classes (Consolidation note's binding correction over
the ADR's own superseded `sidebar-item-details` parenthetical -- this
lives in `.main` page content, not the sidebar nav, so it carries the
light card-internal treatment, not sidebar chrome). Depth-0 (top-level)
nodes render open; every nested level renders collapsed by default (UX
§2.6). A `children` array beyond 40 entries renders only the first 40
(already alphabetical, matching `getProjectStructure()`'s own sort) plus
a static "+N more" line -- no expand-more JS.
| Parameter | Type | Optional | Description |
|---|---|---|---|
node | {name: string, description: string, files: object, children: (Array|undefined)} | ||
depth | number | - 0 for a top-level directory. |
Returns:
string Signature
renderStructureNode(node: any, depth: any): any
"{N} pattern signal(s) · {P} architecture pattern(s) · {M} framework
signal(s) · {D} top-level director{y|ies}" (UX §2.1, extended
2026-07-15 for architecturePatterns) -- omits any segment whose count is 0.
| Parameter | Type | Optional | Description |
|---|---|---|---|
facts | object |
Returns:
string Signature
buildArchitectureSubtitle(facts: any): any
"WHAT KIND OF PROJECT IS THIS" section (architecture-pattern signals),
or "" when there are no signals to show. Split out of
`buildArchitectureSection()` (GitHub code-scanning alert: that function's
combined Halstead volume/cyclomatic complexity crossed threshold) --
output is unchanged, just relocated.
| Parameter | Type | Optional | Description |
|---|---|---|---|
architectureSignals | object[] |
Returns:
string Signature
buildArchitectureSignalsSection(architectureSignals: any): any
"ARCHITECTURAL PATTERN(S)" section, or "" when none were detected. See
`buildArchitectureSignalsSection()`'s doc comment for why this was split
out of `buildArchitectureSection()`.
| Parameter | Type | Optional | Description |
|---|---|---|---|
architecturePatterns | object[] |
Returns:
string Signature
buildArchitecturePatternsSection(architecturePatterns: any): any
"WHAT IT'S BUILT WITH" section (framework signals), or "" when none
were detected. See `buildArchitectureSignalsSection()`'s doc comment for
why this was split out of `buildArchitectureSection()`.
| Parameter | Type | Optional | Description |
|---|---|---|---|
frameworkSignals | object[] |
Returns:
string Signature
buildFrameworkSignalsSection(frameworkSignals: any): any
The structure section's tree body: either the rendered nodes (capped at
40, "+N more" beyond that, per UX §2.6) or the "no subdirectories" empty
state. Structure is the one section with no presence guard -- an empty
`[]` is a legitimate result to show, not an absent-data state.
| Parameter | Type | Optional | Description |
|---|---|---|---|
structure | object[] |
Returns:
string Signature
buildStructureBodyHtml(structure: any): any
"HOW IT'S ORGANIZED" section -- always rendered (never gated on an
empty-check) once `buildArchitectureSection()` has already decided the
page as a whole has something to show. See
`buildArchitectureSignalsSection()`'s doc comment for why this was split
out of `buildArchitectureSection()`.
| Parameter | Type | Optional | Description |
|---|---|---|---|
structure | object[] | ||
workspacePackages | object[] |
Returns:
string Signature
buildStructureSection(structure: any, workspacePackages: any): any
Builds the three content sections of the Architecture page (pattern
signals -> framework signals -> structure, UX §1/§3's mandated DOM order)
from `getAllFacts()` output. Returns "" when `facts` is absent or every
relevant field is empty -- the single presence-check this ticket's "no
page on empty/absent facts" AC hangs off (mirrors `buildQualitySection`'s
`if (!quality || !quality.result) return "";` guard).
The pattern-signal and framework-signal sections are themselves omitted
when their own signal list is empty (no card grid with zero cards) --
the structure section is the one documented exception (UX §2.6): a
`getProjectStructure()` of `[]` is "a legitimate, correct result to show,
not an absent-data state," so that section always renders once this
function doesn't early-return, with a `.qempty` message in place of a
tree.
Each of the four sections' own markup lives in its own
`build*Section()` helper above (GitHub code-scanning alert: this
function's combined Halstead volume/cyclomatic complexity crossed
threshold when all four were inlined) -- this function is now just the
presence-guard plus a fixed-order concatenation, with identical output
to before.
| Parameter | Type | Optional | Description |
|---|---|---|---|
facts | object | - getAllFacts() output. |
Returns:
string Signature
buildArchitectureSection(facts: any): any
Assembles the standalone architecture.html page (task-arch-04, ADR
Decisions 1-4/6) via the existing `page()`/`buildTopnav()`/`buildSidebar()`
helpers, parallel to `buildHealthDetailPages()`'s `wrap()` pattern. Only
meaningful to call when `buildArchitectureSection(facts)` is non-empty;
returns `null` otherwise so callers (buildSite()) skip pushing a page and
skip wiring the sidebar navbutton -- no page/section/navbutton at all on
absent/empty facts, per ADR Decision 3.
Deviation from the ticket's literal signature, disclosed: the ticket text
lists `buildArchitecturePage(facts, projectName, version, tree,
switcherHtml, defaultCache)` with no `modules` parameter. `buildSidebar()`
requires `modules` (its first argument, used inside `renderTreeLevel()` to
resolve each module's href) for every other page in the site, including
the structurally-parallel `buildHealthDetailPages()`; omitting it here
would render an empty/broken Modules tree in this one page's sidebar,
inconsistent with every other generated page. `modules` and `parentsLinked`
(mirroring `buildHealthDetailPages()`'s own trailing param, so this page
reuses `buildSite()`'s already-linked `__parent` pointers instead of
re-walking them) are added to the signature below.
same-named param: when given, adds a canonical link (`seoBaseUrl + "architecture.html"`)
plus OpenGraph tags. Omitted entirely, output is unchanged from before.
ARCHITECTURE_ORIENTATION_PARAGRAPH (already accurate, plain-English page copy)
when the caller doesn't supply a site-wide one.
| Parameter | Type | Optional | Description |
|---|---|---|---|
facts | object | - getAllFacts() output. | |
modules | object[] | ||
projectName | string | ||
version | string | ||
tree | object | - precomputed pathTree(modules), reused from buildSite. | |
switcherHtml | string | ||
defaultCache | Map | ||
parentsLinked | boolean | yes | |
seoBaseUrl | string | yes | - trailing/optional, mirrors buildHealthDetailPages()'s |
seoDescription | string | yes | - meta description; falls back to |
Returns:
{path: string, html: string}|null Signature
buildArchitecturePage(facts: any, modules: any, projectName: any, version: any, tree: any, switcherHtml: any, defaultCache: any, parentsLinked: any, seoBaseUrl: any, seoDescription: any): any
Precomputes a filePath-keyed lookup of per-file health data for the
module-page strip (story-code-health-drilldown AC4/AC8). Built once per
buildSite() call, not per module page. Join key is path.resolve(filePath)
— code-multivitals's FileReport.filePath and this project's own
mod.filePath are both whatever string was in the `files` array passed to
extractModule()/runQuality() (same array, same run), so they already
match string-for-string in the common case; resolving both sides is a
defensive normalization, not a fix for a known mismatch.
Per-file error/warning counts and function count are not provided
directly by code-multivitals's FileSummary — they're derived here by
counting existing FunctionReport.metrics[].severity entries and
FileReport.functions.length, reusing data already present in the
analyse() result (no new metrics).
| Parameter | Type | Optional | Description |
|---|---|---|---|
quality | {result: object} |
Returns:
Object<string, object> Signature
buildFileHealthLookup(quality: any): any
Signature
getFileReportMap(qualityResult: any): any
| Parameter | Type | Optional | Description |
|---|---|---|---|
quality | any | ||
filePath | any |
Returns:
any Signature
buildFunctionHealthLookup(quality: any, filePath: any): any
Compact inline per-function/method health chip row (story-function-level-
health-drilldown). Reuses scoreToGrade()/qColor()/qSeverityColor() verbatim
at a smaller, inline scale -- deliberately not a second full gauge (AC2:
must read as subordinate to the per-file hero above it on the same page).
Graceful fallback (AC3/architect Decision 4): no matching FunctionReport ->
a single muted qchip-empty span, never a broken/NaN render, never a silent
fall-back to file-level aggregate data.
| Parameter | Type | Optional | Description |
|---|---|---|---|
name | string | ||
line | number|null | ||
healthLookup | {match: function} |
Returns:
string Signature
functionHealthChip(name: any, line: any, healthLookup: any): any
Signature
qChip(label: any, value: any, color: any, href: any): any
Short, factual one-line summary built purely from real per-file counts
(story-file-detail-redesign AC1). Deliberately NOT the File Detail
mockup's stylized "encouraging" copy ("Nearly there -- clear the 2
clones and this file ships clean.") -- that would be invented,
un-derivable prose, the same category story-code-health-redesign
already declined to build for the index-page hero. Every clause here is
a literal count already in `d`.
| Parameter | Type | Optional | Description |
|---|---|---|---|
d | object | - buildFileHealthLookup() entry for one file. |
Returns:
string Signature
fileHeroNarrative(d: any): any
Per-file hero panel for module pages (story-file-detail-redesign,
replacing the old flat `.qstrip` chip row -- ADR Decision 1). Reuses
story-code-health-redesign's gauge/grade primitives (`scoreToGrade()`,
`qColor()` bands) verbatim, scoped to this one file's
`weightedHealthScore`/`weightedMI` instead of the project-wide average.
Files with no code-multivitals entry keep the same graceful fallback
`buildHealthStrip()` always had -- one muted row, never a broken/zero
gauge.
| Parameter | Type | Optional | Description |
|---|---|---|---|
mod | object | ||
healthLookup | Object<string, object> | - buildFileHealthLookup() output. | |
cloneHref | string | - relative href to health-duplicates.html from a module page. |
Returns:
string Signature
buildFileHero(mod: any, healthLookup: any, cloneHref: any): any
| Parameter | Type | Optional | Description |
|---|---|---|---|
mod | any | ||
sourceUrl | any | ||
symbolMap | any | ||
functionHealthLookup | any |
Returns:
any Signature
buildModuleBody(mod: any, sourceUrl: any, symbolMap: any, functionHealthLookup: any): any
`seo` (optional) -- adds a meta description, an explicit robots directive,
and (only when `seo.canonical` is given, since a relative/invalid URL is
worse than no canonical at all) a canonical link plus matching OpenGraph
tags. Every field is additive and defaults to omitted, so existing callers
that don't pass `seo` produce byte-identical output to before this was
added -- see buildSite()'s new `baseUrl`/`description` options for how
callers opt in.
| Parameter | Type | Optional | Description |
|---|---|---|---|
title | any | ||
sidebarHtml | any | ||
bodyHtml | any | ||
assetPrefix | any | ||
topnavHtml | any | ||
tocHtml | any | ||
seo | {description?: string, canonical?: string} | yes |
Returns:
any Signature
page(title: any, sidebarHtml: any, bodyHtml: any, assetPrefix: any, topnavHtml: any, tocHtml: any, seo: any): any
Variables & Constants(360)
Signature
let NO_DIR_DESCRIPTION_SENTINEL: string
Signature
let FRAMEWORK_DEP_MARKER_BY_NAME: Object
let ARCHITECTURE_SIGNAL_SENTENCES: Array
varUX §2.5's first phrasing table: one row per named architecture-pattern
signal, each pairing the exact evidence-string shape
`getArchitectureSignals()` produces for that signal with the sentence
template to render for it. Kept as data (rather than inline `if` chains)
so `architectureSignalSentence()` stays a thin dispatcher — see that
function's own doc comment for the fallback behavior when a signal's name
isn't in this table, or its evidence doesn't match the row's pattern.
Signature
let ARCHITECTURE_SIGNAL_SENTENCES: Array
let ARCHITECTURE_SIGNAL_FALLBACKS: Array
varUX §2.5's general rule: evidence shapes with no named row in
`ARCHITECTURE_SIGNAL_SENTENCES` (a future signal, or a named signal whose
evidence didn't match its own row's pattern) still get a sentence built
from the actual evidence shape, keyed only on that shape — never on
signal name, and never a bare/un-wrapped fallback.
Signature
let ARCHITECTURE_SIGNAL_FALLBACKS: Array
Signature
let STRUCTURE_BADGE_CATEGORIES: Array
Signature
let STRUCTURE_BADGE_FOLDER_COLOR: string
Signature
let STRUCTURE_BADGE_OTHER_COLOR: string
Signature
let architecturePatterns: any
Signature
let ARCHITECTURE_ORIENTATION_PARAGRAPH: any
let fileReportMapCache: WeakMap
varPer-function/method Code Health matching (story-function-level-health-drilldown).
Empirical finding (TICKET-1, checked live against sample/container.ts via
runQuality()): code-multivitals emits BARE method names for class members
("constructor", "resolve", "debug", ...) -- never a "ClassName.methodName"
composite, even when multiple classes in the same file share a method name
(three unrelated classes in that fixture each have their own "constructor"
entry at different line ranges). Point-in-range matching against
startLine/endLine is what actually disambiguates same-named methods across
classes, not the name alone -- so no composite-name fallback path is
implemented; it would never be reached.
Matching strategy (solutions-architect decision): name + point-in-range
(extracted.line within [fn.startLine, fn.endLine] inclusive), tightest
(smallest) range wins on ambiguous/nested matches. Returns an object with
a `match(name, line)` method rather than a plain map, since resolution
needs a computed range-containment check per lookup, not a static key --
callers can always call `.match()` safely, never need to null-check the
lookup object itself.
Signature
let fileReportMapCache: WeakMap
Signature
let toOutDirRootFromIndex: any
Signature
let toOutDirRootFromModule: any
Signature
let functionHealthLookup: any