Skip to content

Commit eec3277

Browse files
committed
fix: context form now poperly supports diagrams and modules and validates them as pathspec/url elements for linking purposes
1 parent fbf5a68 commit eec3277

File tree

4 files changed

+148
-51
lines changed

4 files changed

+148
-51
lines changed

GENERATE-CONTEXT-PROMPT.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,16 @@ When generating a .context.md file:
139139
3. Ensure that all sections are filled with relevant and detailed information.
140140
4. If certain information is not available, make reasonable assumptions based on common practices in software development.
141141
5. Tailor the content to the specific type of project (e.g., web application, mobile app, data processing system) while maintaining the overall structure.
142-
6. When specifying related modules, include both the name of the module and its path. The path can be a local directory path (for modules within the same repository) or a URL (for external modules or modules in different repositories).
143-
7. In the diagrams section, include references to any architectural, flow, or other diagrams that help visualize the project's structure or processes. Provide both the name and path for each diagram.
142+
6. When specifying related modules, include both the name of the module and its path. The path must be a valid relative path specification from the current directory or .context.md file. These should be directories that contain a .context file.
143+
7. In the diagrams section, include references to any architectural, flow, or other diagrams that help visualize the project's structure or processes. Provide both the name and path for each diagram. Prefer .mermaid files for diagrams, but also allow other lightweight diagramming formats (see Diagram Specifications section).
144+
145+
## Diagram Specifications
146+
147+
When referencing diagrams in the .context.md file:
148+
149+
1. Prefer .mermaid files for diagrams. These offer the best support for context and markdown fluency.
150+
2. Other allowed file formats include: .mmd, .pdf, .png, .jpg, .jpeg.
151+
3. The diagram path should point to a specific file, not just a directory.
152+
4. When possible, include a brief description of what the diagram represents in the Markdown content section.
144153

145154
Remember, the goal is to create a .context.md file that provides valuable context for both human developers and AI assistants, enabling more effective collaboration and development on the project.

examples/context-editor/src/components/ContextForm.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ interface ContextFormProps {
1616

1717
export type FormDataType = {
1818
moduleName: string;
19-
relatedModules: string[];
19+
relatedModules: { name: string; path: string }[];
2020
version: string;
2121
description: string;
22-
diagrams: string[];
22+
diagrams: { name: string; path: string }[];
2323
technologies: string[];
2424
conventions: string;
2525
directives: string;
@@ -116,7 +116,7 @@ const ContextForm: React.FC<ContextFormProps> = ({ onSubmit }) => {
116116
}));
117117
};
118118

