@khotwa/jana
v0.2.0
Published
Vite plugin for Markdown with Svelte component support and unified plugins
Maintainers
Readme
Jana
A Vite plugin that transforms Markdown files into HTML, allowing you to import and use Svelte components directly in your Markdown content. Extensible with remark and rehype plugins.
Features
- Import Svelte components inside Markdown files - Use Svelte components directly in your Markdown content
- Prose components - Auto-replace HTML tags (
<p>,<h1>,<pre>, etc.) with your custom Svelte components - Automatic escaping of Svelte syntax (
{,}) in code blocks - Full Markdown to HTML conversion
- Extensible with remark and rehype plugins
- Fast and lightweight (no syntax highlighting overhead)
- SvelteKit and Vite compatible
Installation
npm install @khotwa/janaUsage
Basic Setup
1. Add Jana to Vite Config
Add Jana to your vite.config.js or vite.config.ts:
import { defineConfig } from 'vite'
import { jana } from '@khotwa/jana'
export default defineConfig({
plugins: [
jana()
// ... other plugins
]
})2. Configure Svelte Extensions
Add .md to the extensions in your svelte.config.js:
const config = {
extensions: ['.svelte', '.md']
// ... rest of your config
}Using Markdown Files
Option 1: Import as a Component
Import Markdown files directly as Svelte components:
<script>
import Post from './Post.md'
</script>
<Post />Option 2: Use as SvelteKit Route File
In SvelteKit, you can use Markdown files directly as route pages:
src/routes/blog/+page.mdThe Markdown file will be automatically processed and rendered as a Svelte page when accessed via the route.
Using Svelte Components in Markdown
You can import and use Svelte components directly inside your Markdown files:
<script>
import MyComponent from './MyComponent.svelte'
</script>
# My Blog Post
This is regular markdown content.
<MyComponent />
You can use components anywhere in your markdown!Prose Components
Prose components let you replace standard HTML tags with your own Svelte components. For example, you can replace every <p> with a custom <P> component that adds styling, or every <pre> with a <Pre> component that adds a copy button.
Auto-Scan (default)
By default, Jana scans src/lib/components/prose/ for Svelte files that match known HTML tag names:
src/lib/components/prose/
P.svelte → wraps all <p> tags
H1.svelte → wraps all <h1> tags
Pre.svelte → wraps all <pre> tags
Code.svelte → wraps all <code> tags
A.svelte → wraps all <a> tagsJust create the file and Jana picks it up automatically. No config needed.
Supported tag names: A, Blockquote, Code, Em, H1-H6, Hr, Img, Li, Ol, P, Pre, Strong, Table, Tbody, Td, Th, Thead, Tr, Ul.
Custom Prose Directory
Change the scan directory with the prose option:
jana({
prose: 'src/components/prose'
})Explicit Components
Map HTML tags to specific component paths directly:
jana({
components: {
p: '$lib/components/P.svelte',
pre: '$lib/components/CodeBlock.svelte',
h1: '$lib/components/Heading.svelte'
}
})Explicit components override auto-scanned ones, so you can use both — auto-scan for most tags and explicit config for specific overrides.
Code Block Metadata
When you use a prose component for pre, Jana automatically passes code block metadata as props:
```js title="example.js" highlight
console.log('hello')
```Your Pre.svelte component receives:
<script>
let { lang, title, highlight, children } = $props()
// lang = "js", title = "example.js", highlight = true
</script>Advanced Usage
Custom Unified Plugins
Jana supports adding custom remark and rehype plugins to extend functionality:
import { defineConfig } from 'vite'
import { jana } from '@khotwa/jana'
import remarkGfm from 'remark-gfm'
import rehypeShiki from 'rehype-shiki'
export default defineConfig({
plugins: [
jana({
plugins: {
remark: [remarkGfm],
rehype: [[rehypeShiki, { theme: 'github-dark' }]]
}
})
]
})Plugin format:
- Plugins can be passed as a function:
[remarkGfm] - Or as a tuple with options:
[[rehypeSlug, { prefix: "heading-" }]]
Full Configuration
jana({
// Custom prose directory (default: 'src/lib/components/prose')
prose: 'src/lib/components/prose',
// Explicit component mappings (override auto-scanned ones)
components: {
pre: '$lib/components/CodeBlock.svelte'
},
// Custom unified plugins
plugins: {
remark: [remarkGfm],
rehype: [rehypeSlug]
}
})How It Works
Jana uses the unified ecosystem to process Markdown:
- Parse — Converts Markdown to an abstract syntax tree (AST) with
remark-parse - Unwrap — Lifts Svelte components out of
<p>wrappers (remark treats them as inline) - Collect metadata — Extracts code block meta (lang, title, etc.) for prose components
- User remark plugins — Runs any custom remark plugins
- Transform — Converts the Markdown AST to HTML AST with
remark-rehype - User rehype plugins — Runs any custom rehype plugins
- Wrap elements — Replaces matched HTML tags with Svelte component wrappers
- Escape — Escapes Svelte syntax characters (
{,}) in code blocks - Stringify — Converts the AST to an HTML string
The plugin automatically processes any file ending with .md during Vite's build process.
License
MIT
