diff --git a/docs/content/7.kb/3.migration-from-mdx.md b/docs/content/7.kb/3.migration-from-mdx.md new file mode 100644 index 0000000..58fc91f --- /dev/null +++ b/docs/content/7.kb/3.migration-from-mdx.md @@ -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 ... ::` | +| Inline component | `text` | `:badge[text]` | +| Props | `` | `::alert{type="info"}` | +| Self-closing | `` | `::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] + + This is an important message with **bold** text. + +``` + +```mdc [Comark] +::alert{type="info"} +This is an important message with **bold** text. +:: +``` +:: + +### Inline Components + +::code-group +```js [MDX] +Status: Active +``` + +```mdc [Comark] +Status: :badge[Active]{color="green"} +``` +:: + +### Self-Closing Components + +::code-group +```js [MDX] + + +``` + +```mdc [Comark] +‎::divider + +‎::chart{color="#fcb32c"} +``` +:: + +### Nested Components + +::code-group +```js [MDX] + + + - Item 1 + - Item 2 + + +``` + +```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] + + Content + +``` + +```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] + +``` + +```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] + +``` + +```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 + +Welcome! + + +``` + +```vue [Comark (Vue)] + + + +``` + +```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 {markdown} +} +``` +:: + +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)] + + + +``` +:: + +--- + +## 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 + +``` + +--- + +## 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 + diff --git a/docs/content/7.kb/3.twoslash.md b/docs/content/7.kb/4.twoslash.md similarity index 100% rename from docs/content/7.kb/3.twoslash.md rename to docs/content/7.kb/4.twoslash.md