Syntax

Components

Embed custom components directly in your Markdown with block and inline syntax, props, slots, and nested children.

Comark extends standard Markdown with component syntax, letting you embed custom UI directly in your content while keeping it readable.

Block Components

Block components use the ::component-name syntax and occupy their own line:

::component-name{prop1="value1" prop2="value2"}
Content inside the component

Can have **markdown** and other elements
::

Examples

::alert{type="info"}
This is an important message!
::

Inline Components

Inline components use the :component-name syntax and can be placed within text:

Check out this :icon-star component in the middle of text.

Click the :button[Submit]{type="primary"} to continue.

The status is :badge[Active]{color="green"} right now.
SyntaxDescription
:icon-checkStandalone inline component
:badge[New]Inline component with content
:badge[New]{color="blue"}Inline component with content and properties
:tooltip{text="Hover text"}Inline component with properties only

Component Properties

Components support two property syntaxes: inline attributes and YAML frontmatter.

Inline Attributes

Use the {...} syntax for simple properties:

::component{prop="value"}
<!-- Standard key-value pair -->
::

::component{bool}
<!-- Boolean property (becomes :bool="true" in AST) -->
::

::component{#custom-id}
<!-- ID attribute -->
::

::component{.class-name}
<!-- CSS class -->
::

::component{.class-one .class-two}
<!-- Multiple CSS classes -->
::

::component{obj='{"key": "value"}'}
<!-- Object/JSON value -->
::

::component{multiple="props" bool #id .class}
<!-- Multiple properties combined -->
::

YAML Frontmatter Props

For components with many properties, use YAML frontmatter inside the component:

::component
---
title: My Component
type: info
count: 42
enabled: true
items:
  - First item
  - Second item
config:
  theme: dark
  mode: auto
---
Component content goes here

With full **markdown** support
::
Objects remain objects, arrays remain arrays, and numbers/booleans are parsed as their respective types rather than strings. Your components receive fully typed props.

Key rules for YAML props:

  • Must be at the very beginning of the component content
  • Enclosed by --- delimiters
  • Merged with inline attributes (inline attributes take precedence)
  • Full support for complex data structures

Combine Both Syntaxes

Inline attributes and YAML props can be combined. Inline attributes take precedence:

::card{.featured}
---
title: Featured Article
author: Jane Doe
tags:
  - markdown
  - documentation
---
This combines inline class `.featured` with YAML props
::

YAML Props Use Cases

Configuration-heavy components:

::data-table
---
columns:
  - name: Name
    field: name
    sortable: true
  - name: Email
    field: email
    sortable: true
options:
  striped: true
  pageSize: 10
---
::

API documentation:

::api-endpoint
---
method: POST
path: /api/users
parameters:
  - name: username
    type: string
    required: true
  - name: email
    type: string
    required: true
response:
  status: 201
  body:
    id: string
    username: string
---
::

Component Slots

Block components support named slots using the #slot-name syntax:

::card
#header
## Card Title

#content
This is the main content of the card

#footer
Footer text here
::

Combine YAML Props with Slots

You can use both YAML frontmatter props and named slots in the same component:

::card{.featured}
---
variant: elevated
color: primary
actions:
  - label: Read More
    url: /article
  - label: Share
    icon: share
---
#header
## Article Title
*By Jane Doe*

#content
This is the main article content with **markdown** support.

#footer
Published on January 15, 2024
::
YAML frontmatter must come immediately after the opening ::component line, before any slot definitions.

Correct order:

::component{inline-attrs}
---
yaml: props
---
#slot-name
Slot content
::

Incorrect order:

::component
#slot-name
Slot content
---
yaml: props  <!-- This won't work -->
---
::

Nested Components

Components can be nested within each other using additional colons:

::outer-component
Content in outer

:::inner-component{variant="compact"}
Content in inner
:::

More content in outer
::

Deep nesting:

::level-1
  :::level-2
    ::::level-3
    Content
    ::::
  :::
::
Adding extra colons is not required but is a good practice to keep nesting visually consistent. The parser resolves nesting by matching opening and closing tags.

This also works:

::level-1
  ::level-2
    ::level-3
    Content
    ::
  ::
::

Next Steps

  • Attributes - Add classes, IDs, and styles to native Markdown elements
  • Vue Rendering - Render components in Vue applications
  • React Rendering - Render components in React applications
  • Comark AST - Understand how components are represented in the AST
Copyright © 2026