Thank you for your interest in contributing to @create-markdown! This document provides guidelines and instructions for contributing.
Please read and follow our Code of Conduct.
This project is a monorepo managed with Turborepo and pnpm.
create-markdown/
├── packages/
│ ├── core/ # @create-markdown/core - Zero-dep parsing/serialization
│ ├── mdx/ # @create-markdown/mdx - Markdown to MDX conversion
│ ├── react/ # @create-markdown/react - React components and hooks
│ ├── preview/ # @create-markdown/preview - HTML rendering with plugins
│ ├── docs/ # @create-markdown/docs - Documentation site
│ └── create-markdown/ # Convenience bundle re-exporting all packages
├── playground/ # Demo application
└── .changeset/ # Changesets for version management
-
Fork and clone the repository
git clone https://github.com/YOUR_USERNAME/create-markdown.git cd create-markdown -
Install dependencies
pnpm install
-
Build all packages
pnpm run build
-
Run tests
pnpm run test -
Run the playground
pnpm run playground
Each package can be developed independently:
# Build a specific package
cd packages/core
pnpm run build
# Watch mode
pnpm run dev
# Run package tests
pnpm run test| Script | Description |
|---|---|
pnpm run build |
Build all packages |
pnpm run test |
Run all tests |
pnpm run typecheck |
Type check all packages |
pnpm run lint |
Lint all packages |
pnpm run clean |
Clean all build artifacts |
pnpm run playground |
Run the demo playground |
When making changes that should be released, add a changeset:
pnpm changesetThis will prompt you to:
- Select which packages have changed
- Choose the semver bump type (major, minor, patch)
- Write a summary of the changes
When to add a changeset:
- Bug fixes (patch)
- New features (minor)
- Breaking changes (major)
- Documentation changes affecting usage (patch)
When NOT to add a changeset:
- Internal refactoring without API changes
- Test additions
- CI/CD changes
- README updates (unless affecting usage)
Use descriptive branch names with prefixes:
feature/- New featuresfix/- Bug fixesdocs/- Documentationrefactor/- Code refactoringtest/- Test additions/changes
Examples:
feature/katex-pluginfix/inline-code-parsingdocs/react-hooks-guide
Follow Conventional Commits:
type(scope): description
[optional body]
[optional footer]
Types:
feat- New featurefix- Bug fixdocs- Documentationstyle- Formatting (no code change)refactor- Code refactoringtest- Adding testschore- Maintenance tasks
Scopes:
core- @create-markdown/corereact- @create-markdown/reactpreview- @create-markdown/previewplayground- Demo appci- CI/CDdeps- Dependencies
Examples:
feat(preview): add KaTeX plugin for math rendering
fix(core): handle empty code blocks correctly
docs(react): add useBlockEditor examples
-
Create a feature branch
git checkout -b feature/my-feature
-
Make your changes
- Write clear, documented code
- Add tests for new functionality
- Update documentation as needed
-
Run checks locally
pnpm run build pnpm run typecheck pnpm run test -
Add a changeset (if applicable)
pnpm changeset
-
Push and create a PR
git push origin feature/my-feature
-
Fill out the PR template
- Describe your changes
- Link related issues
- Check the checklist
- Use explicit types for function parameters and returns
- Prefer interfaces over type aliases for object shapes
- Use JSDoc comments for public APIs
- Follow existing patterns in the codebase
/**
* Parses markdown string into blocks
*
* @param markdown - The markdown string to parse
* @param options - Optional parsing options
* @returns Array of parsed blocks
*
* @example
* ```ts
* const blocks = parse('# Hello\n\nWorld');
* ```
*/
export function parse(
markdown: string,
options?: MarkdownParseOptions
): Block[] {
// ...
}- 2-space indentation
- Single quotes for strings
- No semicolons
- Max line length: 100 characters
// 1. Imports (external, then internal)
import React from 'react';
import type { Block } from '@create-markdown/core';
// 2. Types and interfaces
export interface MyProps {
// ...
}
// 3. Constants
const DEFAULT_OPTIONS = {
// ...
};
// 4. Helper functions (private)
function helperFunction() {
// ...
}
// 5. Main exports
export function mainFunction() {
// ...
}We use Vitest for testing.
# Run all tests
pnpm run test
# Run tests for a specific package
cd packages/core
pnpm run test
# Watch mode
pnpm run test:watch
# With coverage
pnpm run test -- --coverageimport { describe, it, expect } from 'vitest';
import { parse, stringify } from '../src';
describe('parse', () => {
it('should parse headings', () => {
const blocks = parse('# Hello');
expect(blocks[0].type).toBe('heading');
expect(blocks[0].props.level).toBe(1);
});
});Aim for 80%+ coverage. Focus on:
- Core parsing/serialization logic
- Edge cases and error handling
- Public API contracts
- Zero dependencies (except devDependencies)
- All functions should be pure when possible
- Comprehensive JSDoc comments
- Peer dependency on React 18+
- Server component compatible when possible
- Hooks follow React conventions
- Plugins are optional peer dependencies
- Web Component follows custom elements spec
- CSS themes are self-contained
- Open a GitHub Discussion
- Check existing issues
- Read the ROADMAP for planned features
By contributing, you agree that your contributions will be licensed under the MIT License.