|
1 | 1 | # Contributing to MDXEditor |
2 | 2 |
|
3 | | -First things first, if you're doing something in the space, [contact me over the email in my profile](https://github.com/petyosi/). |
4 | | -The project is still in its infancy, and I would love to get additional perspective. |
| 3 | +## Getting Started |
5 | 4 |
|
6 | | -Bundling is done with Vite, and tests are using Vitest. Ladle is used for examples. |
| 5 | +Install dependencies: |
7 | 6 |
|
8 | | -To preview the available examples in the browser, run `npm dev`. |
| 7 | +```bash |
| 8 | +npm install |
| 9 | +``` |
| 10 | + |
| 11 | +Run the development server with component examples: |
| 12 | + |
| 13 | +```bash |
| 14 | +npm run dev |
| 15 | +``` |
| 16 | + |
| 17 | +This starts Ladle on <http://localhost:61000> where you can browse and test the examples. |
| 18 | + |
| 19 | +## Development Commands |
| 20 | + |
| 21 | +**Build and development:** |
| 22 | + |
| 23 | +- `npm run build` - Build the library with Vite |
| 24 | +- `npm run dev` - Start Ladle dev server (component explorer) |
| 25 | +- `npm start` - Alias for `npm run dev` |
| 26 | + |
| 27 | +**Code quality:** |
| 28 | + |
| 29 | +- `npm run typecheck` - Run TypeScript type checking |
| 30 | +- `npm run lint` - Lint source files with ESLint |
| 31 | + |
| 32 | +**Testing:** |
| 33 | + |
| 34 | +- `npm test` - Run Vitest in watch mode |
| 35 | +- `npm run test:once` - Run Vitest once (CI mode) |
| 36 | + |
| 37 | +Tests are located in `src/test/**/*.test.{ts,tsx}` |
| 38 | + |
| 39 | +## Project Architecture |
| 40 | + |
| 41 | +MDXEditor is built on: |
| 42 | + |
| 43 | +- **React 18/19** with TypeScript |
| 44 | +- **Lexical** - Facebook's extensible text editor framework |
| 45 | +- **Gurx** - Reactive state management library |
| 46 | +- **MDAST** - Markdown abstract syntax tree |
| 47 | + |
| 48 | +### Plugin System |
| 49 | + |
| 50 | +The editor uses a plugin architecture with Gurx for state management. Each feature is implemented as a plugin that can: |
| 51 | + |
| 52 | +- Register custom Lexical nodes |
| 53 | +- Add markdown import/export visitors |
| 54 | +- Provide toolbar UI components |
| 55 | +- Manage feature-specific state |
| 56 | + |
| 57 | +**Plugin structure:** |
| 58 | + |
| 59 | +```typescript |
| 60 | +export const myPlugin = realmPlugin({ |
| 61 | + init: (realm, params) => { |
| 62 | + /* register nodes, visitors, cells */ |
| 63 | + }, |
| 64 | + postInit: (realm, params) => { |
| 65 | + /* access other plugins' state */ |
| 66 | + }, |
| 67 | + update: (realm, params) => { |
| 68 | + /* handle prop updates */ |
| 69 | + } |
| 70 | +}) |
| 71 | +``` |
| 72 | + |
| 73 | +### Key Directories |
| 74 | + |
| 75 | +- `src/plugins/` - Plugin implementations (headings, lists, table, image, codeblock, etc.) |
| 76 | +- `src/plugins/core/` - Core plugin with fundamental functionality |
| 77 | +- `src/plugins/toolbar/` - Toolbar UI components |
| 78 | +- `src/examples/` - Ladle stories (component examples) |
| 79 | +- `src/jsx-editors/` - Editors for JSX components |
| 80 | +- `src/directive-editors/` - Editors for directives (admonitions, etc.) |
| 81 | +- `src/styles/` - CSS modules and theming |
| 82 | +- `src/utils/` - Utility functions |
| 83 | +- `src/test/` - Test files |
| 84 | + |
| 85 | +### Markdown Conversion |
| 86 | + |
| 87 | +The editor maintains bidirectional conversion between markdown and Lexical's internal state: |
| 88 | + |
| 89 | +**Import (Markdown → Lexical):** |
| 90 | + |
| 91 | +- Parses markdown to MDAST using micromark |
| 92 | +- Converts MDAST nodes to Lexical nodes using the `MdastImportVisitor` interface |
| 93 | + |
| 94 | +**Export (Lexical → Markdown):** |
| 95 | + |
| 96 | +- Converts Lexical nodes to MDAST using `LexicalExportVisitor` interface |
| 97 | +- Serializes MDAST to markdown |
| 98 | + |
| 99 | +Each plugin registers both import and export visitors for its node types. |
| 100 | + |
| 101 | +## Coding Conventions |
| 102 | + |
| 103 | +- Use path alias `@/` for imports from `src/` directory |
| 104 | +- CSS Modules with camelCase class names |
| 105 | +- Gurx exports suffixed with `$` (e.g., `markdown$`, `applyBlockType$`) |
| 106 | +- Lexical functions prefixed with `$` for editor read/update cycles (e.g., `$isCodeBlockNode`) |
| 107 | +- TypeScript strict mode enabled |
| 108 | + |
| 109 | +## Adding a New Feature |
| 110 | + |
| 111 | +1. Create a new plugin in `src/plugins/your-feature/` |
| 112 | +2. Implement custom Lexical nodes if needed |
| 113 | +3. Add MDAST import/export visitors for markdown conversion |
| 114 | +4. Add toolbar components if needed |
| 115 | +5. Create examples in `src/examples/` |
| 116 | +6. Write tests in `src/test/` |
| 117 | +7. Export the plugin from `src/index.ts` |
| 118 | + |
| 119 | +## Pull Requests |
| 120 | + |
| 121 | +- Ensure `npm run typecheck` and `npm run lint` pass |
| 122 | +- Add tests for new features |
| 123 | +- Update examples in `src/examples/` to demonstrate the feature |
| 124 | +- Keep commits focused and well-described |
0 commit comments