feat: support .md and .mdx file uploads#8995
Conversation
Plain-text files have no magic bytes, so the file-type signature detector returned an empty MIME type and the backend rejected them. Add an extension-based fallback for markdown/mdx, allow text/mdx in the API and editor allow-lists, and pick a file icon for these extensions.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughAdds MDX support across the stack by allowing the "text/mdx" MIME type, adding extension-based MIME detection for plain-text formats, and mapping markdown/MDX extensions to the text attachment icon. (48 words) ChangesMDX support and extension-based detection
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/services/src/file/helper.ts (1)
112-135:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winDo not fall back to the extension after filename validation fails.
validateFilename()already flags suspicious names such asfoo.exe.md, but the result is only logged. With the new extension fallback, those files still resolve totext/markdown/text/mdxand can pass the allow-list, which defeats the double-extension safeguard.Suggested fix
const validateAndDetectFileType = async (file: File): Promise<string> => { // Basic filename validation const filenameError = validateFilename(file.name); if (filenameError) { console.warn(`File validation warning: ${filenameError}`); + return ""; } try { const signatureType = await detectMimeTypeFromSignature(file); if (signatureType) { return signatureType;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/services/src/file/helper.ts` around lines 112 - 135, If validateFilename(file.name) returns an error, stop and do not use the extension fallback; in validateAndDetectFileType, after calling validateFilename use the returned filenameError to short-circuit and return an empty string (or otherwise mark the file as unknown/rejected) instead of continuing to detectMimeTypeFromExtension. Keep the existing signature-based detection path (detectMimeTypeFromSignature) but only run it when validateFilename passed; reference validateAndDetectFileType, validateFilename, detectMimeTypeFromSignature, and detectMimeTypeFromExtension when making this change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@packages/services/src/file/helper.ts`:
- Around line 112-135: If validateFilename(file.name) returns an error, stop and
do not use the extension fallback; in validateAndDetectFileType, after calling
validateFilename use the returned filenameError to short-circuit and return an
empty string (or otherwise mark the file as unknown/rejected) instead of
continuing to detectMimeTypeFromExtension. Keep the existing signature-based
detection path (detectMimeTypeFromSignature) but only run it when
validateFilename passed; reference validateAndDetectFileType, validateFilename,
detectMimeTypeFromSignature, and detectMimeTypeFromExtension when making this
change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: ba97d0e1-9b14-4903-9ecf-89c664a15ef5
📒 Files selected for processing (4)
apps/api/plane/settings/common.pyapps/web/core/components/icons/attachment/attachment-icon.tsxpackages/editor/src/core/constants/config.tspackages/services/src/file/helper.ts
There was a problem hiding this comment.
Pull request overview
This PR extends Plane’s attachment upload flow to recognize Markdown and MDX files end-to-end by adding extension-based MIME fallback in the shared upload helper, allowing text/mdx through the editor/API allow-lists, and showing text-file icons for markdown attachments.
Changes:
- Added extension-based MIME detection for plain-text uploads (
.md,.markdown,.mdx) when signature detection returns no type. - Updated frontend and backend attachment MIME allow-lists to include MDX support.
- Mapped markdown-family file extensions to the existing text attachment icon.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
packages/services/src/file/helper.ts |
Adds filename-extension fallback for markdown MIME detection in the shared upload metadata helper. |
packages/editor/src/core/constants/config.ts |
Adds text/mdx to the editor attachment MIME allow-list. |
apps/web/core/components/icons/attachment/attachment-icon.tsx |
Routes md / markdown / mdx extensions to the text-file icon. |
apps/api/plane/settings/common.py |
Adds text/mdx to the backend attachment MIME allow-list and removes a duplicate markdown entry. |
| // Plain-text formats (markdown, mdx, …) have no magic bytes — fall back to extension. | ||
| const extensionType = detectMimeTypeFromExtension(file.name); | ||
| if (extensionType) { | ||
| return extensionType; | ||
| } | ||
|
|
||
| // fallback for unknown files |
| "application/vnd.openxmlformats-officedocument.presentationml.presentation", | ||
| "text/plain", | ||
| "text/markdown", | ||
| "text/mdx", |
| case "md": | ||
| case "markdown": | ||
| case "mdx": |
- Short-circuit validateAndDetectFileType when validateFilename flags a suspicious name so files like foo.exe.md cannot bypass the attachment allowlist via the new extension MIME fallback. - Lowercase fileType in getFileIcon so uppercase extensions (e.g. .MD, .PDF) resolve to the correct icon.
Summary
.mdand.mdxfiles to flow through the existing attachment upload pipeline.text/mdx(text/markdownwas already present); removed a duplicatetext/markdownentry.text/mdx; attachment icon picker handlesmd/markdown/mdx.Changes
packages/services/src/file/helper.ts— fallback totext/markdown/text/mdxfrom extension whenfile-typesignature detection yields nothing.packages/editor/src/core/constants/config.ts— addtext/mdxtoACCEPTED_ATTACHMENT_MIME_TYPES.apps/api/plane/settings/common.py— addtext/mdxtoATTACHMENT_MIME_TYPES; drop duplicatetext/markdown.apps/web/core/components/icons/attachment/attachment-icon.tsx— renderTxtIconformd/markdown/mdx.Notes
MDX has no IANA-registered MIME type;
text/mdxis a de-facto convention. Open to aliasing.mdxtotext/markdowninstead if preferred — that would avoid the backend allow-list change.Test plan
.mdfile as an issue attachment — succeeds; correct icon is shown..mdxfile as an issue attachment — succeeds; correct icon is shown..md/.mdxinto the rich-text editor as an attachment — accepted.foo.exe.md) are still rejected..bin) are still rejected with the existing error.Summary by CodeRabbit
New Features
Bug Fixes