Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
346 changes: 346 additions & 0 deletions docs/content/7.kb/3.migration-from-mdx.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,346 @@
---
title: Migrating from MDX
description: How to convert MDX content to Comark syntax.
navigation:
title: Migration from MDX
links:
- label: Component Syntax
icon: i-lucide-puzzle
to: /syntax/components
color: neutral
variant: soft
- label: Attributes
icon: i-lucide-settings
to: /syntax/attributes
color: neutral
variant: soft
---

If you're coming from MDX, this guide maps every MDX concept to its Comark equivalent. The core idea is the same, embed components in Markdown — but Comark uses a text-friendly syntax instead of JSX.

---

## Quick Comparison

| Concept | MDX | Comark |
|---------|-----|--------|
| Block component | `<Alert>...</Alert>` | `::alert ... ::` |
| Inline component | `<Badge>text</Badge>` | `:badge[text]` |
| Props | `<Alert type="info">` | `::alert{type="info"}` |
| Self-closing | `<Divider />` | `::divider` |
| Dynamic binding | `year={year}` | `:year="year"` |
| Children | JSX children | Markdown between `::` delimiters |
| Imports | `import X from './X'` | Component registered in renderer |
| Exports | `export const x = 1` | Frontmatter or application state |

---

## Components

### Block Components

MDX uses JSX tags. Comark uses `::` fences:

::code-group
```js [MDX]
<Alert type="info">
This is an important message with **bold** text.
</Alert>
```

```mdc [Comark]
::alert{type="info"}
This is an important message with **bold** text.
::
```
::

### Inline Components

::code-group
```js [MDX]
Status: <Badge color="green">Active</Badge>
```

```mdc [Comark]
Status: :badge[Active]{color="green"}
```
::

### Self-Closing Components

::code-group
```js [MDX]
<Divider />
<Chart color="#fcb32c" />
```

```mdc [Comark]
‎::divider

‎::chart{color="#fcb32c"}
```
::

### Nested Components

::code-group
```js [MDX]
<Card title="Example">
<List>
- Item 1
- Item 2
</List>
</Card>
```

```mdc [Comark]
::card{title="Example"}
:::list
- Item 1
- Item 2
:::
::
```
::

Nesting in Comark uses increasing colons: `::` for outer, `:::` for inner, `::::` for deeper levels.

---

## Props & Attributes

### Static Props

::code-group
```js [MDX]
<Alert type="info" dismissible>
Content
</Alert>
```

```mdc [Comark]
::alert{type="info" dismissible}
Content
::
```
::

### Dynamic / Expression Binding

MDX uses JSX curly-brace expressions. Comark uses `:prop="value"` binding syntax:

::code-group
```js [MDX]
<Chart year={currentYear} data={chartData} />
```

```mdc [Comark]
‎::chart{:year="currentYear" :data="chartData"}
```
::

The `:` prefix marks a prop as a dynamic binding — the value is treated as an expression rather than a literal string.

### Numeric & Boolean Props

::code-group
```js [MDX]
<Grid columns={3} fluid={true} />
```

```mdc [Comark]
‎::grid{:columns="3" fluid}
```
::

Boolean props without a value default to `true` in both formats.

---

## Imports & Component Registration

MDX imports components per-file. In Comark, components are registered once in the renderer:

::code-group
```js [MDX]
import Alert from './components/Alert'
import Chart from './components/Chart'

# Dashboard

<Alert type="info">Welcome!</Alert>

<Chart data={metrics} />
```

```vue [Comark (Vue)]
<script setup>
import { Comark } from '@comark/vue'
import Alert from './components/Alert.vue'
import Chart from './components/Chart.vue'

const markdown = `
# Dashboard

::alert{type="info"}
Welcome!
::

‎::chart{:data="metrics"}
`
</script>

<template>
<Suspense>
<Comark :components="{ Alert, Chart }">{{ markdown }}</Comark>
</Suspense>
</template>
```

```tsx [Comark (React)]
import { Comark } from '@comark/react'
import { Alert } from './components/Alert'
import { Chart } from './components/Chart'

const markdown = `
# Dashboard

::alert{type="info"}
Welcome!
::

‎::chart{:data="metrics"}
`

export default function Page() {
return <Comark components={{ Alert, Chart }}>{markdown}</Comark>
}
```
::

For shared defaults, use `defineComarkComponent` to avoid passing components everywhere:

```typescript
import { defineComarkComponent } from '@comark/vue' // or '@comark/react'
import Alert from './components/Alert'
import Chart from './components/Chart'

export const DocsComark = defineComarkComponent({
name: 'DocsComark',
components: { Alert, Chart },
})
```

---

## Exports & State

MDX uses `export` statements to define page-level variables:

```js
export const year = 2023

# Report for {year}
```

Comark doesn't support inline JavaScript expressions. Instead, use frontmatter for static metadata and application state for dynamic values:

::code-group
```mdc [Frontmatter]
---
year: 2023
---

# Report for {{ year }}
```

```vue [Application State (Vue)]
<script setup>
const year = ref(2023)
const markdown = computed(() => `# Report for ${year.value}`)
</script>

<template>
<Suspense>
<Comark>{{ markdown }}</Comark>
</Suspense>
</template>
```
::

---

## Expressions in Text

MDX allows JavaScript expressions anywhere in text:

```js
The result is {2 + 3}.
Today is {new Date().toLocaleDateString()}.
```

Comark does not evaluate inline expressions. Compute values in your application code and interpolate them into the markdown string before parsing:

```typescript
const result = 2 + 3
const today = new Date().toLocaleDateString()

const markdown = `
The result is ${result}.
Today is ${today}.
`

const tree = await parse(markdown)
```

---

## Layouts

MDX supports layout components via default exports:

```js
export { default } from './layouts/BlogPost'

# My Post
```

In Comark, wrap the renderer with your layout component:

```vue
<template>
<BlogPostLayout>
<Suspense>
<Comark>{{ content }}</Comark>
</Suspense>
</BlogPostLayout>
</template>
```

---

## Markdown Features

Standard markdown works identically in both formats. No changes needed for:

- Headings, paragraphs, lists
- Bold, italic, strikethrough
- Links and images
- Code blocks and inline code
- Blockquotes
- Tables
- Horizontal rules

---

## Migration Checklist

1. **Replace JSX tags** with Comark `::component` / `:component` syntax
2. **Move imports** from per-file `import` statements to renderer `components` option
3. **Convert expression props** `prop={expr}` to `:prop="expr"`
4. **Replace inline expressions** `{expr}` with template string interpolation
5. **Move exports** to frontmatter or application state
6. **Remove layout exports** and wrap with layout components instead
7. **Register plugins** (math, mermaid, highlight) in your renderer setup

File renamed without changes.
Loading