From 79005dc7773590737d26b4b4e1b1d2aa28e42c77 Mon Sep 17 00:00:00 2001 From: Janpeter Visser <30029041+madhura68@users.noreply.github.com> Date: Fri, 8 May 2026 13:22:10 +0200 Subject: [PATCH] Sprint: regril (#170) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ST-cmowjelb1: Parser: bestand-relatieve regel + hint-detectie in YAMLParseError-tak - Voeg `hint?: string` toe aan PlanParseError type - Bereken bestand-relatief regelnummer (yamlLine + 1 voor de openings-`---`) - Detecteer markdown-patronen (numbered/bullet lijst) op de offending regel - Zet Nederlandstalige hint bij markdown-match - Render hint als "Tip: …" onder het foutbericht in IdeaMdEditor * ST-cmowjeq3q: UI: render hint apart onder error-message in IdeaMdEditor Vervang door
voor de Tip-hint per plan-spec (MD3-token, geen status-kleur). * ST-cmowjewfg: Test: parser geeft hint bij markdown-in-frontmatter Voeg twee Vitest-cases toe: - hints when markdown sneaks into frontmatter: fixture met [unclosed op een genummerde markdown-regel triggert YAMLParseError op die regel (plain lijst zonder unclosed flow parset als geldig YAML) - omits hint for non-markdown yaml errors: unclosed bracket zonder markdown-patroon geeft geen hint --- __tests__/lib/idea-plan-parser.test.ts | 35 ++++++++++++++++++++++++++ components/ideas/idea-md-editor.tsx | 3 +++ lib/idea-plan-parser.ts | 23 +++++++++++------ 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/__tests__/lib/idea-plan-parser.test.ts b/__tests__/lib/idea-plan-parser.test.ts index 30169aa..c279ea8 100644 --- a/__tests__/lib/idea-plan-parser.test.ts +++ b/__tests__/lib/idea-plan-parser.test.ts @@ -62,6 +62,41 @@ body } }) + it('hints when markdown sneaks into frontmatter', () => { + // "1. **...**: [unclosed" triggers a YAMLParseError at the markdown line + // (plain-list-with-bold parses as valid YAML without an unclosed flow) + const broken = `--- +pbi: + title: Test + priority: 2 +stories: +1. **Toggle zichtbaar in productie**: [unclosed +--- + +body +` + const r = parsePlanMd(broken) + expect(r.ok).toBe(false) + if (!r.ok) { + expect(r.errors[0].hint).toMatch(/markdown/i) + expect(r.errors[0].line).toBeGreaterThan(1) + } + }) + + it('omits hint for non-markdown yaml errors', () => { + const broken = `--- +pbi: + title: Test + priority: [unclosed +stories: + - foo +--- +` + const r = parsePlanMd(broken) + expect(r.ok).toBe(false) + if (!r.ok) expect(r.errors[0].hint).toBeUndefined() + }) + it('reports schema-validation error when pbi-section missing', () => { const noPbi = `--- stories: diff --git a/components/ideas/idea-md-editor.tsx b/components/ideas/idea-md-editor.tsx index 1d7c46e..85c52bd 100644 --- a/components/ideas/idea-md-editor.tsx +++ b/components/ideas/idea-md-editor.tsx @@ -123,6 +123,9 @@ export function IdeaMdEditor({ ideaId, kind, initialValue, onCancel }: Props) {
  • {err.line ? `Regel ${err.line}: ` : ''} {err.message} + {err.hint && ( +
    Tip: {err.hint}
    + )}
  • ))} diff --git a/lib/idea-plan-parser.ts b/lib/idea-plan-parser.ts index 02b968b..b8202b9 100644 --- a/lib/idea-plan-parser.ts +++ b/lib/idea-plan-parser.ts @@ -13,7 +13,7 @@ import { type IdeaPlanFrontmatter, } from '@/lib/schemas/idea' -export type PlanParseError = { line?: number; message: string } +export type PlanParseError = { line?: number; message: string; hint?: string } export type PlanParseResult = | { ok: true; plan: IdeaPlanFrontmatter; body: string } @@ -43,14 +43,23 @@ export function parsePlanMd(md: string): PlanParseResult { parsed = parseYaml(frontmatterRaw) } catch (err) { if (err instanceof YAMLParseError) { + const yamlLine = err.linePos?.[0]?.line + const fileLine = yamlLine != null ? yamlLine + 1 : undefined + const offendingLine = + yamlLine != null + ? frontmatterRaw.split(/\r?\n/)[(yamlLine ?? 1) - 1] + : undefined + const isMarkdown = + offendingLine != null && + (/^\s*\d+\.\s+\*\*/.test(offendingLine) || + /^\s*[-*]\s+\*\*/.test(offendingLine) || + /^\s*\d+\..*:/.test(offendingLine)) + const hint = isMarkdown + ? 'Lijkt op markdown-content (genummerde of opsommingslijst) binnen YAML-frontmatter. Verplaats deze regels naar na de afsluitende `---`, of zet ze in een `description: |` blok.' + : undefined return { ok: false, - errors: [ - { - line: err.linePos?.[0]?.line, - message: err.message, - }, - ], + errors: [{ line: fileLine, message: err.message, hint }], } } return {