# NoirMD — LLM Reference
> Quick reference for AI assistants helping users install, configure, and use NoirMD.
> NoirMD is a framework-agnostic markdown renderer with React, Vue, and Vanilla JS renderers.
> npm: `@noirmd/previewer` | GitHub: https://github.com/NOIR-DexPrkr/NoirMD
## Package Overview
| Entry point | Description | Dependencies |
|-------------|-------------|--------------|
| `@noirmd/previewer/core` | Parser, types, utilities | None |
| `@noirmd/previewer/react` | React components + renderer | React ≥18 |
| `@noirmd/previewer/vanilla` | Vanilla DOM renderer + CSS | None (highlight.js bundled) |
| `@noirmd/previewer/vue` | Vue 3 components + composables | Vue ≥3 |
| `@noirmd/previewer` | Backward-compat (core + react) | React ≥18 |
| `@noirmd/previewer/editor` | CodeMirror 6 editor | React + CodeMirror |
---
## Setup — React
```bash
npm install @noirmd/previewer react react-dom
# Editor (optional):
npm install @uiw/react-codemirror @codemirror/view @codemirror/state @codemirror/language @lezer/highlight
```
```tsx
import { NRpreviewer } from '@noirmd/previewer/react';
import '@noirmd/previewer/markdown.css';
function App() {
return ;
}
```
### NRpreviewer Props (React)
- `content: string` — Markdown string to render
- `html: string` — Pre-rendered HTML (skip parsing)
- `tailwindCDN: boolean` — Inject Tailwind CSS v4 CDN
- `className: string` — Additional CSS class
- `style: CSSProperties` — Inline styles
### NReditor Props (React)
```tsx
import NReditor from '@noirmd/previewer/editor';
```
- `value: string` — Markdown content
- `onChange: (value: string) => void` — Change handler
- `debounceMs: number` — Debounce for preview (default: 150)
- `tailwindCDN: boolean` — Inject Tailwind CSS v4 CDN
---
## Setup — Vue 3
```bash
npm install @noirmd/previewer vue
```
```vue
```
### NRpreviewer Props (Vue)
- `content: string` — Markdown string
- `tailwindCDN: boolean` — Inject Tailwind CDN
- `className: string` — Additional CSS class
---
## Setup — Vanilla JS
```bash
npm install @noirmd/previewer
```
```ts
import { renderMarkdownString } from '@noirmd/previewer/vanilla';
import '@noirmd/previewer/vanilla/vanilla.css';
const el = renderMarkdownString('# Hello **World**');
document.getElementById('app')!.appendChild(el);
```
### API (Vanilla)
- `renderMarkdownString(markdown: string): HTMLElement` — Returns a DOM element
- `parseMarkdown(markdown: string): Token[]` — Returns raw AST tokens (from `@noirmd/previewer/core`)
### CDN Usage (no build step)
```html
```
---
## Core Parser (Framework-Agnostic)
```ts
import { parseMarkdown } from '@noirmd/previewer/core';
const tokens = parseMarkdown('# Hello **World**');
```
Zero dependencies. Returns `Token[]` AST.
---
## Inline Syntax
| Syntax | Result |
|--------|--------|
| `**bold**` | **bold** |
| `_italic_` | _italic_ |
| `***bold italic***` | ***bold italic*** |
| `~~strikethrough~~` | ~~strikethrough~~ |
| `` `code` `` | `code` |
| `==highlight==` | ==highlight== |
| `!>spoilerCentered<- ## ->Right->
## Title ##{.class #id}
```
### Code Blocks
````markdown
```javascript title="file.js"
code here
```
````
### Lists
```markdown
- Unordered item
1. Ordered item
```
### Tables
```markdown
| Col1 | Col2 |
|------|------|
| A | B |
```
### Blockquotes
```markdown
> Quoted text with **formatting**
```
### HTML Blocks
```html
Markdown **inside** HTML works.
```
---
## Directives
General syntax:
```markdown
:::type {key="value"}
Content
:::
```
Short form: `:::note Quick Title` → `{title="Quick Title"}`
Shorthands: `.class` → `{class}`, `#id` → `{id}`
### Admonitions
- `:::note`, `:::info`, `:::warning`, `:::danger`, `:::greentext`
- Props: `title`, `icon`, `class`, `style`
### Cards
- `:::card` (static), `:::card-m` (modal), `:::card-b` (link)
- Props: `title`, `icon`, `image`, `class`, `style`, `url`, `batch`
- Slots: `#description`, `#content` (card-m only)
### Details
- `:::details {title="..." icon="..." defaultOpen="true"}`
- Collapsible section with custom state management
### Modal
- `:::modal {title="..." label="Open" icon="open_in_new"}`
- Opens dialog with markdown content
### Slide
- `:::slide {class="text-xl" interval="3000"}`
- Text carousel, one line per slide
### Wrapper
- `:::div`, `:::style`, `:::custom`, `:::raw`
- Generic wrapper, same as native ``
---
## Styling System
- Tailwind CDN injection via `tailwindCDN` prop
- CSS variables: `--color-background-primary`, `--color-text-primary`, `--color-accent-primary`, etc.
- Theme: light/dark via `.dark` class on root
- Font families: `font-sans` (Inter), `font-mono` (Roboto Mono), etc.
### Custom Theme
```css
:root {
--color-background-primary: #ffffff;
--color-text-primary: #1a1a2e;
--color-accent-primary: #6366f1;
}
.dark {
--color-background-primary: #0f0f23;
--color-text-primary: #e2e8f0;
--color-accent-primary: #818cf8;
}
```
---
## Parser Order
1. Headers → 2. Aligned paragraphs → 3. Code blocks → 4. Directives → 5. Images → 6. Tables → 7. Lists → 8. Blockquotes → 9. HR → 10. TOC → 11. HTML blocks → 12. Paragraphs
---
## TypeScript Support
Full type definitions included with every entry point:
```ts
import type { Token } from '@noirmd/previewer/core';
import type { RenderContext, DirectiveComponentProps } from '@noirmd/previewer/react';
```
---
## Troubleshooting
**Styles not loading?** Import the CSS: `import '@noirmd/previewer/markdown.css'`
**Tailwind classes not working?** Add `tailwindCDN` prop to enable JIT CDN compilation.
**Syntax highlighting missing?** Highlight.js is bundled in react/vanilla renderers. Ensure you're importing from the correct entry point.
**Vue SSR error "window is not defined"?** Normal — Tailwind CDN hook accesses `window`. Components work fine client-side with `client:load` (Astro) or in browser.
**Next.js "use client" needed?** Yes — add `'use client'` directive for components using hooks.