From b9b9d19df4e43a7d2091c8e212edaba1b32f3208 Mon Sep 17 00:00:00 2001 From: liufree Date: Thu, 22 Jan 2026 00:13:27 +0800 Subject: [PATCH] feat: fix issues --- AGENTS.md | 247 +++++++++++++++++++++++++ src/pages/bases/DashMemoryCardView.tsx | 14 +- src/pages/bases/DashTableView.tsx | 4 +- 3 files changed, 260 insertions(+), 5 deletions(-) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..d36fab1 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,247 @@ +# AGENTS.md - Obsidian QueryDash Plugin + +This document provides essential information for AI agents working on the Obsidian QueryDash plugin codebase. + +## Project Overview + +Obsidian QueryDash is a plugin that provides enhanced views for Obsidian Bases and Dataview data, offering table, list, timeline, and memory card views with features similar to Notion databases. + +## Build Commands + +### Development +```bash +npm run dev # Build with watch mode for development +``` + +### Production +```bash +npm run build # Build for production +``` + +### Version Management +```bash +npm run version # Bump version and update manifest.json +``` + +## Code Quality & Linting + +### ESLint Configuration +- Uses TypeScript ESLint with recommended rules +- Run linting: `npx eslint . --ext .ts,.tsx` +- Configuration file: `.eslintrc` + +### Key ESLint Rules +- `no-unused-vars`: Off (handled by TypeScript version) +- `@typescript-eslint/no-unused-vars`: Error (except function arguments) +- `@typescript-eslint/ban-ts-comment`: Off (allows TypeScript directives) +- `@typescript-eslint/no-empty-function`: Off + +### Editor Configuration +- **Indentation**: Tabs (4 spaces width) +- **Line Endings**: LF +- **Charset**: UTF-8 +- **Final Newline**: Required +- Configuration file: `.editorconfig` + +## TypeScript Configuration + +### Compiler Options (`tsconfig.json`) +- **Target**: ES6 +- **Module**: ESNext +- **JSX**: React +- **Strict**: `noImplicitAny`, `strictNullChecks` +- **Module Resolution**: Node +- **Allow Synthetic Default Imports**: true +- **Lib**: DOM, ES5, ES6, ES7 + +### Type Checking +```bash +npx tsc --noEmit # Type check without emitting files +``` + +## Code Style Guidelines + +### File Structure +- Source code in `src/` directory +- Main entry point: `src/main.tsx` +- Pages/components in `src/pages/` +- Models in `src/models/` +- Components in `src/components/` + +### Naming Conventions +- **Files**: PascalCase for components (e.g., `QueryDashView.tsx`), camelCase for utilities +- **Components**: PascalCase (e.g., `DashTableView`, `QueryDashView`) +- **Variables/Functions**: camelCase +- **Types/Interfaces**: PascalCase +- **Constants**: UPPER_SNAKE_CASE + +### Import Organization +1. External dependencies (React, Obsidian) +2. Internal modules +3. Type imports +4. Style imports + +Example: +```typescript +import React, {useEffect, useState} from 'react'; +import {App} from "obsidian"; +import TableView from "./tableview/TableView"; +import {ConfigProvider, theme} from "antd"; +``` + +### React Components +- Use functional components with TypeScript +- Define props interfaces with `interface` keyword +- Use `React.FC` type for components +- Prefer explicit return types for complex components + +Example: +```typescript +interface QueryDashViewProps { + app: App; + source: string; +} + +const QueryDashView: React.FC = ({app, source}) => { + // Component implementation +}; +``` + +### TypeScript Usage +- Always use TypeScript strict mode +- Define explicit types for function parameters and return values +- Use interfaces for object shapes +- Avoid `any` type; use `unknown` or specific types +- Use optional chaining (`?.`) and nullish coalescing (`??`) for safe property access + +### Error Handling +- Use try-catch blocks for async operations +- Log errors with appropriate context +- Return meaningful error messages to users +- Validate inputs before processing + +### State Management +- Use React hooks (`useState`, `useEffect`) +- Keep state as local as possible +- Lift state up when shared between components +- Use proper dependency arrays in `useEffect` + +### Styling +- Use Ant Design components as primary UI library +- Theme follows Obsidian's dark/light mode +- Custom styles in CSS when needed +- Responsive design considerations + +## Testing + +### Current Status +- No formal test framework configured +- Manual testing through Obsidian plugin installation +- Consider adding Jest/Vitest for unit tests + +### Recommended Test Structure +```bash +tests/ +├── unit/ # Unit tests +├── integration/ # Integration tests +└── e2e/ # End-to-end tests +``` + +## Dependencies + +### Core Dependencies +- **React**: UI library +- **Ant Design**: Component library +- **Obsidian API**: Plugin framework +- **Dataview**: Data querying + +### Development Dependencies +- **TypeScript**: Type safety +- **ESLint**: Code linting +- **Vite**: Build tool +- **Husky**: Git hooks +- **lint-staged**: Pre-commit linting + +## Git Workflow + +### Commit Messages +- Use conventional commits format +- Start with type: `feat:`, `fix:`, `docs:`, `style:`, `refactor:`, `test:`, `chore:` +- Keep first line under 50 characters +- Provide detailed description in body + +### Branch Strategy +- `main`: Production releases +- `dev`: Development branch +- Feature branches: `feature/description` +- Bug fix branches: `fix/issue-description` + +### Pre-commit Hooks +- Husky configured for pre-commit hooks +- lint-staged runs ESLint on staged files +- Ensure code passes linting before commit + +## Plugin Development Notes + +### Obsidian Plugin API +- Extend `Plugin` class +- Register markdown code block processors +- Register Bases views when applicable +- Clean up resources in `onunload()` + +### Build Output +- Main file: `main.js` +- Styles: `styles.css` +- Manifest: `manifest.json` +- Source maps in development mode + +### Version Management +- Update `manifest.json` version +- Update `versions.json` for compatibility +- Use `npm run version` script + +## Performance Considerations + +- Use React.memo for expensive components +- Implement virtualization for large lists +- Lazy load heavy components +- Optimize re-renders with proper dependency arrays +- Monitor bundle size with Vite build + +## Security Best Practices + +- Sanitize user inputs +- Validate file paths and URLs +- Use Obsidian's safe APIs for file operations +- Avoid eval() or similar dangerous functions +- Keep dependencies updated + +## Troubleshooting + +### Common Issues +1. **Build failures**: Check TypeScript errors first +2. **Plugin not loading**: Verify manifest.json and main.js exist +3. **UI not rendering**: Check React component errors in console +4. **Type errors**: Ensure proper TypeScript configuration + +### Debugging +- Use `console.log` with appropriate context +- Check browser developer tools +- Enable source maps in development +- Test in Obsidian's developer mode + +## Contributing Guidelines + +1. Follow existing code patterns and conventions +2. Add TypeScript types for new features +3. Update documentation when changing APIs +4. Test changes in Obsidian before committing +5. Keep bundle size minimal + +## Resources + +- [Obsidian Plugin Docs](https://docs.obsidian.md/Home) +- [React Documentation](https://react.dev/) +- [TypeScript Handbook](https://www.typescriptlang.org/docs/) +- [Ant Design Components](https://ant.design/components/overview/) +- [Vite Documentation](https://vitejs.dev/guide/) \ No newline at end of file diff --git a/src/pages/bases/DashMemoryCardView.tsx b/src/pages/bases/DashMemoryCardView.tsx index d3d713c..2ac7bff 100644 --- a/src/pages/bases/DashMemoryCardView.tsx +++ b/src/pages/bases/DashMemoryCardView.tsx @@ -26,7 +26,10 @@ export class DashMemoryCardView extends BasesView { // 按 sr-due 升序排序 this.sortedCards = [...allCards] .map(function (card) { - return {card, due: card.getValue('note.sr-due')}; + const dueValue = card.getValue('note.sr-due'); + // Convert Value to string for dayjs + const dueString = dueValue?.toString() || ''; + return {card, due: dueString}; }) .sort((a, b) => { if (!a.due && !b.due) return 0; @@ -180,13 +183,18 @@ const MemoryCard: React.FC = ({ useEffect(() => { if (mdRef.current && !rendered) { - // 修正:传递一个 Obsidian Component 实例,避免内存泄漏 + // 创建一个简单的组件实例 + const component = { + load: () => {}, + unload: () => {} + }; + MarkdownRenderer.render( app, markdown, mdRef.current, filePath, - null + component as any ); setRendered(true); } diff --git a/src/pages/bases/DashTableView.tsx b/src/pages/bases/DashTableView.tsx index 2892ab1..0f62b74 100644 --- a/src/pages/bases/DashTableView.tsx +++ b/src/pages/bases/DashTableView.tsx @@ -159,11 +159,11 @@ const const [columns, setColumns] = React.useState[]>([]); - function parseTableResult(rows: any, params: any): Array> { + function parseTableResult(rows: any[], params: any): Array> { delete params.current; delete params.pageSize; - const filteredData = rows.filter(item => { + const filteredData = rows.filter((item: Record) => { return Object.keys(params).every(key => { if (params[key]) { if (item[key]) {