Skip to content
On this page

Quick Start

Spin up the editor, wire up the bundled actions, and opt into plugins in just a few steps. ๐ŸŽ‰

1. Install the Package

Choose your favorite package manager:

::: code-group

bash [npm]
npm install @pinkpixel/marzipan
bash [pnpm]
pnpm add @pinkpixel/marzipan
bash [yarn]
yarn add @pinkpixel/marzipan

:::

The package ships ESM output and TypeScript definitions. No extra formatting dependencies are required.

2. Render Your First Editor

ts
import { Marzipan } from '@pinkpixel/marzipan';

const [editor] = new Marzipan('#my-editor', {
  placeholder: 'Start writingโ€ฆ',
  toolbar: true,
  theme: 'solar',
  smartLists: true,
});

You can pass a selector string, DOM element, NodeList, or array of elements. The constructor always returns an array of instances.

TIP

Use array destructuring for a single editor instance:

ts
const [editor] = new Marzipan('#my-editor');

3. Trigger Formatting with Bundled Actions

ts
import { actions } from '@pinkpixel/marzipan';

const textarea = document.querySelector<HTMLTextAreaElement>('#my-editor textarea');
if (textarea) {
  actions.toggleBold(textarea);
  actions.toggleItalic(textarea);
  actions.insertLink(textarea);
}

All actions accept the target HTMLTextAreaElement. They're the same utilities used internally by the toolbar and keyboard shortcuts.

INFO

No need to install markdown-actions or similar packages - all formatting helpers are bundled with Marzipan!

4. Enable a Plugin

Every plugin in src/plugins publishes under @pinkpixel/marzipan/plugins/<name>.

ts
import { tablePlugin } from '@pinkpixel/marzipan/plugins/tablePlugin';
import { tinyHighlight } from '@pinkpixel/marzipan/plugins/tinyHighlight';

new Marzipan('#with-plugins', {
  plugins: [tablePlugin(), tinyHighlight()],
});

Each plugin exports a factory so you can configure behavior before adding it to the editor instance.

Available Plugins
  • Tables: tablePlugin, tableGridPlugin, tableGeneratorPlugin
  • Syntax Highlighting: tinyHighlight
  • Diagrams: mermaidPlugin, mermaidExternalPlugin
  • Images: imagePickerPlugin, imageManagerPlugin
  • Theming: accentSwatchPlugin

See the Plugins Overview for details.

5. Framework Integration

React Example

tsx
import { useEffect, useRef } from 'react';
import { Marzipan } from '@pinkpixel/marzipan';

export function Editor() {
  const hostRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!hostRef.current) return;
    const [instance] = new Marzipan(hostRef.current, { 
      toolbar: true,
      theme: 'cave',
    });
    return () => instance.destroy?.();
  }, []);

  return <div ref={hostRef} />;
}

Vue Example

vue
<template>
  <div ref="editorRef"></div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { Marzipan } from '@pinkpixel/marzipan';

const editorRef = ref<HTMLDivElement>();
let editor: Marzipan;

onMounted(() => {
  if (editorRef.value) {
    [editor] = new Marzipan(editorRef.value, {
      toolbar: true,
    });
  }
});

onUnmounted(() => {
  editor?.destroy?.();
});
</script>

Svelte Example

svelte
<script lang="ts">
  import { onMount, onDestroy } from 'svelte';
  import { Marzipan } from '@pinkpixel/marzipan';

  let editorDiv: HTMLDivElement;
  let editor: Marzipan;

  onMount(() => {
    [editor] = new Marzipan(editorDiv, {
      toolbar: true,
    });
  });

  onDestroy(() => {
    editor?.destroy?.();
  });
</script>

<div bind:this={editorDiv}></div>

6. Explore the Bakeshop Demo

The Marzipan repository includes a full-featured demo application:

bash
cd bakeshop-demo
npm install
npm run dev

Open http://localhost:5173 to experiment with every option, plugin, and action in a guided playground.

Common Patterns

Custom Toolbar Buttons

ts
import { Marzipan, actions } from '@pinkpixel/marzipan';

const [editor] = new Marzipan('#editor', {
  toolbar: false, // Disable default toolbar
});

// Create custom button
const boldButton = document.createElement('button');
boldButton.textContent = 'Bold';
boldButton.addEventListener('click', () => {
  const textarea = editor.textarea;
  if (textarea) actions.toggleBold(textarea);
});

Listening to Changes

ts
const [editor] = new Marzipan('#editor', {
  onChange: (value) => {
    console.log('Content changed:', value);
    // Save to localStorage, sync to server, etc.
  },
});

Programmatic Content Updates

ts
const [editor] = new Marzipan('#editor');

// Set initial content
editor.setValue('# Welcome\n\nStart writing!');

// Get current content
const markdown = editor.getValue();

// Get rendered HTML
const html = editor.getRenderedHTML();

Next Steps

Now that you have a working editor, dive deeper:

Need Help?

  • ๐Ÿ› Issues - Report bugs or request features
  • ๐Ÿ’ฌ Discussions - Ask questions and share ideas
  • ๐Ÿ“ง Email - Direct support

Released under the Apache 2.0 License