Skip to content

Markdown Support ​

The Markdown extension enables converting between markdown and JSON for your slide content. It's perfect for importing markdown files, exporting presentations, or programmatically working with content.

Not a markdown editor

This extension provides conversion tools, not real-time markdown editing. Users edit in the visual editor, and you can import/export markdown programmatically.

Installation ​

The Markdown extension is included in the ExtensionKit by default. If you're using a custom extension setup:

ts
import { Markdown } from '@blockslides/markdown'

const editor = useEditor({
  extensions: [
    // ... other extensions
    Markdown.configure({
      // optional configuration
    })
  ]
})

Importing Markdown ​

There are several ways to load markdown content into the editor:

At Initialization ​

Load markdown when creating the editor:

ts
const editor = useEditor({
  extensions: [Markdown],
  content: '# Welcome\n\nThis is a **slide** with markdown.',
  contentType: 'markdown'
})

Programmatically ​

Parse and insert markdown at any time:

ts
const markdown = `# My Slide

- First item
- Second item
- **Bold text**`

const json = editor.markdown.parse(markdown)
editor.commands.setContent(json)

Insert at Cursor ​

Insert markdown content at the current cursor position:

ts
const markdown = '## New Section\n\nSome content here.'

editor.commands.insertContent(markdown, { 
  contentType: 'markdown' 
})

Insert at Specific Position ​

Insert markdown at a specific document position:

ts
editor.commands.insertContentAt(100, markdown, { 
  contentType: 'markdown' 
})

Exporting Markdown ​

Get the current editor content as markdown:

ts
const markdown = editor.getMarkdown()

console.log(markdown)
// Output:
// # Welcome
// 
// This is a **slide** with markdown.

You can also serialize specific JSON content:

ts
const json = editor.getJSON()
const markdown = editor.markdown.serialize(json)

Configuration ​

Indentation ​

Control how nested content (like lists and code blocks) is indented:

ts
Markdown.configure({
  indentation: {
    style: 'space',  // 'space' or 'tab'
    size: 2          // number of spaces/tabs per level
  }
})

Examples:

ts
// Use tabs instead of spaces
indentation: { style: 'tab', size: 1 }

// Use 4 spaces
indentation: { style: 'space', size: 4 }

Custom Marked Instance ​

Provide your own configured marked instance:

ts
import { marked } from 'marked'

// Configure marked
marked.setOptions({
  gfm: true,
  breaks: false
})

// Use it in Blockslides
Markdown.configure({
  marked: marked
})

Marked Options ​

Pass options directly to marked.setOptions():

ts
Markdown.configure({
  markedOptions: {
    gfm: true,           // GitHub Flavored Markdown
    breaks: false,       // Line breaks as <br>
    pedantic: false,     // Strict markdown
    smartypants: false   // Typographic punctuation
  }
})

See the marked.js documentation for all available options.

Supported Markdown Syntax ​

The following markdown syntax is supported when you have the corresponding extensions enabled:

Text Formatting ​

  • **bold** → bold
  • *italic* → italic
  • ~~strikethrough~~ → strikethrough
  • `code` → code

Headings ​

markdown
# Heading 1
## Heading 2
### Heading 3
#### Heading 4
##### Heading 5
###### Heading 6

Lists ​

Bullet lists:

markdown
- Item 1
- Item 2
  - Nested item
  - Another nested
- Item 3

Numbered lists:

markdown
1. First item
2. Second item
3. Third item

Blockquotes ​

markdown
> This is a blockquote.
> It can span multiple lines.

Code Blocks ​

markdown
```javascript
function hello() {
  console.log('Hello, world!')
}
```

Images ​

markdown
![Alt text](https://example.com/image.jpg)

Horizontal Rules ​

markdown
---

Tables ​

If you're using the Table extension:

markdown
| Header 1 | Header 2 |
|----------|----------|
| Cell 1   | Cell 2   |
| Cell 3   | Cell 4   |

Math ​

If you're using the Mathematics extension:

markdown
Inline math: $E = mc^2$

Block math:
$$
\frac{n!}{k!(n-k)!}
$$

Markdown-Style Input Rules ​

While typing in the editor, you can use markdown-style shortcuts to quickly format content:

  • # → Heading 1
  • ## → Heading 2
  • ### → Heading 3
  • > → Blockquote
  • - → Bullet list
  • 1. → Numbered list
  • --- → Horizontal rule

Input rules are separate

These input rules are built into individual extensions (Heading, Blockquote, etc.), not the Markdown extension. They work automatically when you have those extensions enabled.

Working with Slides ​

Since Blockslides uses a slide-based structure, markdown conversion handles slides specially:

Single Slide ​

When you parse markdown with multiple blocks, they'll be wrapped in a single slide:

ts
const markdown = `
# Welcome

This is paragraph 1.

This is paragraph 2.
`

const json = editor.markdown.parse(markdown)
// Result: { type: 'doc', content: [{ type: 'slide', content: [...] }] }
// One doc containing one slide with heading and two paragraphs

Multiple Slides ​

To create multiple slides, you'll need to structure your JSON and then serialize/parse appropriately. Markdown doesn't have a native "slide break" concept, so you'll typically:

  1. Import markdown as a single slide
  2. Split content manually if needed
  3. Or structure your JSON with multiple slides first, then export

Common Use Cases ​

Import a Markdown File ​

ts
async function importMarkdown(file: File) {
  const text = await file.text()
  const json = editor.markdown.parse(text)
  editor.commands.setContent(json)
}

Export as Markdown File ​

ts
function exportMarkdown() {
  const markdown = editor.getMarkdown() // <--

  const blob = new Blob([markdown], { type: 'text/markdown' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = 'presentation.md'
  a.click()
  URL.revokeObjectURL(url)
}

Convert Between Formats ​

ts
// Markdown → JSON
const json = editor.markdown.parse(markdownString)

// JSON → Markdown
const markdown = editor.markdown.serialize(jsonContent)

// Get current content as markdown
const currentMarkdown = editor.getMarkdown()

Extending with Custom Markdown ​

Extensions can define custom markdown parsing and rendering. This allows you to add support for custom syntax.

Each extension can provide:

  • parseMarkdown - How to convert markdown tokens to JSON nodes
  • renderMarkdown - How to convert JSON nodes back to markdown
  • markdownTokenizer - Custom tokenization rules for unique syntax

For details on creating custom extensions with markdown support, see Creating Custom Extensions.