quikdown_bd - Bidirectional Markdown/HTML Conversion

⚠️ Important: Use quikdown_bd, not quikdown

Bidirectional conversion is only available in the quikdown_bd module. The regular quikdown module does NOT support HTML-to-Markdown conversion.

// ✅ Correct - Use quikdown_bd for bidirectional support
import quikdown_bd from 'quikdown/bd';

// ❌ Wrong - Regular quikdown doesn't have bidirectional support
import quikdown from 'quikdown';
// quikdown.toMarkdown(html); // Error: toMarkdown is not a function

Overview

quikdown_bd is a separate build of quikdown that provides bidirectional conversion between Markdown and HTML. It includes all the features of regular quikdown PLUS the ability to convert HTML back to Markdown, preserving the original structure and formatting.

New in v1.0.5: The core quikdown module now supports emitting data-qd attributes via the bidirectional option, though it doesn't include the toMarkdown function. The quikdown_bd module automatically enables this option and adds the HTML-to-Markdown conversion capability.

Installation

npm install quikdown

Then import the bidirectional module:

// ES6 modules
import quikdown_bd from 'quikdown/bd';

// CommonJS
const quikdown_bd = require('quikdown/dist/quikdown_bd.cjs');

// Browser (UMD)
<script src="https://unpkg.com/quikdown/dist/quikdown_bd.umd.min.js"></script>

Basic Usage

Forward Conversion (Markdown → HTML)

const markdown = '**Hello** *world*!';
const html = quikdown_bd(markdown);
// Output: <p><strong data-qd="**" class="quikdown-strong">Hello</strong> <em data-qd="*" class="quikdown-em">world</em>!</p>

Reverse Conversion (HTML → Markdown)

const html = '<p><strong>Hello</strong> <em>world</em>!</p>';
const markdown = quikdown_bd.toMarkdown(html);
// Output: **Hello** *world*!

Round-trip Conversion

const originalMarkdown = '# Heading\n\n**Bold** and *italic* text.';
const html = quikdown_bd(originalMarkdown);
const recoveredMarkdown = quikdown_bd.toMarkdown(html);
// recoveredMarkdown ≈ originalMarkdown

Key Features

Data Attributes for Source Tracking

quikdown_bd adds data-qd attributes to HTML elements to track the original Markdown syntax:

quikdown_bd('**bold**')
// <strong data-qd="**" class="quikdown-strong">bold</strong>

quikdown_bd('~~strike~~')
// <del data-qd="~~" class="quikdown-del">strike</del>

Supported Elements

All standard Markdown elements are supported for bidirectional conversion:

Returns: Configured parser function

Browser vs Node.js Usage

Browser

// Works natively in browsers with DOM support
const html = quikdown_bd('# Hello');
const markdown = quikdown_bd.toMarkdown(html);

Node.js

// Requires a DOM implementation for toMarkdown
const { JSDOM } = require('jsdom');
global.document = new JSDOM().window.document;

const html = quikdown_bd('# Hello');
const markdown = quikdown_bd.toMarkdown(html);

Limitations

What Works Well

Known Limitations

  1. Custom HTML: Non-quikdown HTML may not convert accurately
  2. Whitespace: Some whitespace normalization occurs
  3. Mermaid: Diagrams render but can't be edited as diagrams
  4. Complex Tables: Very complex nested tables may lose formatting
  5. Inline HTML: Raw HTML in Markdown is escaped for safety

Not Suitable For

Performance

Examples

Live Editor

// Create a live bidirectional editor
const editor = {
  markdown: document.getElementById('markdown-input'),
  html: document.getElementById('html-output'),
  
  updateHTML() {
    this.html.innerHTML = quikdown_bd(this.markdown.value);
  },
  
  updateMarkdown() {
    this.markdown.value = quikdown_bd.toMarkdown(this.html.innerHTML);
  }
};

// Two-way binding
editor.markdown.addEventListener('input', () => editor.updateHTML());
editor.html.addEventListener('input', () => editor.updateMarkdown());

With Syntax Highlighting

const options = {
  fence_plugin: {
    render: (code, lang) => {
      if (lang && window.hljs) {
        const highlighted = hljs.highlight(code, { language: lang }).value;
        return `<pre><code class="language-${lang}">${highlighted}</code></pre>`;
      }
    }
  }
};

const html = quikdown_bd(markdown, options);

Migration from Regular quikdown

// Before (one-way)
import quikdown from 'quikdown';
const html = quikdown(markdown);

// After (bidirectional)
import quikdown_bd from 'quikdown/bd';
const html = quikdown_bd(markdown);
const recoveredMarkdown = quikdown_bd.toMarkdown(html);

Best Practices

  1. Use for quikdown content: Best results with quikdown-generated HTML
  2. Preserve data attributes: Don't remove data-qd attributes if you need reverse conversion
  3. Test round-trips: Verify your content survives round-trip conversion
  4. Handle edge cases: Plan for imperfect conversions with user-generated content
  5. Performance: Use debouncing for live editors with large documents

TypeScript Support

import quikdown_bd from 'quikdown/bd';
import type { QuikdownBDOptions } from 'quikdown/bd';

const options: QuikdownBDOptions = {
  inline_styles: true,
  fence_plugin: {
    render: (code: string, lang: string) => {
      return `<pre class="${lang}">${code}</pre>`;
    }
  }
};

const html: string = quikdown_bd(markdown, options);
const md: string = quikdown_bd.toMarkdown(html);

Version

quikdown_bd uses the same version as core quikdown: 1.2.3

License

BSD-2-Clause - Same as quikdown core