Components
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
::
[
"component-name",
{ "prop1": "value1", "prop2": "value2" },
["p", {}, "Content inside the component"],
["p", {}, "Can have ", ["strong", {}, "markdown"], " and other elements"]
]
Examples
::alert{type="info"}
This is an important message!
::
::card{title="My Card"}
Card content with **markdown** support
::
::divider
::
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.
| Syntax | Description |
|---|---|
:icon-check | Standalone 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
::
{
"nodes": [
[
"component",
{
"title": "My Component",
"type": "info",
"count": 42,
"enabled": true,
"items": ["First item", "Second item"],
"config": { "theme": "dark", "mode": "auto" }
},
["p", {}, "Component content goes here"],
["p", {}, "With full ", ["strong", {}, "markdown"], " support"]
]
]
}
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
::
{
"nodes": [
[
"card",
{},
[
"template",
{ "name": "header" },
["h2", {}, "Card Title"]
],
[
"template",
{ "name": "content" },
["p", {}, "This is the main content of the card"]
],
[
"template",
{ "name": "footer" },
["p", {}, "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
::
::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
::::
:::
::
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