Thank you for your interest in contributing to Slides Extended! This guide will help you get started with development.
This repository has a few distinct codebases with a hard boundary between them:
| Codebase | Branch | What lives there |
|---|---|---|
src/, test/, se-test-vault/ |
main |
Obsidian plugin — runs inside Obsidian as a Node.js/Electron process |
reveal-dist/ submodule |
reveal-dist |
reveal.js assets — rendered only by a browser (iframe or exported HTML) |
| docs source | docs |
Documentation site (Hugo-based SSG; some translation required for edits) |
- Plugin code (UI, settings, markdown processors, the preview panel):
src/onmain - Browser-rendered presentation content (reveal.js plugins, themes, layout CSS, HTML templates):
reveal-distsubmodule - Documentation updates:
docsbranch (Ex-hugo SSG, now mostly markdown; some translation of content is required for hosting)
- Node.js (version 18 or higher recommended)
- pnpm - This project uses pnpm as its package manager
-
Clone the repository with submodules:
git clone --recurse-submodules git@github.com:ebullient/obsidian-slides-extended.git
Or, if you already cloned without submodules:
git submodule update --init
-
Install dependencies for the main plugin:
pnpm install
-
Build the reveal.js distribution assets (required for the plugin to serve presentations):
cd reveal-dist && pnpm install && pnpm build && cd ..
This populates
reveal-dist/build/withcss/,dist/,plugin/, andtemplate/which the plugin's HTTP server serves at runtime.
# Start development mode (watch mode with hot reload)
pnpm dev
# Run tests
pnpm test
# Run tests with coverage
pnpm coverage
# Run a single test file
jest test/basicSyntax.unit.test.ts
# Lint and format check
pnpm lint
# Auto-fix linting and formatting issues
pnpm fix
# Production build (runs tests and biome check first)
pnpm buildFor testing the plugin in Obsidian during development:
-
Set the
OUTDIRenvironment variable to your Obsidian vault's plugin directory:export OUTDIR="/path/to/your/vault/.obsidian/plugins/slides-extended"
-
Run
pnpm devto watch and build automatically -
The plugin will hot-reload in Obsidian (requires the
.hotreloadfile which is created automatically)
This project uses Biome for linting and formatting (a modern alternative to ESLint/Prettier).
- Configuration is in biome.json
- 4-space indentation
- Double quotes for JavaScript
- Auto-organize imports
Before submitting a PR, ensure:
pnpm fix # Fix any auto-fixable issues
pnpm test # All tests pass
pnpm build # Production build succeedsTests are located in the test/ directory:
*.unit.test.ts- Unit test files__snapshots__/- Jest snapshot files for regression testing__mocks__/- Mock implementations (e.g., Obsidian utilities)fixtures/- Test fixture files
When adding new features or processors:
- Create a test file in
test/(e.g.,myFeature.unit.test.ts) - Test both the processor directly and end-to-end markdown transformation
- Use snapshot tests for complex HTML transformations
- Mock
ObsidianUtilswhen needed (it's excluded from coverage as it depends on Obsidian APIs)
Example test structure:
import { MarkdownProcessor } from '../src/obsidian/markdownProcessor';
import { mockObsidianUtils } from './__mocks__/mockObsidianUtils';
describe('MyFeature', () => {
let processor: MarkdownProcessor;
beforeEach(() => {
processor = new MarkdownProcessor(mockObsidianUtils);
});
it('should transform markdown correctly', () => {
const input = '...';
const result = processor.process(input, options);
expect(result).toMatchSnapshot();
});
});The core of Slides Extended is a multi-phase markdown processing pipeline in src/obsidian/markdownProcessor.ts. Understanding this is key to contributing:
-
Phase 1: Template Processing
- Runs iteratively with circuit breaker (max 10 iterations) to handle nested templates
MultipleFileProcessor- Handles file includes (![[other-file]])TemplateProcessor- Applies templates from YAML frontmatter
-
Phase 2: Slide Structure
SkipSlideProcessor- Removes slides marked to be hiddenDebugViewProcessor- Adds debug grid if enabledAutoClosingProcessor- Auto-closes self-closing HTML tagsDefaultBackgroundProcessor- Applies default backgrounds
-
Phase 3: Content Processing (executed in this specific order)
LatexProcessor- LaTeX/MathJax equationsEmojiProcessor- Emoji shortcode conversionIconsProcessor- FontAwesome iconsFormatProcessor- Text formattingMermaidProcessor- Mermaid diagramsBlockProcessor- Block-level transformationsFootnoteProcessor- Footnote handlingExcalidrawProcessor- Excalidraw drawing embedsMediaProcessor- Images/videosInternalLinkProcessor- Obsidian wikilinksReferenceProcessor- Block referencesFragmentProcessor- Reveal.js fragments (animations)DropProcessor- Drop layoutsGridProcessor- Grid layoutsCommentProcessor- Slide commentsChartProcessor- Chart.js integration
Important: The order of processors matters! For example, LatexProcessor must run before MediaProcessor to avoid conflicts. Each processor implements the Processor interface with a process(markdown: string, options: Options): string method.
-
Create your processor in src/obsidian/processors/:
import type { Options, Processor } from '../../@types'; export class MyProcessor implements Processor { process(markdown: string, options: Options): string { // Your transformation logic return transformedMarkdown; } }
-
Register it in src/obsidian/markdownProcessor.ts:
- Import the processor
- Instantiate it in the constructor
- Add it to the appropriate phase in the correct order
-
Write tests in test/
-
Update documentation if needed
Reveal.js distribution assets live in the reveal-dist submodule
(branch reveal-dist on this repo). Changes to reveal assets go there, not in the
main plugin source.
-
cd reveal-dist -
Add the npm package to
reveal-dist/package.json -
Update
reveal-dist/esbuild.config.mjsto copy the necessary files:copy({ assets: { from: ['node_modules/your-plugin/**/*'], to: ['./plugin/your-plugin/'], } })
-
Run
pnpm install && pnpm buildinsidereveal-dist/to verify the output
reveal-dist/ # git submodule (branch: reveal-dist)
├── plugin/ # Custom reveal.js plugins (source)
├── template/ # Mustache HTML templates (source)
├── package.json # Minimal deps: reveal.js ecosystem only
└── esbuild.config.mjs # Builds css/, dist/, plugin/, template/ to build/
src/
├── main.ts # Plugin entry point
├── slidesExtended-Plugin.ts # Core plugin class
├── reveal/ # Reveal.js integration (plugin-side)
│ ├── revealPreviewView.ts # Preview view
│ ├── revealServer.ts # Fastify HTTP server
│ ├── revealRenderer.ts # Markdown-to-HTML conversion
│ └── revealExporter.ts # PDF/HTML export
├── obsidian/ # Obsidian-specific processing
│ ├── markdownProcessor.ts # Core pipeline orchestrator
│ ├── processors/ # 15+ processor modules
│ ├── transformers/ # Style/attribute transformers
│ └── suggesters/ # Editor autocompletion
├── yaml/ # Configuration management
├── scss/ # Styles and themes
└── @types/ # TypeScript type definitions- Ensure
.hotreloadfile exists in your build directory - In dev mode, this is created automatically
- Restart Obsidian if hot reload stops working
- Check if you need to update snapshots:
jest -u - Ensure processors are added in the correct order
- Mock
ObsidianUtilsif your processor uses it
- Make sure all required assets are listed in esbuild.config.mjs
- Check that node_modules contains the expected files
- Try
rm -rf node_modules && pnpm install
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Make your changes
- Ensure tests pass and code is formatted (
pnpm fix && pnpm test) - Commit your changes with a clear message
- Push to your fork
- Open a Pull Request
- Use clear, descriptive commit messages
- Focus on the "why" rather than the "what"
- Examples:
- "Fix greedy embed pattern matching"
- "Add support for custom chart colors"
- "Improve error handling in media processor"
Releases are automated via GitHub Actions and are typically handled by maintainers:
- Manual workflow trigger with version bump (major/minor/patch)
- Runs tests and builds the plugin
- Creates GitHub release with artifacts
- Updates manifest.json and versions.json
- Open an issue for bugs or feature requests
- Check existing issues before creating a new one
- Be respectful and provide clear descriptions
This project is MIT licensed. By contributing, you agree that your contributions will be licensed under the MIT License.
Thank you for contributing to Slides Extended! 🎉