This guide covers building, testing, and contributing to the MarkView open-source edition.
- Prerequisites
- Getting Started
- Project Structure
- Build System
- Development Workflow
- Testing
- Code Style
- Architecture Overview
- Common Tasks
- Troubleshooting
- Node.js 18.0.0 or higher (Download)
- pnpm 8.0.0 or higher (Installation)
- Git 2.0 or higher
node --version # Should be v18.0.0 or higher
pnpm --version # Should be 8.0.0 or higher
git --version # Should be 2.0 or higherIf you don't have pnpm installed:
npm install -g pnpmgit clone https://github.com/markview-app/markview.git
cd markviewpnpm installThis will install all required packages listed in package.json.
# Development build (with source maps)
pnpm run dev
# Production build (minified)
pnpm run buildThe extension will be built to the dist/ directory.
- Open Chrome and navigate to
chrome://extensions/ - Enable "Developer mode" (toggle in top-right)
- Click "Load unpacked"
- Select the
dist/folder from the project directory - Enable "Allow access to file URLs" in extension details
markview/
├── src/ # Source code
│ ├── core/ # Core rendering engine
│ │ ├── markdown.ts # Markdown-it configuration
│ │ ├── document-renderer.ts # Document rendering logic
│ │ ├── lifecycle.ts # Extension lifecycle
│ │ └── plugins/ # Markdown-it plugins
│ ├── components/ # UI components
│ │ ├── theme-toggle.ts # Theme switcher
│ │ └── toc-sidebar.ts # Table of contents
│ ├── utils/ # Utility functions
│ │ ├── dom.ts # DOM manipulation
│ │ ├── logger.ts # Logging utility
│ │ └── i18n.ts # Internationalization
│ ├── styles/ # CSS stylesheets
│ │ ├── main.css # Main styles
│ │ ├── themes.css # Theme definitions
│ │ └── syntax-highlighting.css
│ ├── manifest.json # Extension manifest
│ └── main.ts # Entry point
├── build/ # Build configuration
│ ├── webpack.common.js # Shared webpack config
│ ├── webpack.dev.js # Development config
│ └── webpack.prod.js # Production config
├── docs/ # Documentation
├── examples/ # Sample markdown files
├── tests/ # Unit tests
├── dist/ # Build output (generated)
├── package.json # Dependencies
├── tsconfig.json # TypeScript config
└── README.md # This file# Development
pnpm run dev # Build with watch mode (auto-rebuild on changes)
pnpm run dev:clean # Clean build + watch mode
# Production
pnpm run build # Production build (minified)
pnpm run build:clean # Clean + production build
# Utilities
pnpm run clean # Remove dist/ folder
pnpm run lint # Run ESLint
pnpm run lint:fix # Fix ESLint issues
pnpm run format # Format code with Prettier
pnpm run format:check # Check code formatting
pnpm run type-check # TypeScript type checking
# Testing
pnpm run test # Run tests with watch mode
pnpm run test:run # Run tests once
pnpm run test:coverage # Generate coverage report
pnpm run test:ui # Open Vitest UIDevelopment Mode (pnpm run dev):
- Source maps enabled for debugging
- No minification (faster builds)
- Watch mode for auto-rebuild
- Detailed error messages
Production Mode (pnpm run build):
- Minified code
- Optimized bundle size
- Source maps disabled
- Ready for distribution
-
Create a feature branch:
git checkout -b feature/your-feature-name
-
Start development server:
pnpm run dev
-
Make your changes in
src/ -
Test in browser:
- Changes auto-rebuild with watch mode
- Refresh the extension:
chrome://extensions/→ Click reload icon - Or use
Ctrl+Ron the markdown page
-
Lint and format:
pnpm run lint:fix pnpm run format
-
Run tests:
pnpm run test -
Commit changes:
git add . git commit -m "feat: add your feature description"
We follow Conventional Commits:
feat:- New featurefix:- Bug fixdocs:- Documentation changesstyle:- Code style changes (formatting, no logic change)refactor:- Code refactoringperf:- Performance improvementstest:- Test additions or changeschore:- Build process or tooling changes
Examples:
git commit -m "feat: add KaTeX math rendering support"
git commit -m "fix: resolve TOC scroll sync issue"
git commit -m "docs: update README with new features"# Watch mode (recommended during development)
pnpm run test
# Single run (for CI)
pnpm run test:run
# Coverage report
pnpm run test:coverage
# Interactive UI
pnpm run test:uiWe use Vitest for testing. Create test files adjacent to source files:
src/utils/dom.ts
src/utils/dom.test.tsExample test:
import { describe, it, expect } from 'vitest';
import { stripMarkdownSyntax } from './dom';
describe('stripMarkdownSyntax', () => {
it('should remove heading markers', () => {
expect(stripMarkdownSyntax('### Hello World')).toBe('Hello World');
});
it('should remove bold syntax', () => {
expect(stripMarkdownSyntax('**bold text**')).toBe('bold text');
});
});Aim for:
- 80%+ coverage for core utilities
- 100% coverage for critical rendering logic
- Unit tests for pure functions
- Integration tests for component interactions
- Use TypeScript for all new code
- Enable strict mode (already configured)
- Avoid
anytype - use specific types orunknown - Use interfaces for object shapes
- Export types from dedicated type files
Example:
// Good
interface MarkdownOptions {
theme: 'light' | 'dark';
plugins: string[];
}
function renderMarkdown(options: MarkdownOptions): string {
// Implementation
}
// Avoid
function renderMarkdown(options: any): any {
// Implementation
}We use Prettier for automatic formatting:
# Format all files
pnpm run format
# Check formatting
pnpm run format:checkPrettier settings (.prettierrc):
- 2 spaces indentation
- Single quotes
- Semicolons
- 100 character line length
We use ESLint for code quality:
# Check for issues
pnpm run lint
# Auto-fix issues
pnpm run lint:fixKey rules:
- No unused variables
- No console.log in production code (use logger utility)
- Prefer
constoverlet - Always use
===instead of==
1. Pure TypeScript Architecture
- No UI frameworks (React, Vue, Angular)
- Direct DOM manipulation
- TypeScript classes for components
- Event-driven communication
2. Modular Design
- Core rendering engine (
src/core/) - Reusable components (
src/components/) - Utility functions (
src/utils/) - Clear separation of concerns
3. Plugin System
- Markdown-it plugins for extended syntax
- Centralized plugin registry
- Priority-based installation
4. State Management
- State passed as function parameters (no globals)
- Type-safe state objects
- Explicit data flow
src/main.ts- Entry point, initializes extensionsrc/core/markdown.ts- Markdown rendering configurationsrc/core/document-renderer.ts- Document rendering pipelinesrc/manifest.json- Extension configuration
For detailed architecture documentation, see the main MarkView repository's TECH_STACK_AND_ARCHITECTURE.md.
-
Install the plugin:
pnpm add markdown-it-plugin-name
-
Add to
src/core/plugins/registry.ts:import pluginName from 'markdown-it-plugin-name'; export const PLUGINS = { // ... existing plugins pluginName: [pluginName, /* options */] };
-
Update manifest and rebuild:
pnpm run build
-
Create component file:
touch src/components/my-component.ts touch src/styles/my-component.css
-
Implement component class:
export class MyComponent { private container: HTMLElement; constructor() { this.container = this.createContainer(); } private createContainer(): HTMLElement { const div = document.createElement('div'); div.className = 'my-component'; return div; } public render(): void { document.body.appendChild(this.container); } public destroy(): void { this.container.remove(); } }
-
Import CSS in
src/main.ts:import './styles/my-component.css';
# Update all dependencies
pnpm update
# Update specific package
pnpm update package-name
# Check for outdated packages
pnpm outdatedError: Cannot find module 'xyz'
Solution:
pnpm installError: TypeScript compilation errors Solution:
pnpm run type-check
# Fix reported type errorsProblem: Extension doesn't appear in browser Solution:
- Check
dist/folder exists - Ensure
manifest.jsonis indist/ - Check browser console for errors
- Try rebuilding:
pnpm run build:clean
Problem: Changes don't trigger rebuild Solution:
- Stop watch mode (
Ctrl+C) - Run
pnpm run clean - Restart:
pnpm run dev
Problem: Tests fail after changes Solution:
- Check test file matches implementation
- Run
pnpm run test:coverageto see coverage - Clear test cache:
pnpm run test -- --clearCache
- Use
pnpm run devfor development (faster than production builds) - Enable webpack caching (already configured)
- Close unnecessary applications to free up system resources
- Avoid large dependencies
- Use tree-shaking (import only what you need)
- Check bundle analysis: Add
webpack-bundle-analyzerif needed
- Documentation: docs/
- GitHub Issues: Report bugs
- GitHub Discussions: Ask questions
- Check existing documentation
- Search closed GitHub issues
- Try debugging with browser DevTools (F12)
- Check browser console for errors
Happy coding! 🚀
Last Updated: January 2026