Conversation
WalkthroughAdds frontmatter image support: new Tauri file utilities and commands, Image field type in schema parsing/merging, editor drag-drop position checks, FileUploadButton and ImageField/ImageThumbnail React components, watcher schema-change events, query/store updates, plus documentation and test content updates. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant User
participant UI as ImageField UI
participant Tauri
participant FS as Filesystem
participant Store as Frontmatter Store
User->>UI: Click FileUploadButton / Drop file
UI->>Tauri: open_dialog() or receive drop path
Tauri-->>UI: absolute file path
UI->>Tauri: is_path_in_project(path, projectRoot)
Tauri->>FS: canonicalize & contains?
Tauri-->>UI: true / false
alt inside project
UI->>Tauri: get_relative_path(path, projectRoot)
Tauri-->>UI: relative path
UI->>Store: update frontmatter with relative path
else outside project
UI->>Tauri: copy_file_to_assets(path, collection/assets)
Tauri->>FS: copy to assets dir
Tauri-->>UI: asset path
UI->>Store: update frontmatter with asset path
end
UI->>UI: render ImageThumbnail -> resolve_image_path -> display preview
sequenceDiagram
autonumber
participant FSWatcher as Tauri Watcher
participant Parser as Zod Parser
participant Frontend as Frontend Store
participant UI
FSWatcher->>FSWatcher: detect file change
FSWatcher->>FSWatcher: is_schema_file(path)?
alt schema changed
FSWatcher->>Parser: parse updated schema (detect Image)
Parser-->>FSWatcher: schema + image fields
FSWatcher->>Frontend: emit schema-changed
else normal file
FSWatcher->>Frontend: emit file-changed
end
Frontend->>Frontend: invalidate collections query
Frontend->>UI: refresh schema -> render ImageField for image types
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related issues
Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (1)
🧰 Additional context used📓 Path-based instructions (1)src/components/**/*.tsx📄 CodeRabbit inference engine (CLAUDE.md)
Files:
🧬 Code graph analysis (3)src/components/frontmatter/fields/ImageField.tsx (9)
src/components/tauri/FileUploadButton.tsx (2)
src/components/frontmatter/fields/ImageThumbnail.tsx (2)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
🔇 Additional comments (3)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 11
🧹 Nitpick comments (18)
docs/tasks-todo/task-4-refactor-file-copying-logic.md (1)
1-220: Minor copyedits for clarity and lintCapitalize “Markdown” and replace bare URLs with link text to satisfy MD034. Content/plan reads well.
src-tauri/src/commands/watcher.rs (1)
112-154: Debounce can drop the final batch; consider a trailing flushprocess_events only runs after a >500ms gap followed by another event. If no further events arrive, buffered changes (incl. schema_changed) won’t emit. Recommend adding a timer-based trailing flush or a short sleep/drain loop.
Minimal tweak inside the loop:
// Replace the current debounce with: use tokio::time::{sleep, Duration}; tokio::spawn(async move { let mut event_buffer = Vec::new(); let mut last_event_time = std::time::Instant::now(); loop { match rx.recv_timeout(Duration::from_millis(100)) { Ok(event) => { event_buffer.push(event); last_event_time = std::time::Instant::now(); } Err(mpsc::RecvTimeoutError::Timeout) => { if !event_buffer.is_empty() && last_event_time.elapsed() > Duration::from_millis(500) { process_events(&app_handle, &mut event_buffer).await; event_buffer.clear(); } } Err(_) => break, // channel closed; flush before exit } } if !event_buffer.is_empty() { process_events(&app_handle, &mut event_buffer).await; } });This preserves debounce and guarantees a trailing flush.
src-tauri/src/schema_merger.rs (2)
711-742: Image type override works; ensure nested and array cases are covered by testsOverride from string→image and array→array
is correct. Please add tests asserting:
- nested path like coverImage.image becomes image
- array of images becomes array sub_type=image
744-792: Unified Zod extraction is clear; minor: don’t else-if array ref caseUsing else-if means a field with both referenced_collection and array_reference_collection (unlikely but safe) only records one. Consider independent checks for clarity.
- if let Some(collection) = field.referenced_collection { - reference_map.insert(field.name.clone(), collection); - } - // Array reference - else if let Some(collection) = field.array_reference_collection { - reference_map.insert(field.name.clone(), collection); - } + if let Some(collection) = field.referenced_collection { + reference_map.insert(field.name.clone(), collection); + } + if let Some(collection) = field.array_reference_collection { + reference_map.insert(field.name.clone(), collection); + }src/components/editor/Editor.tsx (1)
192-208: Tauri drag-drop listener: solid setup and guarded errors.
Good: await listen, capture UnlistenFn, and pass payload+view to handler. Consider logging the handler result in DEV for easier diagnostics.- unlistenDrop = await listen('tauri://drag-drop', event => { - void handleTauriFileDrop(event.payload, view) - }) + unlistenDrop = await listen('tauri://drag-drop', async event => { + const res = await handleTauriFileDrop(event.payload, view) + if (import.meta.env.DEV && !res.success) { + // eslint-disable-next-line no-console + console.warn('[DROP] failed:', res.error) + } + })src-tauri/src/commands/files.rs (1)
999-1016: Path containment check is correct and safe. Add tests.
Canonicalize + starts_with is appropriate. Please add unit tests for positive/negative cases (incl. symlink into/out of project if applicable).docs/tasks-todo/task-3-zod-parser-pattern-matching-rewrite.md (1)
58-61: Avoid fragile line-number references; anchor by function name instead.Line numbers drift quickly. Refer to function names and modules only (e.g., “parser.rs: parse_schema_fields()”) or add code anchors in comments.
docs/developer/architecture-guide.md (1)
142-176: Document the editor container data-attribute required by drop-bounds checks.Drag/drop now checks closest('[data-editor-container]'). Please add a note that the editor root element must include data-editor-container to enable correct bounds gating.
src/components/frontmatter/fields/ImageThumbnail.tsx (2)
19-55: Add unmount-safety in async effect to avoid setState on unmounted component.Prevent rare React warnings by guarding updates after unmount.
Apply this diff:
useEffect(() => { + let cancelled = false if (!path || !projectPath) { setImageUrl(null) setLoadingState('idle') return } const loadImage = async () => { setLoadingState('loading') try { @@ - setImageUrl(assetUrl) - setLoadingState('success') + if (!cancelled) { + setImageUrl(assetUrl) + setLoadingState('success') + } } catch { // Fail silently - don't show error state - setLoadingState('error') + if (!cancelled) setLoadingState('error') } } - void loadImage() + void loadImage() + return () => { + cancelled = true + } }, [path, projectPath, currentFile?.path])
71-79: Improve accessibility: alt should reflect the image path or label.Use a descriptive alt; fallback to file name.
Apply this diff:
- <img - src={imageUrl} - alt="Preview" + <img + src={imageUrl} + alt={`Image preview: ${path.split('/').pop() || path}`}src/components/frontmatter/fields/ImageField.tsx (1)
42-44: Reduce re-renders by selecting only the field’s value.Optional: subscribe to just the nested frontmatter value to avoid full frontmatter-driven re-renders.
Sketch:
const fieldValue = useEditorStore(s => getNestedValue(s.frontmatter, name))src/lib/editor/dragdrop/handlers.ts (3)
69-86: Gate debug logs behind DEV flag.Avoid noisy logs in production.
Apply this diff:
- // eslint-disable-next-line no-console - console.log('[DROP] Handler called, editorView:', !!editorView) + if (import.meta.env.DEV) { + // eslint-disable-next-line no-console + console.log('[DROP] Handler called, editorView:', !!editorView) + } @@ - // eslint-disable-next-line no-console - console.log('[DROP] Files:', filePaths.length, 'Position:', position) + if (import.meta.env.DEV) { + // eslint-disable-next-line no-console + console.log('[DROP] Files:', filePaths.length, 'Position:', position) + }Repeat the same pattern for other console.log calls below.
93-99: Fallback if container attribute isn’t present.Use editorView.dom when [data-editor-container] isn’t found.
Apply this diff:
- const editorElement = editorView.dom.closest('[data-editor-container]') + const editorElement = + editorView.dom.closest('[data-editor-container]') ?? editorView.dom
17-38: Return the declared FileDropPayload type for consistency.Reuse the exported type to reduce divergence across modules.
Apply this diff:
export const parseFileDropPayload = ( payload: unknown -): { paths: string[]; position?: { x: number; y: number } } => { +): FileDropPayload => { let filePaths: string[] = [] let position: { x: number; y: number } | undefined = undefined @@ - return { paths: [] } + return { paths: [] } @@ - return { paths: filePaths, position } + return { paths: filePaths, position }docs/tasks-done/task-images-in-frontmatter.md (1)
56-56: Format URL as proper markdown link (optional).The bare URL could be formatted as a proper markdown link for better readability and to satisfy markdown linting rules.
Apply this diff:
-It is not possible to know about this from the generated JSON schemas because they show any image fields as a string (the path to the file). So we have to do this by reading `content.config.json` Similar way to how we do it for references. See here for the docs on images in content collections: https://docs.astro.build/en/guides/images/#images-in-content-collections +It is not possible to know about this from the generated JSON schemas because they show any image fields as a string (the path to the file). So we have to do this by reading `content.config.json` Similar way to how we do it for references. See here for the [docs on images in content collections](https://docs.astro.build/en/guides/images/#images-in-content-collections).src/components/tauri/FileUploadButton.tsx (3)
168-173: Inconsistent async patterns between handlers.The click handler uses
async/await(lines 90-123), while the drag-drop handler usesPromise.resolve().finally(). Both work correctly, but using a consistent pattern improves code maintainability.Consider extracting the file processing logic into a shared async function:
const processFile = React.useCallback(async (filePath: string) => { setIsProcessing(true) try { await onFileSelectRef.current(filePath) } finally { setIsProcessing(false) } }, [])Then use it in both handlers:
// In click handler: await processFile(selected) // In drag-drop handler: void processFile(filePath)
149-153: Multiple dropped files: only first file processed.When multiple files are dropped, only the first file is processed (line 152) without informing the user that additional files were ignored. This could be confusing if a user accidentally drops multiple files.
Consider logging a warning in DEV mode when multiple files are dropped:
if (paths.length === 0) return + if (import.meta.env.DEV && paths.length > 1) { + // eslint-disable-next-line no-console + console.warn(`Multiple files dropped. Only processing the first file.`) + } + // Take the first file const filePath = paths[0]
195-207: Consider adding visual processing feedback (optional).The component disables the button during processing but provides no visual indication (like a spinner) that an operation is in progress. While the current design keeps the component flexible (consumers can customize children), users might be confused when the button becomes briefly unresponsive.
If you want to add built-in loading feedback, consider:
import { Loader2 } from 'lucide-react' // In render: <Button ...> {isProcessing && <Loader2 className="mr-2 size-4 animate-spin" />} {children} </Button>Alternatively, keep the current design and document that consumers can check for the disabled state to show their own loading indicators.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (29)
docs/developer/architecture-guide.md(2 hunks)docs/tasks-done/task-images-in-frontmatter.md(1 hunks)docs/tasks-todo/task-2-images-in-frontmatter.md(0 hunks)docs/tasks-todo/task-3-zod-parser-pattern-matching-rewrite.md(1 hunks)docs/tasks-todo/task-4-refactor-file-copying-logic.md(1 hunks)src-tauri/src/commands/files.rs(1 hunks)src-tauri/src/commands/watcher.rs(3 hunks)src-tauri/src/lib.rs(1 hunks)src-tauri/src/parser.rs(6 hunks)src-tauri/src/schema_merger.rs(7 hunks)src/components/editor/Editor.tsx(2 hunks)src/components/frontmatter/fields/FrontmatterField.tsx(2 hunks)src/components/frontmatter/fields/ImageField.tsx(1 hunks)src/components/frontmatter/fields/ImageThumbnail.tsx(1 hunks)src/components/tauri/FileUploadButton.tsx(1 hunks)src/components/tauri/index.ts(1 hunks)src/hooks/editor/useTauriListeners.ts(1 hunks)src/lib/editor/dragdrop/handlers.ts(2 hunks)src/lib/editor/dragdrop/index.ts(1 hunks)src/lib/editor/dragdrop/types.ts(1 hunks)src/lib/query-client.ts(1 hunks)src/lib/schema.ts(2 hunks)src/store/projectStore.ts(1 hunks)test/dummy-astro-project/.astro/collections/notes.schema.json(1 hunks)test/dummy-astro-project/.astro/content-assets.mjs(1 hunks)test/dummy-astro-project/src/content.config.ts(1 hunks)test/dummy-astro-project/src/content/articles/2023-12-05-schema-testing-article.md(1 hunks)test/dummy-astro-project/src/content/articles/2025-01-22-image-preview-test.md(1 hunks)test/dummy-astro-project/src/content/notes/test-nested-image.md(1 hunks)
💤 Files with no reviewable changes (1)
- docs/tasks-todo/task-2-images-in-frontmatter.md
🧰 Additional context used
📓 Path-based instructions (5)
src-tauri/**/*.rs
📄 CodeRabbit inference engine (CLAUDE.md)
Write and maintain Rust tests and code for the Tauri backend with modern Rust formatting (use format("{variable}"))
Files:
src-tauri/src/parser.rssrc-tauri/src/commands/files.rssrc-tauri/src/commands/watcher.rssrc-tauri/src/lib.rssrc-tauri/src/schema_merger.rs
docs/developer/architecture-guide.md
📄 CodeRabbit inference engine (CLAUDE.md)
Update docs/developer/architecture-guide.md whenever adding new architectural patterns
Files:
docs/developer/architecture-guide.md
src/lib/schema.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Centralize Zod schema parsing for frontmatter in src/lib/schema.ts
Files:
src/lib/schema.ts
src/components/**/*.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Use the Direct Store Pattern in React components (access Zustand stores directly) and never use React Hook Form
Files:
src/components/frontmatter/fields/ImageField.tsxsrc/components/tauri/FileUploadButton.tsxsrc/components/editor/Editor.tsxsrc/components/frontmatter/fields/FrontmatterField.tsxsrc/components/frontmatter/fields/ImageThumbnail.tsx
src/store/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
In Zustand stores, dispatch CustomEvent from store functions (no React hooks in stores) for cross-layer communication
Files:
src/store/projectStore.ts
🧠 Learnings (1)
📚 Learning: 2025-10-20T20:14:57.077Z
Learnt from: CR
PR: dannysmith/astro-editor#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-20T20:14:57.077Z
Learning: Applies to src/content/config.ts : Keep Astro content collections configuration in src/content/config.ts and ensure valid syntax for schema parsing
Applied to files:
test/dummy-astro-project/src/content.config.ts
🧬 Code graph analysis (8)
src-tauri/src/commands/files.rs (1)
src-tauri/src/models/file_entry.rs (1)
new(20-70)
src/lib/editor/dragdrop/handlers.ts (2)
src/lib/editor/dragdrop/index.ts (3)
parseFileDropPayload(23-23)FileDropPayload(38-38)isDropWithinElement(24-24)src/lib/editor/dragdrop/types.ts (1)
FileDropPayload(5-11)
src/components/frontmatter/fields/ImageField.tsx (8)
src/types/common.ts (1)
FieldProps(7-11)src/lib/schema.ts (1)
SchemaField(7-36)src/store/editorStore.ts (2)
useEditorStore(219-490)getNestedValue(77-95)src/store/projectStore.ts (1)
useProjectStore(42-405)src/lib/project-registry/path-resolution.ts (1)
getEffectiveAssetsDirectory(58-79)src/lib/constants.ts (1)
ASTRO_PATHS(2-8)src/components/tauri/FileUploadButton.tsx (1)
FileUploadButton(70-208)src/components/frontmatter/fields/ImageThumbnail.tsx (1)
ImageThumbnail(13-82)
src/components/tauri/FileUploadButton.tsx (2)
src/components/tauri/index.ts (2)
FileUploadButtonProps(9-9)FileUploadButton(8-8)src/components/ui/button.tsx (1)
buttonVariants(60-60)
src/store/projectStore.ts (2)
src/lib/query-client.ts (1)
queryClient(4-18)src/lib/query-keys.ts (1)
queryKeys(3-40)
src/components/editor/Editor.tsx (1)
src/lib/editor/dragdrop/handlers.ts (1)
handleTauriFileDrop(69-193)
src/components/frontmatter/fields/FrontmatterField.tsx (1)
src/components/frontmatter/fields/ImageField.tsx (1)
ImageField(36-247)
src-tauri/src/lib.rs (1)
src-tauri/src/commands/files.rs (2)
is_path_in_project(1008-1016)get_relative_path(1027-1038)
🪛 LanguageTool
docs/tasks-todo/task-3-zod-parser-pattern-matching-rewrite.md
[grammar] ~64-~64: Use a hyphen to join words.
Context: ...gested Approach 1. Create new pattern matching functions: ```rust fn f...
(QB_NEW_EN_HYPHEN)
docs/tasks-todo/task-4-refactor-file-copying-logic.md
[uncategorized] ~78-~78: Did you mean the formatting language “Markdown” (= proper noun)?
Context: ...y) 3. Maintains separation of concerns (markdown formatting stays in editor, UI logic st...
(MARKDOWN_NNP)
[uncategorized] ~152-~152: Did you mean the formatting language “Markdown” (= proper noun)?
Context: ... with call to shared function - Keep markdown formatting separate (formatAsMarkdown...
(MARKDOWN_NNP)
docs/tasks-done/task-images-in-frontmatter.md
[style] ~11-~11: ‘exactly the same’ might be wordy. Consider a shorter alternative.
Context: ...ped, it should be copied and renamed in exactly the same way as we currently do for images dragg...
(EN_WORDINESS_PREMIUM_EXACTLY_THE_SAME)
[style] ~11-~11: ‘exactly the same’ might be wordy. Consider a shorter alternative.
Context: ...re of the current collection, again, in exactly the same way that we do with dragging and droppi...
(EN_WORDINESS_PREMIUM_EXACTLY_THE_SAME)
[grammar] ~13-~13: Ensure spelling is correct
Context: ...We can probably use similar code to the folating image previews we recently implemented....
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~14-~14: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...d to display the component and maybe we need to have a button that when you press it, i...
(REP_NEED_TO_VB)
[style] ~14-~14: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ... the file or copies it or something. We need to think about the best UI for making this...
(REP_NEED_TO_VB)
[style] ~15-~15: As an alternative to the over-used intensifier ‘very’, consider replacing this phrase.
Context: ...ry this before, it got very complicated very quickly. ### Design Decisions UI Pattern:...
(EN_WEAK_ADJECTIVE)
🪛 markdownlint-cli2 (0.18.1)
docs/tasks-todo/task-4-refactor-file-copying-logic.md
56-56: Bare URL used
(MD034, no-bare-urls)
docs/tasks-done/task-images-in-frontmatter.md
56-56: Bare URL used
(MD034, no-bare-urls)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (rust)
🔇 Additional comments (27)
src/lib/query-client.ts (1)
3-18: LGTM! Well-configured for desktop app context.The QueryClient configuration is appropriate for a desktop application:
- Disabling
refetchOnWindowFocusprevents unnecessary refetches since file changes are handled by watchers- 5-minute
staleTimeand 10-minutegcTimeprovide good balance for a desktop app where data is relatively stableThe comments clearly explain the reasoning behind each choice.
src/lib/schema.ts (1)
47-61: Image type plumbing looks goodEnum + string mapping are consistent and safe; Unknown fallback preserved. No further changes needed.
Also applies to: 123-140
test/dummy-astro-project/.astro/collections/notes.schema.json (1)
77-88: Schema addition matches intended structurecoverImage with { image, alt } and additionalProperties:false looks correct and aligns with the content config. If this artifact is committed intentionally for tests, all good; otherwise consider excluding .astro outputs from VCS outside test fixtures.
test/dummy-astro-project/src/content.config.ts (1)
37-59: notes schema: image() integration looks correctFunction-form schema with image().optional() under coverImage is valid and matches the generated JSON schema. No changes needed.
If nested image fields aren’t yet rendered in the UI (per PR note), consider adding a small follow-up issue to track that gap.src-tauri/src/schema_merger.rs (2)
204-211: Good: Zod-driven enhancement after JSON parseApplying Zod info post-JSON preserves structure and augments types. Error handling via warn is fine.
862-875: Include Image in zod_type_to_field_type — goodMapping covers Image; fallback remains Unknown for future types.
test/dummy-astro-project/.astro/content-assets.mjs (1)
1-7: Auto-generated file - no review needed.This appears to be an auto-generated Astro content assets manifest that maps image imports to their resolved paths. The changes reflect the new image references added to test content files in this PR.
src/lib/editor/dragdrop/index.ts (1)
21-25: Clean API extension.Exporting
isDropWithinElementextends the drag-drop public API to support position-aware drop boundary validation, aligning well with the enhanced position tracking introduced in this PR.test/dummy-astro-project/src/content/articles/2023-12-05-schema-testing-article.md (1)
12-12: Appropriate test content.The addition of a relative image path in the
coverfield provides good test coverage for the new image field functionality.test/dummy-astro-project/src/content/articles/2025-01-22-image-preview-test.md (1)
9-9: Good test coverage.The absolute path syntax in the
coverfield complements the relative path test in the other article, providing comprehensive test coverage for different image path formats.src/hooks/editor/useTauriListeners.ts (1)
11-14: Good defensive programming.The early return prevents listener setup until the editor view is ready, avoiding potential null reference issues and unnecessary listener registration attempts.
src/lib/editor/dragdrop/types.ts (1)
7-10: Backward-compatible type extension.The optional
positionfield cleanly extendsFileDropPayloadto support position-aware drop handling while maintaining backward compatibility with existing code.test/dummy-astro-project/src/content/notes/test-nested-image.md (1)
9-11: Clarify nested image field support.The PR objectives state: "The change does not currently support .image() fields nested inside objects." However, this test file includes a nested
coverImage.imagefield. Please clarify whether:
- This is intentional test data for future nested image support
- The nested image schema is supported but only the sidebar rendering is not yet implemented
- This test case should be removed or modified
src/components/frontmatter/fields/FrontmatterField.tsx (2)
14-14: Clean import addition.
152-157: Well-integrated image field handling.The image field handler follows the established pattern used for other field types and is appropriately positioned in the conditional chain. The implementation adheres to the Direct Store Pattern guideline (confirmed by reviewing the ImageField component which uses
useEditorStore()anduseProjectStore.getState()directly).src/components/editor/Editor.tsx (1)
4-4: Imports look good and align with the drag/drop refactor.
No issues found.Also applies to: 9-9, 11-11
src/components/tauri/index.ts (1)
1-9: Barrel exports look good.
Clear and minimal API, no issues.src-tauri/src/lib.rs (1)
371-372: Commands exposed correctly.
Matches backend implementations; no issues.src/components/frontmatter/fields/ImageField.tsx (3)
42-47: Direct Store Pattern ✅Uses Zustand stores directly and getState() in async handlers. Aligns with our component guidelines.
82-106: All referenced Tauri commands exist and are properly registered.Verification confirms that
copy_file_to_assets,copy_file_to_assets_with_override,is_path_in_project, andget_relative_pathare all implemented insrc-tauri/src/commands/files.rswith the#[tauri::command]macro and registered in thegenerate_handler!macro insrc-tauri/src/lib.rs. The code inImageField.tsxcorrectly invokes these commands.Likely an incorrect or invalid review comment.
14-16: Import path is correct as-is.The index.ts file properly re-exports
getEffectiveAssetsDirectoryviaexport * from './path-resolution'(final line), confirming that importing from'../../../lib/project-registry'as a barrel export is valid and appropriate. No changes needed.docs/tasks-done/task-images-in-frontmatter.md (1)
423-468: Phase 5 completion status unclear.Phase 5 (Testing & Documentation) does not have a completion marker (✅) like Phases 0-4, but the PR appears to be ready for review. Clarify whether Phase 5 tasks have been completed or are pending.
If Phase 5 is complete, add the completion marker to maintain consistency with other phases.
src/components/tauri/FileUploadButton.tsx (5)
8-31: Well-structured types and props interface.The type definitions are clear, well-documented, and appropriate for the Tauri drag-drop API. The props interface provides good flexibility with optional styling props.
36-50: Helper functions are correct and handle edge cases.The extension validation logic properly handles files without extensions by returning false, which is the correct behavior.
79-87: Good use of refs to optimize effect dependencies.Storing the callback in a ref is the correct pattern to avoid unnecessary effect re-runs while ensuring the latest callback is always used.
90-123: Click handler is well-implemented.The file picker flow properly guards against concurrent operations, handles cancellation gracefully, and includes error handling. The file dialog filters should prevent selection of invalid file types, though explicit validation after selection could add an extra safety layer.
70-208: Component follows Direct Store Pattern guideline appropriately.This reusable component correctly uses the callback pattern (
onFileSelect) rather than directly accessing Zustand stores. This design allows the component to be used in various contexts. The coding guideline about Direct Store Pattern is more relevant for form fields that update specific application state, so this implementation is appropriate.Based on coding guidelines.
Adds support for Astro's
.image()helper, rendering a preview and file picker in the frontmatter sidebar where appropriate.Currently not supported inside nested objects.
Partially addresses #21 - everything except support for image fields in nested objects.
Summary by CodeRabbit
New Features
Improvements
Documentation