1. Project Overview & Quickstart (unjs/consola)
๐จ Consola
Elegant Console Wrapper
Why Consola?
๐ Easy to use
๐
Fancy output with fallback for minimal environments
๐ Pluggable reporters
๐ป Consistent command line interface (CLI) experience
๐ท Tag support
๐ Redirect console and stdout/stderr to consola and easily restore redirect.
๐ Browser support
โฏ Pause/Resume support
๐ป Mocking support
๐ฎโโ๏ธ Spam prevention by throttling logs
โฏ Interactive prompt support powered by clack
Installation
Using npm:
npm i consolaUsing yarn:
yarn add consolaUsing pnpm:
pnpm i consolaGetting Started
// ESM
import { consola, createConsola } from "consola";
// CommonJS
const { consola, createConsola } = require("consola");
consola.info("Using consola 3.0.0");
consola.start("Building project...");
consola.warn("A new version of consola is available: 3.0.1");
consola.success("Project built!");
consola.error(new Error("This is an example error. Everything is fine!"));
consola.box("I am a simple box");
await consola.prompt("Deploy to the production?", {
type: "confirm",
});Will display in the terminal:
You can use smaller core builds without fancy reporter to save 80% of the bundle size:
import { consola, createConsola } from "consola/basic";
import { consola, createConsola } from "consola/browser";
import { createConsola } from "consola/core";Consola Methods
`(logObject)` `(args...)`
Log to all reporters.
Example: consola.info('Message')
`await prompt(message, { type, cancel })`
Show an input prompt. Type can either of text, confirm, select or multiselect.
If prompt is canceled by user (with Ctrol+C), default value will be resolved by default. This strategy can be configured by setting { cancel: "..." } option:
"default"- Resolve the promise with thedefaultvalue orinitialvalue."undefined" - Resolve the promise withundefined."null"- Resolve the promise withnull."symbol"- Resolve the promise with a symbolSymbol.for("cancel")."reject"- Reject the promise with an error.
See examples/prompt.ts for usage examples.
`addReporter(reporter)`
- Aliases:
add
Register a custom reporter instance.
`removeReporter(reporter?)`
- Aliases:
remove,clear
Remove a registered reporter.
If no arguments are passed all reporters will be removed.
`setReporters(reporter|reporter[])`
Replace all reporters.
`create(options)`
Create a new Consola instance and inherit all parent options for defaults.
`withDefaults(defaults)`
Create a new Consola instance with provided defaults
`withTag(tag)`
- Aliases:
withScope
Create a new Consola instance with that tag.
`wrapConsole()` `restoreConsole()`
Globally redirect all console.log, etc calls to consola handlers.
`wrapStd()` `restoreStd()`
Globally redirect all stdout/stderr outputs to consola.
`wrapAll()` `restoreAll()`
Wrap both, std and console.
console uses std in the underlying so calling wrapStd redirects console too.
Benefit of this function is that things like console.info will be correctly redirected to the corresponding type.
`pauseLogs()` `resumeLogs()`
- Aliases:
pause/resume
Globally pause and resume logs.
Consola will enqueue all logs when paused and then sends them to the reported when resumed.
`mockTypes`
- Aliases:
mock
Mock all types. Useful for using with tests.
The first argument passed to mockTypes should be a callback function accepting (typeName, type) and returning the mocked value:
// Jest
consola.mockTypes((typeName, type) => jest.fn());
// Vitest
consola.mockTypes((typeName, type) => vi.fn());Please note that with the example above, everything is mocked independently for each type. If you need one mocked fn create it outside:
// Jest
const fn = jest.fn();
// Vitest
const fn = vi.fn();
consola.mockTypes(() => fn);If callback function returns a falsy value, that type won't be mocked.
For example if you just need to mock consola.fatal:
// Jest
consola.mockTypes((typeName) => typeName === "fatal" && jest.fn());
// Vitest
consola.mockTypes((typeName) => typeName === "fatal" && vi.fn());NOTE: Any instance of consola that inherits the mocked instance, will apply provided callback again.
This way, mocking works for withTag scoped loggers without need to extra efforts.
Custom Reporters
Consola ships with 3 built-in reporters out of the box. A fancy colored reporter by default and fallsback to a basic reporter if running in a testing or CI environment detected using unjs/std-env and a basic browser reporter.
You can create a new reporter object that implements { log(logObject): () => { } } interface.
Example: Simple JSON reporter
import { createConsola } from "consola";
const consola = createConsola({
reporters: [
{
log: (logObj) => {
console.log(JSON.stringify(logObj));
},
},
],
});
// Prints {"date":"2023-04-18T12:43:38.693Z","args":["foo bar"],"type":"log","level":2,"tag":""}
consola.log("foo bar");Example: Exit on fatal errors
import { consola } from 'consola';
consola.addReporter({
log(logObj) {
if(logObj.type === 'fatal') {
process.exit(1)
}
}
})
// Will exit on this line.
consola.fatal("fatal error");Log Level
Consola only shows logs with configured log level or below. (Default is 3)
Available log levels:
0: Fatal and Error1: Warnings2: Normal logs3: Informational logs, success, fail, ready, start, ...4: Debug logs5: Trace logs-999: Silent+999: Verbose logs
You can set the log level by either:
- Passing
leveloption tocreateConsola - Setting
consola.levelon instance - Using the
CONSOLA_LEVELenvironment variable (not supported for browser and core builds).
Log Types
Log types are exposed as consola.[type](...) and each is a preset of styles and log level.
A list of all available built-in types is available here.
Creating a new instance
Consola has a global instance and is recommended to use everywhere.
In case more control is needed, create a new instance.
import { createConsola } from "consola";
const logger = createConsola({
// level: 4,
// fancy: true | false
// formatOptions: {
// columns: 80,
// colors: false,
// compact: false,
// date: false,
// },
});Integrations
With jest or vitest
describe("your-consola-mock-test", () => {
beforeAll(() => {
// Redirect std and console to consola too
// Calling this once is sufficient
consola.wrapAll();
});
beforeEach(() => {
// Re-mock consola before each test call to remove
// calls from before
// Jest
consola.mockTypes(() => jest.fn());
// Vitest
consola.mockTypes(() => vi.fn());
});
test("your test", async () => {
// Some code here
// Let's retrieve all messages of `consola.log`
// Get the mock and map all calls to their first argument
const consolaMessages = consola.log.mock.calls.map((c) => c[0]);
expect(consolaMessages).toContain("your message");
});
});With jsdom
{
new jsdom.VirtualConsole().sendTo(consola);
}Console Utils
// ESM
import {
stripAnsi,
centerAlign,
rightAlign,
leftAlign,
align,
box,
colors,
getColor,
colorize,
} from "consola/utils";
// CommonJS
const { stripAnsi } = require("consola/utils");Raw logging methods
Objects sent to the reporter could lead to unexpected output when object is close to internal object structure containing either message or args props. To enforce the object to be interpreted as pure object, you can use the raw method chained to any log type.
Example:
// Prints "hello"
consola.log({ message: "hello" });
// Prints "{ message: 'hello' }"
consola.log.raw({ message: "hello" });License
MIT
2. Official Technical Reference & Guides (unjs/docs)
File: README.md
UnDocs
Minimal documentation theme and CLI for shared usage across UnJS/H3/Nitro projects.
Write your docs as Markdown, drop in a single config file, and get a fast,
elegant, zero-config documentation site โ dev server, production build, search,
and llms.txt included.
Quick Start
A docs project is three files. Create them in a docs/ folder:
1. docs/package.json โ pulls in the CLI and wires up two scripts:
{
"name": "docs",
"private": true,
"scripts": {
"dev": "undocs dev",
"build": "undocs build"
},
"devDependencies": {
"undocs": "latest"
}
}2. docs/.config/docs.yaml โ your site config:
# yaml-language-server: $schema=https://unpkg.com/undocs/schema/config.json
name: "packageName"
shortDescription: "One-line summary."
github: "unjs/packageName"3. docs/1.guide/1.index.md โ your first page:
# Getting Started
Welcome to the docs!Then install and start the dev server on localhost:3000:
cd docs
npm install
npm run devBuild a static production bundle with npm run build.
Adding pages
Every Markdown file becomes a page. Numeric prefixes (1., 2.) control the
order in the sidebar and are stripped from the URL, so 1.guide/1.index.md
is served at /guide. Add folders and files to grow the navigation โ no routing
setup required:
docs/
โโ .config/
โ โโ docs.yaml
โโ 1.guide/
โ โโ 1.index.md โ /guide
โ โโ 2.usage.md โ /guide/usage
โโ 2.config/
โโ 1.index.md โ /configSee the configuration reference for the full
list of options (landing page, banner, socials, sponsors, llms.txt, and more).
Stack
Undocs is currently powered by Nitro, Vite, md4x, rangi, Unhead and Reka UI.
UnDocs was originally based on Nuxt, Nuxt UI, Nuxt Content (Comark), Vue Router, and other Nuxt ecosystem modules such as nuxt-llms and nuxt-icon which inspired the new generation of undocs.
License
Published under the MIT license.
File: docs/blog/1.initial-release.md
category: release date: 2000-01-01
Initial release
Undocs is out!
[release notes and other content]
File: docs/blog/2.second-release.md
category: release date: 2001-01-01
Second release
Undocs is out with improvements!
[release notes and other content]
File: docs/blog/3.new-blog.md
category: release
date: 2025-06-01
authors:
- name: Pooya Parsa
github: pi0
New blog section
Undocs now allows easily creating a blog section!
Section
[release notes and other content]
Section
[another section]
File: docs/2.config/1.index.md
Configuration
Learn how to configure the documentation site made with UnDocs.
Example
#
# yaml-language-server: $schema=https://unpkg.com/undocs/schema/config.json
name: "packageName"
shortDescription: ""
github: "unjs/packageName"
# url: 'https://packageName.unjs.io'
# llms:
# # Generate `/llms.txt` and `/llms-full.txt`
# domain: 'https://packageName.unjs.io'
# title: 'packageName'
# full:
# title: 'packageName'
# redirects:
# "/from": "/to"
# automd: true
landing:
heroLinks:
stackblitz:
icon: "i-lucide-play"
to: "https://stackblitz.com/github/unjs/packageName/tree/main/playground"
# contributors: true
# features:
# - title:
# description:Cross-origin isolation
Pages that use SharedArrayBuffer or wasm threads โ an embedded SQLite build, an
FFmpeg demo, a Rust playground, anything reaching for Atomics.wait โ only get
those APIs on a cross-origin isolated
page. Isolation is opt-in, and off by default:
crossOriginIsolation: trueWith it on, every response serves:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: credentiallessBoth headers are required โ COOP alone does not isolate. They are applied through
Nitro route rules, so undocs dev and the built output behave identically.
credentialless (what true means) sends cross-origin no-cors subresource
requests without credentials, so third-party images, fonts and scripts keep
loading whether or not the servers hosting them opt in.
require-corp is the stricter alternative, and only safe once every cross-origin
asset the docs load sends Cross-Origin-Resource-Policy (or is fetched with
CORS) โ anything that does not is blocked outright:
crossOriginIsolation: require-corp::note
Under either value, a cross-origin iframe must send its ownCross-Origin-Embedder-Policy to load at all. Check any embedded playground,
video or third-party widget after turning isolation on โ that is a property of
isolation itself, not of the value you pick.
::
Reference
`$schema`
- Type:
string
`automd`
- Type:
boolean
Enable integration with https://automd.unjs.io
`banner`
Banner configuration
`actions`
- Type:
array
Display a list of action buttons next to the title.
`close`
- Type:
undefined
`closeIcon`
- Type:
string - Default:
"i-lucide-x"
The icon displayed in the close button (e.g., 'i-lucide-x').
`color`
- Type:
string - Default:
"primary"
Banner color theme.
`icon`
- Type:
string
The icon displayed next to the title (e.g., 'i-lucide-info').
`id`
- Type:
string
A unique id saved to local storage to remember if the banner has been dismissed. Change this value to show the banner again.
`target`
- Type:
string
Link target attribute.
`title`
- Type:
string
The banner title text.
`to`
- Type:
string
Link destination URL or route path.
`ui`
UI customization classes for banner components.
`actions`
- Type:
undefined
Actions container classes
`center`
- Type:
undefined
Center section classes
`close`
- Type:
undefined
Close button classes
`container`
- Type:
undefined
Container element classes
`icon`
- Type:
undefined
Icon element classes
`left`
- Type:
undefined
Left section classes
`right`
- Type:
undefined
Right section classes
`root`
- Type:
undefined
Root element classes
`title`
- Type:
undefined
Title element classes
`branch`
- Type:
string
The branch of the GitHub repository for the documentation site.
`buildCache`
- Type:
boolean
Enable build cache (experimental)
`description`
- Type:
string
The description of the documentation site.
`dir`
- Type:
string
Documentation directory
Note: This option will be automatically set
`github`
- Type:
string
The GitHub repository for the documentation site.
`landing`
- Type:
undefined
`lang`
- Type:
string - Default:
"en"
The language of the documentation site.
`llms`
Configuration for llms.txt generation (/llms.txt and /llms-full.txt).
`description`
- Type:
string
Description used in /llms.txt.
`domain`
- Type:
string
Public site domain (e.g. https://example.com).
`full`
Metadata for /llms-full.txt.
`description`
- Type:
string
Description used in /llms-full.txt.
`title`
- Type:
string
Title used in /llms-full.txt.
`title`
- Type:
string
Title used in /llms.txt.
`name`
- Type:
string
The name of the documentation site.
`redirects`
Redirects for the documentation site.
`shortDescription`
- Type:
string
The description of the documentation site.
`socials`
Social media links for the documentation site.
`sponsors`
`api`
- Type:
string
The URL to the sponsors JSON API.
`themeColor`
- Type:
string
The accent color of the documentation site. Defaults to mono.
Accepts mono (no accent โ links and active navigation read in body color, the monochrome default), a Geist hue (blue, red, amber, green, teal, purple, pink), a Tailwind palette name that maps onto the nearest Geist hue (violet -> purple, cyan -> teal, rose -> red, ...), a neutral name (gray, slate, zinc, neutral, stone) as a synonym for mono, or any CSS color.
It tints links, active navigation, icons, and the landing glow, and is used for the theme-color meta tag. Buttons and other solid fills stay monochrome, as they are in Geist.
`url`
- Type:
string
The URL of the documentation site.
`versions`
- Type:
array
The versions of the documentation site.
File: docs/1.guide/1.index.md
Getting Started
Write your docs as Markdown, drop in a single config file, and get a fast,
elegant, zero-config documentation site โ dev server, production build, search,
andllms.txtincluded.
Overview
UnJS Docs is a minimal Documentation Theme and CLI for shared usage across UnJS projects.
Stack
Undocs is currently powered by Nitro, Vite, md4x, rangi and Unhead. Its UI primitives are its own, derived from the MIT-licensed Reka UI.
UnDocs was originally based on Nuxt, Nuxt UI, Nuxt Content (Comark), Vue Router, and other Nuxt ecosystem modules such as nuxt-llms and nuxt-icon which inspired the new generation of undocs.
Quick Start
Create docs/ project with starter template:
:pm-x{command="giget gh:unjs/undocs/template docs --install"}
Go to the docs dir cd docs/
Start development server:
:pm-run{script="dev"}
Build for production:
:pm-run{script="build"}
File: docs/1.guide/2.components.md
icon: i-lucide-puzzle
Components
Discover the components you can use in your markdown files.
Alerts
::tabs ::div
label: Preview icon: i-lucide-search
::note Highlights information that users should take into account, even when skimming. :: ::tip Optional information to help a user be more successful. :: ::important Crucial information necessary for users to succeed. :: ::warning{to="/"} Critical content demanding immediate user attention due to potential risks. :: ::caution{to="/"} Negative potential consequences of an action. :: :: ::div
label: Code icon: i-lucide-square-code
::note
Highlights information that users should take into account, even when skimming.
::
::tip
Optional information to help a user be more successful.
::
::important
Crucial information necessary for users to succeed.
::
::warning{to="/"}
Critical content demanding immediate user attention due to potential risks.
::
::caution{to="/"}
Negative potential consequences of an action.
:: ::
::
Package Manager
Components to generate cross package manager comments
::tabs ::div
label: Preview icon: i-lucide-search
:pm-install{name="defu"}
:pm-run{script="dev"}
:pm-x{command="giget unjs new-lib"}
:: ::div
label: Code icon: i-lucide-square-code
:pm-install{name="defu"}
:pm-run{script="dev"}
:pm-x{command="giget unjs new-lib"} ::
::
Read More
The component is used to create a link to another page.
::tabs ::div
label: Preview icon: i-lucide-search
:read-more{to="/guide"} :read-more{to="https://unjs.io" title="UnJS Website"} :: ::div
label: Code icon: i-lucide-square-code
:read-more{to="/guide"}
:read-more{to="https://unjs.io" title="UnJS Website"} ::
::
Cards
Group related links or highlights into cards. A ::card can be standalone or wrapped in a ::card-group grid. Add a to to make the whole card a link.
::tabs ::div
label: Preview icon: i-lucide-search
::card-group{cols="2"}
::card
---
title: Getting Started
icon: i-lucide-rocket
to: /guide
---
Install undocs and scaffold your first docs site.
::
::card
---
title: Components
icon: i-lucide-puzzle
to: /guide/components
---
Alerts, tabs, cards and more, straight from markdown.
::
::
::
::div
label: Code icon: i-lucide-square-code
::card-group{cols="2"}
::card
---
title: Getting Started
icon: i-lucide-rocket
to: /guide
---
Install undocs and scaffold your first docs site.
::
::card
---
title: Components
icon: i-lucide-puzzle
to: /guide/components
---
Alerts, tabs, cards and more, straight from markdown.
::
:: ::
::
Tabs
Group alternative content into tabs. Each direct child becomes a tab โ set its label (or title) and an optional icon. Children can be ::tab blocks or ::div blocks carrying those props.
::tabs
::tab{label="npm" icon="i-lucide-package"}
Content shown under the npm tab.
::
::tab{label="pnpm" icon="i-lucide-package"}
Content shown under the pnpm tab.
::
::
::tabs
::tab{label="npm" icon="i-lucide-package"}
Content shown under the **npm** tab.
::
::tab{label="pnpm" icon="i-lucide-package"}
Content shown under the **pnpm** tab.
::
::Steps
Render a vertical, numbered steps list. Each heading inside ::steps becomes a numbered step; the content beneath it belongs to that step. Numbering and the guide line are produced with CSS, so any headings work.
::steps
Install the package
:pm-install{name="undocs"}
Run the dev server
:pm-run{script="dev"}
Ship your docs ๐
::
::steps
#### Install the package
:pm-install{name="undocs"}
#### Run the dev server
:pm-run{script="dev"}
#### Ship your docs ๐
::[!TIP]
Steps are also generated automatically from standard numbered lists โ see Content Transform.
Code Group
Group multiple code blocks into a single tabbed switcher. Each block's filename (in [brackets]) becomes its tab label, with a language icon inferred automatically.
::code-group
{
"scripts": {
"dev": "undocs dev"
}
}export default defineEventHandler(() => {
return { hello: "world" };
});::
::code-group
```json [package.json]
{
"scripts": {
"dev": "undocs dev"
}
}
```
```ts [server/api/hello.get.ts]
export default defineEventHandler(() => {
return { hello: "world" };
});
```
::[!NOTE]
Consecutive code blocks are grouped automatically โ see Content Transform. Use::code-groupwhen you need to group blocks that are not adjacent.
Code Tree
Display a set of files in a VS Codeโstyle explorer: a folder/file tree on the left, the selected file's highlighted code on the right. Filenames containing / (e.g. [server/routes/index.ts]) nest into folders. Use defaultValue to pick the initially selected file and expandAll to expand every folder.
::code-tree{defaultValue="src/app.ts" expandAll}
{
"name": "my-app"
}export const app = createApp();export default defineRoute(() => "Hello");::
::code-tree{defaultValue="src/app.ts" expandAll}
```ts [package.json]
{
"name": "my-app"
}
```
```ts [src/app.ts]
export const app = createApp();
```
```ts [src/routes/index.ts]
export default defineRoute(() => "Hello");
```
::Mermaid Graphs
```mermaid
graph TD
A[Getting Started] --> B[Components]
A --> C[Content Transform]
A --> D[Prose]
click A "/guide"
click B "/guide/components"
click C "/guide/content-transformation"
click D "/guide/prose"
```%%{init: {'theme':'neutral'}}%%
graph TD
A[Getting Started] --> B[Components]
A --> C[Content Transform]
A --> D[Prose]
click A "/guide"
click B "/guide/components"
click C "/guide/content-transformation"
click D "/guide/prose"Prose Components
Undocs ships its own set of Prose components that render standard markdown โ headings, links, tables, code blocks, and more โ with sensible typography defaults. Just write markdown and they are applied automatically.
:read-more{to="/guide/prose" title="Prose rendering"}
File: docs/1.guide/3.content-transformation.md
icon: material-symbols:markdown-outline
Content Transform
Discover ways that undocs transforms content to make it more easier to just write documentation.
Github Notes
https://github.com/orgs/community/discussions/16925
> [!NOTE]
> Highlights information that users should take into account, even when skimming.[!NOTE]
Highlights information that users should take into account, even when skimming.
> [!TIP]
> Optional information to help a user be more successful.[!TIP]
Optional information to help a user be more successful.
> [!IMPORTANT]
> Crucial information necessary for users to succeed.[!IMPORTANT]
Crucial information necessary for users to succeed.
> [!WARNING]
> Critical content demanding immediate user attention due to potential risks.[!WARNING]
Critical content demanding immediate user attention due to potential risks.
> [!CAUTION]
> Negative potential consequences of an action.[!CAUTION]
Negative potential consequences of an action.
Auto Code Groups
If you have code blocks right after each other, they will be grouped together using a code-group component.
```json [package.json]
{
"scripts": {
"dev": "undocs dev"
}
}
```
```ts [server/api/hello.get.ts]
export default defineEventHandler(() => {
return {
hello: "world",
};
});
```
```html [index.html]
<template>
<h1>Welcome to the homepage</h1>
</template>
```{
"scripts": {
"dev": "undocs dev"
}
}export default defineEventHandler(() => {
return {
hello: "world",
};
});<template>
<h1>Welcome to the homepage</h1>
</template>Steps
Generate steps by using standard markdown numbered lists!
[!IMPORTANT]
In order to generate this component, you need to have content inside at least one of the lists. The list can't be a child of another component & also any content within a Markdown list will need at least 2 tabs to be considered as a child of the list.
1. Install Package
::note
Please note that steps only work with numbered lists and is not within children.
::
:pm-install{name="undocs"}
2. Run development server
:pm-run{script="undocs"}
3. Done โ
Install Package
::note
Please note that steps only work with numbered lists and is not within children.
:::pm-install{name="undocs"}
Run development server
:pm-run{script="undocs"}
Done โ
Config References
Generate beautiful references for your configuration files by just using markdown!
[!TIP]
If you use automd:jsdocs, you can reference the schema file directly! Check out this example from the config page.
### `$schema`
- **Type**: `string`
### `automd`
- **Type**: `boolean`
Enable integration with https://automd.unjs.io
### `buildCache`
- **Type**: `boolean`
Enable build cache (experimental)
### `description`
- **Type**: `string`
The description of the documentation site.`$schema`
- Type:
string
`automd`
- Type:
boolean
Enable integration with https://automd.unjs.io
`buildCache`
- Type:
boolean
Enable build cache (experimental)
`description`
- Type:
string
The description of the documentation site.
[!TIP]
Do you have an idea for a new content transformation, feel free to open an issue!
File: docs/1.guide/4.prose.md
icon: material-symbols:text-fields
Prose
Undocs renders standard Markdown through its own set of Prose components with sensible typography defaults โ just write Markdown and it looks great.
Headings
Use # through ###### for headings. Each renders with consistent spacing and an anchor link on hover.
# Heading 1
## Heading 2
### Heading 3
#### Heading 4Text
Emphasize inline content with bold, italic, strikethrough, and inline code. Combine them for strong emphasis where needed.
**bold**, _italic_, ~~strikethrough~~, and `inline code`.Links
Internal and external links are styled consistently. External links open in a new tab automatically.
Internal and external [links](https://unjs.io) are styled consistently.Blockquotes
A blockquote is rendered with a subtle left border and muted text โ handy for callouts and citations.
> A blockquote is rendered with a subtle left border and muted text.Lists
Unordered, ordered, and task lists all render cleanly:
- First item
- Second item
- Nested item
- Third item
- Install the package
- Run the dev server
- Ship your docs
- Write the Markdown
- Review the rendering
- Deploy
- First item
- Second item
- Nested item
1. Install the package
2. Run the dev server
- [x] Write the Markdown
- [ ] Review the renderingTables
| Feature | Supported | Notes |
|---|---|---|
| Headings | โ | Anchor links on hover |
| Tables | โ | Column alignment respected |
| Code blocks | โ | Syntax highlighted |
| Task lists | โ | Rendered as checkboxes |
| Feature | Supported | Notes |
| ------- | :-------: | --------------------- |
| Tables | โ
| Column alignment kept |Code
Inline code and fenced code blocks are highlighted with rangi:
export function greet(name: string): string {
return `Hello, ${name}!`;
}Images
Images are responsive and constrained to the content width:
Horizontal Rule
Separate sections with a thematic break:
That's a --- rendered as a horizontal rule.