This post is generated from a single .md file by the vlozi blog importer. Every section below targets a specific construct so you can spot regressions visually after parser changes. The frontmatter status above is intentionally published — the importer should downgrade it to draft and surface a warning.
1. Headings
Heading 1 — primary title
Heading 2 — section
Heading 3 — subsection
Heading 4 — nested
Heading 5 — minor
Heading 6 — micro
A paragraph after the heading run to confirm spacing.
2. Paragraph + inline marks
This paragraph mixes bold, italic, bold-italic, strikethrough, and inline code. It also has a regular link, a link with a title attribute, a bare URL https://example.com inside text, and an email link [email protected]. Unsafe protocols like #alert(1) should drop their link mark entirely — only the visible text should remain: click me.
A second paragraph with a hard break
forced by two trailing spaces above this line — the break should split the paragraph at that point.
3. Lists
3.1 Bullet list
First bullet item
Second bullet item
Nested bullet (level 2)
Another nested bullet
Deeply nested (level 3)
Third bullet with bold and
code
3.2 Numbered list
Step one — set up the project
Step two — install dependencies
Step three — start the dev server
Sub-step a
Sub-step b
Step four — ship it
3.3 Task list (GFM)
Wire up the parser
Add a paste dialog
Cover image upload from
.zipRound-trip support (probably never)
3.4 Mixed list with paragraphs
A list item that contains a full paragraph of text. This should still render inside the list item's body without breaking the bullet flow above.
Even with a second paragraph nested inside the same list item.
Next item resumes normally.
4. Blockquote
A regular blockquote. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Multiple lines and even inline formatting are supported here.
5. Callouts (GFM admonitions)
This is a NOTE admonition. The importer maps it to your info callout type.
A TIP — maps to the tip callout. Often used for "did you know?"-style asides.
Same family as NOTE — also maps to info. Use for emphasis without alarming the reader.
Maps to the warning callout. Heads-up but not destructive.
Maps to the danger callout. Reserve this for irreversible operations.
6. Code blocks
6.1 TypeScript
interface User {
id: string
name: string
}
function greet(user: User): string {
return `Hello, ${user.name}!`
}
console.log(greet({ id: "u1", name: "Dipanshu" }))6.2 Python
def fizzbuzz(n: int) -> None:
for i in range(1, n + 1):
if i % 15 == 0:
print("FizzBuzz")
elif i % 3 == 0:
print("Fizz")
elif i % 5 == 0:
print("Buzz")
else:
print(i)6.3 Bash
pnpm add unified remark-parse remark-gfm gray-matter
git commit -m "feat(blog): markdown import"6.4 Code without a language tag
Plain text code — no syntax highlighting expected.
Useful for log dumps and ASCII diagrams.6.5 Mermaid diagram
flowchart LR
A([User pastes .md]) --> B[Frontmatter parser]
B --> C{Has title?}
C -- yes --> D[Convert body]
C -- no --> E[Use first H1]
E --> D
D --> F[Resolve category]
F --> G[(createPost)]
G --> H{{Editor opens}}
style A fill:#0a0a0a,stroke:#fafafa,color:#fafafa
style H fill:#fafafa,stroke:#0a0a0a,color:#0a0a0a6.6 Mermaid sequence (second flavor)
sequenceDiagram
participant U as User
participant E as Editor
participant P as Parser
participant API as createPost
U->>E: Drops .md file
E->>P: parseImport(text)
P-->>E: { title, body, tags }
E->>API: POST /api/blog/admin/posts
API-->>E: { id }
E->>U: Navigate to /dashboard/blog/{id}7. Tables (GFM)
Feature | Status | Notes |
|---|---|---|
Headings 1–6 | ✅ | Levels clamped to |
Bold / italic | ✅ | Combined marks supported |
Tables | ✅ | First row treated as header |
Mermaid | ✅ | Renders live in the editor |
Round-trip export | ❌ | One-way import only |
A second smaller table for spacing checks:
Key | Value |
|---|---|
|
|
|
|
8. Images
A standalone image:

An inline image inside a paragraph: 
inline: true config on the Image extension.
A relative-path image that should be dropped with a warning, leaving the alt text behind: local-only.
9. Horizontal rule
Above the rule.
Below the rule.
10. YouTube embed (standalone link)
A bare YouTube URL on its own line should be promoted to an embed:
A YouTube link inside a paragraph stays as a regular link: visit https://www.youtube.com/watch?v=dQw4w9WgXcQ for the classic.
11. HTML — should be dropped
The importer drops raw HTML for security. The <details> block below should not render, and neither should the inline <span>:
A paragraph containing an inline styled span should keep only the surrounding text.
12. Edge cases
12.1 Empty heading
Below this line is an empty heading (no text) — the editor should still emit a heading node:
12.2 Long line wrapping
This paragraph is one very long line of text intended to test soft-wrap behaviour, narrow viewport rendering, and the table-of-contents truncation logic that lives in the right rail of the editor; it should wrap naturally and not introduce horizontal scrolling on a 1280px viewport.
12.3 Special characters
Em-dashes — like this — and en-dashes – like this – should survive intact. So should curly quotes "smart quotes" and apostrophes don't break.
Code with angle brackets: <Component prop="value" /> and an inline backtick literal `nested`.
12.4 List immediately after heading
Sub-heading
Item right after a heading
Should render without a blank paragraph in between
12.5 Code block right before EOF
// This is the very last block in the file.
export const ok = true