119-
const handleMultiChange = (field: string) => (event: React.SyntheticEvent, value: string[]) => {
119+
const handleMultiChange = (field: string) => (value: any) => {
120120
setFormData((prevData) => ({
121121
...prevData,
122122
[field]: value,

examples/context-editor/src/components/MetadataSection.tsx

Lines changed: 132 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,114 @@
1-
import React from 'react';
2-
import { Grid2, TextField, Chip, Autocomplete } from '@mui/material';
1+
import React, { useState } from 'react';
2+
import { Grid2, TextField, Chip, Autocomplete, Button, Box, Typography, Divider, Accordion, AccordionSummary, AccordionDetails } from '@mui/material';
3+
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
34
import { FormDataType } from './ContextForm';
45

56
interface MetadataSectionProps {
67
formData: FormDataType;
78
errors: { [key: string]: string };
89
handleChange: (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
9-
handleMultiChange: (field: string) => (event: React.SyntheticEvent, value: string[]) => void;
10+
handleMultiChange: (field: string) => (value: any) => void;
1011
}
1112

13+
interface NamePathPair {
14+
name: string;
15+
path: string;
16+
}
17+
18+
const NamePathInput: React.FC<{
19+
label: string;
20+
items: NamePathPair[];
21+
onAdd: (item: NamePathPair) => void;
22+
onRemove: (index: number) => void;
23+
validatePath: (path: string) => string | null;
24+
}> = ({ label, items, onAdd, onRemove, validatePath }) => {
25+
const [name, setName] = useState('');
26+
const [path, setPath] = useState('');
27+
const [error, setError] = useState<string | null>(null);
28+
29+
const handleAdd = () => {
30+
const validationError = validatePath(path);
31+
if (validationError) {
32+
setError(validationError);
33+
} else if (name && path) {
34+
onAdd({ name, path });
35+
setName('');
36+
setPath('');
37+
setError(null);
38+
}
39+
};
40+
41+
return (
42+
<Box sx={{ mb: 2 }}>
43+
<TextField
44+
label={`${label} Name`}
45+
value={name}
46+
onChange={(e) => setName(e.target.value)}
47+
fullWidth
48+
margin="normal"
49+
/>
50+
<TextField
51+
label={`${label} Path`}
52+
value={path}
53+
onChange={(e) => setPath(e.target.value)}
54+
fullWidth
55+
margin="normal"
56+
error={!!error}
57+
helperText={error}
58+
/>
59+
<Button onClick={handleAdd} variant="contained" color="primary" fullWidth sx={{ mt: 1 }}>
60+
Add {label}
61+
</Button>
62+
<Box sx={{ mt: 1 }}>
63+
{items.map((item, index) => (
64+
<Chip
65+
key={index}
66+
label={`${item.name} (${item.path})`}
67+
onDelete={() => onRemove(index)}
68+
style={{ margin: '4px' }}
69+
/>
70+
))}
71+
</Box>
72+
</Box>
73+
);
74+
};
75+
76+
const validateRelativeModulePath = (path: string): string | null => {
77+
if (!path.startsWith('./') && !path.startsWith('../')) {
78+
return 'Path must be a relative path (start with ./ or ../)';
79+
}
80+
if (path.endsWith('/')) {
81+
return 'Path must not end with a slash';
82+
}
83+
return null;
84+
};
85+
86+
const validateDiagramPath = (path: string): string | null => {
87+
const allowedExtensions = ['.mermaid', '.mmd', '.pdf', '.png', '.jpg', '.jpeg'];
88+
const extension = path.substring(path.lastIndexOf('.'));
89+
if (!allowedExtensions.includes(extension.toLowerCase())) {
90+
return `File must be one of: ${allowedExtensions.join(', ')}`;
91+
}
92+
return null;
93+
};
94+
1295
const MetadataSection: React.FC<MetadataSectionProps> = ({ formData, errors, handleChange, handleMultiChange }) => {
96+
const handleAddRelatedModule = (item: NamePathPair) => {
97+
handleMultiChange('relatedModules')([...formData.relatedModules, item]);
98+
};
99+
100+
const handleRemoveRelatedModule = (index: number) => {
101+
handleMultiChange('relatedModules')(formData.relatedModules.filter((_, i) => i !== index));
102+
};
103+
104+
const handleAddDiagram = (item: NamePathPair) => {
105+
handleMultiChange('diagrams')([...formData.diagrams, item]);
106+
};
107+
108+
const handleRemoveDiagram = (index: number) => {
109+
handleMultiChange('diagrams')(formData.diagrams.filter((_, i) => i !== index));
110+
};
111+
13112
return (
14113
<Grid2 container spacing={2}>
15114
<Grid2 size={12}>
@@ -24,27 +123,21 @@ const MetadataSection: React.FC<MetadataSectionProps> = ({ formData, errors, han
24123
/>
25124
</Grid2>
26125
<Grid2 size={12}>
27-
<Autocomplete
28-
multiple
29-
freeSolo
30-
options={[]}
31-
value={formData.relatedModules}
32-
onChange={handleMultiChange('relatedModules')}
33-
renderTags={(value: string[], getTagProps) =>
34-
value.map((option: string, index: number) => (
35-
<Chip variant="outlined" label={option} {...getTagProps({ index })} />
36-
))
37-
}
38-
renderInput={(params) => (
39-
<TextField
40-
{...params}
41-
variant="outlined"
42-
label="Related Modules"
43-
placeholder="Add module"
44-
helperText="Optional: Add related modules"
126+
<Divider sx={{ my: 2 }} />
127+
<Accordion>
128+
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
129+
<Typography>Related Modules</Typography>
130+
</AccordionSummary>
131+
<AccordionDetails>
132+
<NamePathInput
133+
label="Related Module"
134+
items={formData.relatedModules}
135+
onAdd={handleAddRelatedModule}
136+
onRemove={handleRemoveRelatedModule}
137+
validatePath={validateRelativeModulePath}
45138
/>
46-
)}
47-
/>
139+
</AccordionDetails>
140+
</Accordion>
48141
</Grid2>
49142
<Grid2 size={{ xs: 12, sm: 6 }}>
50143
<TextField
@@ -71,35 +164,30 @@ const MetadataSection: React.FC<MetadataSectionProps> = ({ formData, errors, han
71164
/>
72165
</Grid2>
73166
<Grid2 size={12}>
74-
<Autocomplete
75-
multiple
76-
freeSolo
77-
options={[]}
78-
value={formData.diagrams}
79-
onChange={handleMultiChange('diagrams')}
80-
renderTags={(value: string[], getTagProps) =>
81-
value.map((option: string, index: number) => (
82-
<Chip variant="outlined" label={option} {...getTagProps({ index })} />
83-
))
84-
}
85-
renderInput={(params) => (
86-
<TextField
87-
{...params}
88-
variant="outlined"
89-
label="Diagrams"
90-
placeholder="Add diagram"
91-
helperText="Optional: Add diagram file paths or URLs"
167+
<Divider sx={{ my: 2 }} />
168+
<Accordion>
169+
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
170+
<Typography>Diagrams</Typography>
171+
</AccordionSummary>
172+
<AccordionDetails>
173+
<NamePathInput
174+
label="Diagram"
175+
items={formData.diagrams}
176+
onAdd={handleAddDiagram}
177+
onRemove={handleRemoveDiagram}
178+
validatePath={validateDiagramPath}
92179
/>
93-
)}
94-
/>
180+
</AccordionDetails>
181+
</Accordion>
95182
</Grid2>
96183
<Grid2 size={12}>
184+
<Divider sx={{ my: 2 }} />
97185
<Autocomplete
98186
multiple
99187
freeSolo
100188
options={[]}
101189
value={formData.technologies}
102-
onChange={handleMultiChange('technologies')}
190+
onChange={(_, value) => handleMultiChange('technologies')(value)}
103191
renderTags={(value: string[], getTagProps) =>
104192
value.map((option: string, index: number) => (
105193
<Chip variant="outlined" label={option} {...getTagProps({ index })} />

examples/context-editor/src/generateContextMd.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import yaml from 'js-yaml';
22

33
interface FormData {
44
moduleName: string;
5-
relatedModules: string[];
5+
relatedModules: { name: string; path: string }[];
66
version: string;
77
description: string;
8-
diagrams: string[];
8+
diagrams: { name: string; path: string }[];
99
technologies: string[];
1010
conventions: string;
1111
directives: string;

0 commit comments

Comments
 (0)