Comprehensive TypeScript type definitions and interfaces for the Slidev presentation framework ecosystem
—
Core data structures for slide information, markdown processing, and presentation data management.
Core interfaces for representing slide data and metadata.
/**
* Base slide information interface
*/
interface SlideInfoBase {
/** Revision identifier for the slide */
revision: string;
/** Frontmatter data as key-value pairs */
frontmatter: Record<string, any>;
/** Main slide content */
content: string;
/** Raw frontmatter string */
frontmatterRaw?: string;
/** Speaker notes for the slide */
note?: string;
/** Slide title extracted from content or frontmatter */
title?: string;
/** Heading level for the slide title */
level?: number;
}
/**
* Source slide information with file positioning
*/
interface SourceSlideInfo extends SlideInfoBase {
/** The filepath of the markdown file */
filepath: string;
/** The index of the slide in the markdown file */
index: number;
/** The range of the slide in the markdown file */
start: number;
contentStart: number;
end: number;
/** Raw slide content including frontmatter */
raw: string;
/** Raw content before being processed by preparsers */
contentRaw: string;
/** Slides imported by this slide */
imports?: SourceSlideInfo[];
/** YAML document for frontmatter parsing */
frontmatterDoc?: YAML.Document;
/** Style of frontmatter formatting */
frontmatterStyle?: FrontmatterStyle;
}
/**
* Processed slide information for rendering
*/
interface SlideInfo extends SlideInfoBase {
/** The index of the slide in the presentation */
index: number;
/** The importers of this slide. Empty array if entry markdown file */
importChain?: SourceSlideInfo[];
/** The source slide where the content is from */
source: SourceSlideInfo;
/** Processed HTML for speaker notes */
noteHTML?: string;
}Interface for updating slide content.
/**
* Editable fields for a slide
*/
type SlidePatch = Partial<Pick<SlideInfoBase, 'content' | 'note' | 'frontmatterRaw'>> & {
/** Skip HMR update for this patch */
skipHmr?: boolean;
/** The frontmatter patch (only the changed fields), null to remove a field */
frontmatter?: Record<string, any>;
}Main data structure containing all presentation information.
/**
* Complete Slidev presentation data structure
*/
interface SlidevData {
/** Slides that should be rendered (disabled slides excluded) */
slides: SlideInfo[];
/** Entry markdown file information */
entry: SlidevMarkdown;
/** Resolved presentation configuration */
config: SlidevConfig;
/** Presentation headmatter data */
headmatter: Record<string, unknown>;
/** Detected features used in the presentation */
features: SlidevDetectedFeatures;
/** Theme metadata if available */
themeMeta?: SlidevThemeMeta;
/** All markdown files in the presentation */
markdownFiles: Record<string, SlidevMarkdown>;
/** From watched files to indexes of slides that must be reloaded */
watchFiles: Record<string, Set<number>>;
}Structure representing a markdown file containing slides.
/**
* Slidev markdown file representation
*/
interface SlidevMarkdown {
/** File path of the markdown file */
filepath: string;
/** Raw markdown content */
raw: string;
/** All slides in this markdown file */
slides: SourceSlideInfo[];
/** Parse errors if any */
errors?: { row: number, message: string }[];
}Interface for detecting features used in presentations.
/**
* Features detected in the Slidev presentation
*/
interface SlidevDetectedFeatures {
/** Whether KaTeX math rendering is used */
katex: boolean;
/** Monaco editor usage, false or referenced module specifiers */
monaco: false | {
types: string[];
deps: string[];
};
/** Whether Twitter embeds are used */
tweet: boolean;
/** Whether Mermaid diagrams are used */
mermaid: boolean;
}Metadata structure for Slidev themes.
/**
* Metadata for "slidev" field in themes' package.json
*/
interface SlidevThemeMeta {
/** Default configuration values */
defaults?: Partial<SlidevConfig>;
/** Supported color schema */
colorSchema?: 'dark' | 'light' | 'both';
/** Preferred highlighter */
highlighter?: 'shiki';
}Interface for slide routing information.
/**
* Slide route information for Vue router
*/
interface SlideRoute {
/** Slide number */
no: number;
/** Route metadata including slide information */
meta: RouteMeta & Required<Pick<RouteMeta, 'slide'>>;
/** Load the slide component itself */
load: () => Promise<{ default: RouteComponent }>;
/** Wrapped async component */
component: Component;
}Interface for extending slide preprocessing.
/**
* Preparser extension interface for custom slide processing
*/
interface SlidevPreparserExtension {
/** Extension name */
name?: string;
/** Transform raw lines before parsing */
transformRawLines?: (lines: string[]) => Promise<void> | void;
/** Transform slide content */
transformSlide?: (content: string, frontmatter: any) => Promise<string | undefined>;
/** Transform speaker notes */
transformNote?: (note: string | undefined, frontmatter: any) => Promise<string | undefined>;
}
/**
* Preparser extension loader function type
*/
type PreparserExtensionLoader = (
headmatter: Record<string, unknown>,
filepath: string,
mode?: string
) => Promise<SlidevPreparserExtension[]>;Additional utility types for slide processing.
/**
* Frontmatter style format types
*/
type FrontmatterStyle = 'frontmatter' | 'yaml';
/**
* Render context types
*/
type RenderContext = 'none' | 'slide' | 'overview' | 'presenter' | 'previewNext';Working with Slide Data:
import type { SlidevData, SlideInfo, SlidePatch } from "@slidev/types";
function processSlideData(data: SlidevData) {
console.log(`Presentation: ${data.config.title}`);
console.log(`Total slides: ${data.slides.length}`);
// Process each slide
data.slides.forEach((slide: SlideInfo, index: number) => {
console.log(`Slide ${index + 1}:`);
console.log(` Title: ${slide.title || 'Untitled'}`);
console.log(` Layout: ${slide.frontmatter.layout || 'default'}`);
console.log(` Source: ${slide.source.filepath}:${slide.source.index}`);
if (slide.noteHTML) {
console.log(` Has speaker notes`);
}
});
// Check detected features
if (data.features.katex) {
console.log('KaTeX math rendering detected');
}
if (data.features.monaco) {
console.log('Monaco editor detected with types:', data.features.monaco.types);
}
}Updating Slide Content:
function updateSlideContent(slideIndex: number, patch: SlidePatch) {
const updateData = {
...patch,
skipHmr: false // Enable HMR by default
};
if (patch.frontmatter) {
console.log('Updating frontmatter:', patch.frontmatter);
}
if (patch.content) {
console.log('Updating slide content');
}
if (patch.note) {
console.log('Updating speaker notes');
}
// Apply the patch (pseudo-implementation)
return applyPatch(slideIndex, updateData);
}
// Example usage
updateSlideContent(0, {
content: '# Updated Title\n\nNew content here',
frontmatter: {
layout: 'cover',
background: 'blue'
},
note: 'Updated speaker notes'
});Processing Markdown Files:
function analyzeMarkdownFile(markdown: SlidevMarkdown) {
console.log(`File: ${markdown.filepath}`);
console.log(`Slides: ${markdown.slides.length}`);
if (markdown.errors && markdown.errors.length > 0) {
console.log('Parse errors found:');
markdown.errors.forEach(error => {
console.log(` Line ${error.row}: ${error.message}`);
});
}
// Analyze slides in the file
markdown.slides.forEach((slide, index) => {
console.log(` Slide ${index + 1} (${slide.start}-${slide.end}):`);
console.log(` Content length: ${slide.content.length}`);
console.log(` Frontmatter keys: ${Object.keys(slide.frontmatter).join(', ')}`);
if (slide.imports && slide.imports.length > 0) {
console.log(` Imports ${slide.imports.length} other slides`);
}
});
}Working with Preparser Extensions:
const customPreparser: SlidevPreparserExtension = {
name: 'custom-preprocessor',
transformRawLines: async (lines: string[]) => {
// Process raw lines before parsing
for (let i = 0; i < lines.length; i++) {
if (lines[i].includes('{{custom}}')) {
lines[i] = lines[i].replace('{{custom}}', 'Processed by custom preparser');
}
}
},
transformSlide: async (content: string, frontmatter: any) => {
// Transform slide content based on frontmatter
if (frontmatter.useCustomTransform) {
return content.replace(/\$\{(\w+)\}/g, (match, variable) => {
return frontmatter[variable] || match;
});
}
return content;
},
transformNote: async (note: string | undefined, frontmatter: any) => {
// Transform speaker notes
if (note && frontmatter.enhanceNotes) {
return `Enhanced: ${note}`;
}
return note;
}
};Interface for table of contents item structure.
/**
* Table of contents item interface
*/
interface TocItem {
/** Slide number */
no: number;
/** Whether this item is currently active */
active?: boolean;
/** Whether this item is an active parent */
activeParent?: boolean;
/** Child TOC items */
children: TocItem[];
/** Whether this item has an active parent */
hasActiveParent?: boolean;
/** Nesting level */
level: number;
/** Title level for heading hierarchy */
titleLevel: number;
/** Path to the slide */
path: string;
/** Whether to hide this item in TOC */
hideInToc?: boolean;
/** Item title */
title?: string;
}Interface for Vite plugin configuration.
/**
* Slidev plugin options for Vite integration
*/
interface SlidevPluginOptions {
vue?: ArgumentsType<typeof Vue>[0];
vuejsx?: ArgumentsType<typeof VueJsx>[0];
markdown?: ArgumentsType<typeof Markdown>[0];
components?: ArgumentsType<typeof Components>[0];
icons?: ArgumentsType<typeof Icons>[0];
remoteAssets?: ArgumentsType<typeof RemoteAssets>[0];
serverRef?: ArgumentsType<typeof ServerRef>[0];
unocss?: UnoCSSConfig;
staticCopy?: ViteStaticCopyOptions;
inspect?: ViteInspectOptions;
}Install with Tessl CLI
npx tessl i tessl/npm-slidev--types