feat: improve readability of list fields in CIM review
- Add normalizeToMarkdown() that converts inline "1) ... 2) ..." patterns to properly spaced markdown numbered lists for existing documents - Update Zod schema descriptions to instruct LLM to use newline-separated numbered items in list fields (keyAttractions, potentialRisks, etc.) - Fixes wall-of-text rendering in investment thesis and next steps sections Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -93,18 +93,18 @@ export const cimReviewSchema = z.object({
|
||||
}).describe("Management Team Overview section"),
|
||||
|
||||
preliminaryInvestmentThesis: z.object({
|
||||
keyAttractions: z.string().describe("Key Attractions / Strengths (Why Invest?)"),
|
||||
potentialRisks: z.string().describe("Potential Risks / Concerns (Why Not Invest?)"),
|
||||
valueCreationLevers: z.string().describe("Initial Value Creation Levers (How PE Adds Value)"),
|
||||
keyAttractions: z.string().describe("Key Attractions / Strengths (Why Invest?) — list each point on its own line, e.g. '1. Point one\\n2. Point two'"),
|
||||
potentialRisks: z.string().describe("Potential Risks / Concerns (Why Not Invest?) — list each point on its own line, e.g. '1. Point one\\n2. Point two'"),
|
||||
valueCreationLevers: z.string().describe("Initial Value Creation Levers (How PE Adds Value) — list each lever on its own line, e.g. '1. Lever one\\n2. Lever two'"),
|
||||
alignmentWithFundStrategy: z.string().describe("Alignment with Fund Strategy"),
|
||||
}).describe("Preliminary Investment Thesis section"),
|
||||
|
||||
keyQuestionsNextSteps: z.object({
|
||||
criticalQuestions: z.string().describe("Critical Questions Arising from CIM Review"),
|
||||
missingInformation: z.string().describe("Key Missing Information / Areas for Diligence Focus"),
|
||||
preliminaryRecommendation: z.string().describe("Preliminary Recommendation"),
|
||||
criticalQuestions: z.string().describe("Critical Questions Arising from CIM Review — list each question on its own line, e.g. '1. Question one\\n2. Question two'"),
|
||||
missingInformation: z.string().describe("Key Missing Information / Areas for Diligence Focus — list each item on its own line"),
|
||||
preliminaryRecommendation: z.string().describe("Preliminary Recommendation (Pass / Proceed with Caution / Proceed with Detailed Diligence)"),
|
||||
rationaleForRecommendation: z.string().describe("Rationale for Recommendation (Brief)"),
|
||||
proposedNextSteps: z.string().describe("Proposed Next Steps"),
|
||||
proposedNextSteps: z.string().describe("Proposed Next Steps — list each step on its own line, e.g. '1. Step one\\n2. Step two'"),
|
||||
}).describe("Key Questions & Next Steps section"),
|
||||
});
|
||||
|
||||
|
||||
@@ -3,6 +3,23 @@ import Markdown from 'react-markdown';
|
||||
import { Save, Download } from 'lucide-react';
|
||||
import { cn } from '../utils/cn';
|
||||
|
||||
/**
|
||||
* Normalize inline numbered lists like "1) First item. 2) Second item."
|
||||
* into proper markdown numbered lists for rendering.
|
||||
* Also handles patterns like "1. First item 2. Second item" without line breaks.
|
||||
*/
|
||||
function normalizeToMarkdown(text: string): string {
|
||||
if (!text) return text;
|
||||
// Convert "N) " patterns (preceded by start-of-string or ". ") to markdown numbered list
|
||||
// Match: start of string or after period+space, then digit(s) followed by ) and space
|
||||
const result = text.replace(/(?:^|\.\s+)(\d+)\)\s/g, (_m, num, offset) => {
|
||||
// If at start of string, just add newline before for markdown
|
||||
if (offset === 0) return `${num}. `;
|
||||
return `.\n\n${num}. `;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
interface CIMReviewData {
|
||||
// Deal Overview
|
||||
dealOverview: {
|
||||
@@ -343,8 +360,8 @@ const CIMReviewTemplate: React.FC<CIMReviewTemplateProps> = ({
|
||||
</label>
|
||||
{type === 'textarea' ? (
|
||||
readOnly && value ? (
|
||||
<div className="block w-full rounded-md border border-gray-200 bg-gray-50 px-3 py-2 text-sm text-gray-700 prose prose-sm max-w-none prose-p:my-1 prose-ul:my-1 prose-li:my-0">
|
||||
<Markdown>{value}</Markdown>
|
||||
<div className="block w-full rounded-md border border-gray-200 bg-gray-50 px-3 py-2 text-sm text-gray-700 prose prose-sm max-w-none prose-p:my-1 prose-ul:my-1 prose-ol:my-1 prose-li:my-0.5">
|
||||
<Markdown>{normalizeToMarkdown(value)}</Markdown>
|
||||
</div>
|
||||
) : (
|
||||
<textarea
|
||||
|
||||
Reference in New Issue
Block a user