mirror of
https://github.com/jhbruhn/respira.git
synced 2026-01-27 02:13:41 +00:00
- Simplify StepCircle cursor logic to use isComplete || isCurrent - Fix UploadButton to use boundsFits prop instead of !!boundsError - Remove XSS vulnerability by parsing markdown safely without dangerouslySetInnerHTML - Move ColorBlock type to shared types.ts file to reduce coupling - Rename useDisplayFilename to getDisplayFilename and move to utils (not a hook) - Improve threadMetadata JSDoc with detailed examples - Make WorkflowStep interface properties readonly for full immutability - Fix PyodideProgress redundant negation logic All issues from Copilot review resolved. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
82 lines
2.6 KiB
TypeScript
82 lines
2.6 KiB
TypeScript
/**
|
|
* Format thread metadata for display.
|
|
*
|
|
* Combines brand, catalog number, chart, and description into a readable string
|
|
* using the following rules:
|
|
*
|
|
* - The primary part consists of the brand and catalog number:
|
|
* - The brand (if present) appears first.
|
|
* - The catalog number (if present) is prefixed with `#` and appended after
|
|
* the brand, separated by a single space (e.g. `"DMC #310"`).
|
|
* - The secondary part consists of the chart and description:
|
|
* - The chart is omitted if it is `null`/empty or exactly equal to
|
|
* `threadCatalogNumber`.
|
|
* - The chart (when shown) and the description are joined with a single
|
|
* space (e.g. `"Anchor 24-colour Black"`).
|
|
* - The primary and secondary parts are joined with `" • "` (space, bullet,
|
|
* space). If either part is empty, only the non-empty part is returned.
|
|
*
|
|
* Examples:
|
|
*
|
|
* - Brand and catalog only:
|
|
* - Input:
|
|
* - `threadBrand: "DMC"`
|
|
* - `threadCatalogNumber: "310"`
|
|
* - `threadChart: null`
|
|
* - `threadDescription: null`
|
|
* - Output: `"DMC #310"`
|
|
*
|
|
* - Brand, catalog, and description:
|
|
* - Input:
|
|
* - `threadBrand: "DMC"`
|
|
* - `threadCatalogNumber: "310"`
|
|
* - `threadChart: null`
|
|
* - `threadDescription: "Black"`
|
|
* - Output: `"DMC #310 • Black"`
|
|
*
|
|
* - Brand, catalog, chart (different from catalog), and description:
|
|
* - Input:
|
|
* - `threadBrand: "Anchor"`
|
|
* - `threadCatalogNumber: "403"`
|
|
* - `threadChart: "24-colour"`
|
|
* - `threadDescription: "Black"`
|
|
* - Output: `"Anchor #403 • 24-colour Black"`
|
|
*
|
|
* - Chart equal to catalog number (chart omitted):
|
|
* - Input:
|
|
* - `threadBrand: "DMC"`
|
|
* - `threadCatalogNumber: "310"`
|
|
* - `threadChart: "310"`
|
|
* - `threadDescription: "Black"`
|
|
* - Output: `"DMC #310 • Black"`
|
|
*/
|
|
|
|
interface ThreadMetadata {
|
|
threadBrand: string | null;
|
|
threadCatalogNumber: string | null;
|
|
threadChart: string | null;
|
|
threadDescription: string | null;
|
|
}
|
|
|
|
export function formatThreadMetadata(thread: ThreadMetadata): string {
|
|
// Primary metadata: brand and catalog number
|
|
const primaryMetadata = [
|
|
thread.threadBrand,
|
|
thread.threadCatalogNumber ? `#${thread.threadCatalogNumber}` : null,
|
|
]
|
|
.filter(Boolean)
|
|
.join(" ");
|
|
|
|
// Secondary metadata: chart and description
|
|
// Only show chart if it's different from catalogNumber
|
|
const secondaryMetadata = [
|
|
thread.threadChart && thread.threadChart !== thread.threadCatalogNumber
|
|
? thread.threadChart
|
|
: null,
|
|
thread.threadDescription,
|
|
]
|
|
.filter(Boolean)
|
|
.join(" ");
|
|
|
|
return [primaryMetadata, secondaryMetadata].filter(Boolean).join(" • ");
|
|
}
|