@pinkpixel/marzipan 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,57 @@
1
+ # Plugin Catalogue
2
+
3
+ Marzipan ships first-party plugins from the `src/plugins` directory. Each plugin exports a factory from `@pinkpixel/marzipan/plugins/<name>` so you can opt into only the code you need.
4
+
5
+ ## Using a plugin
6
+
7
+ ```ts
8
+ import { Marzipan } from '@pinkpixel/marzipan';
9
+ import { tablePlugin } from '@pinkpixel/marzipan/plugins/tablePlugin';
10
+
11
+ new Marzipan('#editor', {
12
+ toolbar: true,
13
+ plugins: [tablePlugin({
14
+ defaultColumns: 3,
15
+ defaultRows: 4,
16
+ })],
17
+ });
18
+ ```
19
+
20
+ Every factory returns an object that Marzipan consumes internally. You can mix and match plugins freely.
21
+
22
+ ## Available plugins
23
+
24
+ | Plugin | Import Path | Description |
25
+ |--------|-------------|-------------|
26
+ | `accentSwatchPlugin` | `@pinkpixel/marzipan/plugins/accentSwatchPlugin` | Adds a palette picker for accent colours and syncs with the toolbar + stats bar. |
27
+ | `imageManagerPlugin` | `@pinkpixel/marzipan/plugins/imageManagerPlugin` | Dropzone and gallery UI for inserting images and managing uploads. |
28
+ | `imagePickerPlugin` | `@pinkpixel/marzipan/plugins/imagePickerPlugin` | Toolbar button for inserting images via URL or optional uploader callback. |
29
+ | `mermaidPlugin` | `@pinkpixel/marzipan/plugins/mermaidPlugin` | Lazy-loads Mermaid from npm/ESM and renders diagrams inline. |
30
+ | `mermaidExternalPlugin` | `@pinkpixel/marzipan/plugins/mermaidExternal` | Mermaid integration that targets a CDN script tag—perfect for sandboxed playgrounds. |
31
+ | `tablePlugin` | `@pinkpixel/marzipan/plugins/tablePlugin` | Toolbar-driven table generator with inline editing controls. |
32
+ | `tableGridPlugin` | `@pinkpixel/marzipan/plugins/tableGridPlugin` | Grid overlay for rapid column/row creation (exports `tableGridStyles`). |
33
+ | `tableGeneratorPlugin` | `@pinkpixel/marzipan/plugins/tableGenerator` | Quick GFM table inserter with prompt-driven sizing. |
34
+ | `tinyHighlightPlugin` | `@pinkpixel/marzipan/plugins/tinyHighlight` | Zero-runtime syntax highlighting for fenced code blocks (`tinyHighlightStyles` helper available). |
35
+
36
+ > 📝 The plugin names map 1:1 to files in `src/plugins`. Inspect those files for advanced configuration options.
37
+
38
+ ## Configuration tips
39
+
40
+ - **Tree shaking** – Import plugins individually; bundlers remove unused exports automatically.
41
+ - **Styling** – Some plugins inject their own CSS. Bakeshop demonstrates how to mirror the styling in your app.
42
+ - **Events** – Many plugins accept callbacks (e.g., image handlers). Pass your own upload or analytics hooks through the factory options.
43
+ - **Server-side rendering** – When using SSR, guard plugin usage behind `typeof window !== 'undefined'` if they rely on browser-only APIs.
44
+
45
+ ## Demo coverage
46
+
47
+ The `bakeshop-demo` application renders every plugin in the “Plugin Gallery” panel. Launch it with:
48
+
49
+ ```bash
50
+ cd bakeshop-demo
51
+ npm install
52
+ npm run dev
53
+ ```
54
+
55
+ Use the panel toggles to see plugin behaviour before integrating it into your own project.
56
+
57
+ For change history and new additions, see the [CHANGELOG](../CHANGELOG.md).
@@ -0,0 +1,90 @@
1
+ # Marzipan Quick Start Guide
2
+
3
+ Spin up the editor, wire up the bundled actions, and opt into plugins in just a few steps. 🎉
4
+
5
+ ## 1. Install the package
6
+
7
+ ```bash
8
+ npm install @pinkpixel/marzipan
9
+ ```
10
+
11
+ The package ships ESM output and TypeScript definitions. No extra formatting dependencies are required.
12
+
13
+ ## 2. Render your first editor
14
+
15
+ ```ts
16
+ import { Marzipan } from '@pinkpixel/marzipan';
17
+
18
+ const [editor] = new Marzipan('#my-editor', {
19
+ placeholder: 'Start writing…',
20
+ toolbar: true,
21
+ theme: 'solar',
22
+ smartLists: true,
23
+ });
24
+ ```
25
+
26
+ You can pass a selector string, DOM element, `NodeList`, or array of elements. The constructor always returns an array of instances.
27
+
28
+ ## 3. Trigger formatting with bundled actions
29
+
30
+ ```ts
31
+ import { actions } from '@pinkpixel/marzipan';
32
+
33
+ const textarea = document.querySelector<HTMLTextAreaElement>('#my-editor textarea');
34
+ if (textarea) {
35
+ actions.toggleBold(textarea);
36
+ }
37
+ ```
38
+
39
+ All actions accept the target `HTMLTextAreaElement`. They’re the same utilities used internally by the toolbar and keyboard shortcuts.
40
+
41
+ ## 4. Enable a plugin
42
+
43
+ Every plugin in `src/plugins` publishes under `@pinkpixel/marzipan/plugins/<name>`.
44
+
45
+ ```ts
46
+ import { tablePlugin } from '@pinkpixel/marzipan/plugins/tablePlugin';
47
+ import { tinyHighlight } from '@pinkpixel/marzipan/plugins/tinyHighlight';
48
+
49
+ new Marzipan('#with-plugins', {
50
+ plugins: [tablePlugin(), tinyHighlight()],
51
+ });
52
+ ```
53
+
54
+ Each plugin exports a factory so you can configure behavior before adding it to the editor instance.
55
+
56
+ ## 5. React usage (example)
57
+
58
+ ```tsx
59
+ import { useEffect, useRef } from 'react';
60
+ import { Marzipan } from '@pinkpixel/marzipan';
61
+ import { actions } from '@pinkpixel/marzipan';
62
+
63
+ export function Editor() {
64
+ const hostRef = useRef<HTMLDivElement>(null);
65
+
66
+ useEffect(() => {
67
+ if (!hostRef.current) return;
68
+ const [instance] = new Marzipan(hostRef.current, { toolbar: true });
69
+ return () => instance.destroy?.();
70
+ }, []);
71
+
72
+ return <div ref={hostRef} />;
73
+ }
74
+ ```
75
+
76
+ ## 6. Explore the Bakeshop demo
77
+
78
+ ```bash
79
+ cd bakeshop-demo
80
+ npm install
81
+ npm run dev
82
+ ```
83
+
84
+ Open `http://localhost:5173` to experiment with every option, plugin, and action in a guided playground.
85
+
86
+ ## Next steps
87
+
88
+ - Review the [API reference](./api.md) for events, helpers, and configuration details.
89
+ - Browse the [Plugin Catalogue](./plugins.md) to discover tables, Mermaid, image helpers, and more.
90
+ - Check [../CHANGELOG.md](../CHANGELOG.md) for the latest updates.
@@ -0,0 +1,231 @@
1
+ /**
2
+ * TypeScript definitions for Marzipan markdown editor
3
+ * @version 1.0.0
4
+ * @author Pink Pixel
5
+ */
6
+
7
+ export interface MarzipanTheme {
8
+ name: string;
9
+ colors: ThemeColors;
10
+ }
11
+
12
+ export interface ThemeColors {
13
+ // Base colors
14
+ background: string;
15
+ text: string;
16
+ textMuted?: string;
17
+
18
+ // Syntax highlighting
19
+ comment: string;
20
+ keyword: string;
21
+ string: string;
22
+ number: string;
23
+ punctuation?: string;
24
+
25
+ // UI elements
26
+ selection?: string;
27
+ border?: string;
28
+ toolbar?: string;
29
+
30
+ // Interactive elements
31
+ linkHover?: string;
32
+ buttonActive?: string;
33
+
34
+ // Additional colors for custom themes
35
+ [key: string]: string | undefined;
36
+ }
37
+
38
+ export interface MarzipanMobileOptions {
39
+ fontSize: string;
40
+ padding: string;
41
+ lineHeight: number;
42
+ }
43
+
44
+ export interface StatsData {
45
+ chars: number;
46
+ words: number;
47
+ lines: number;
48
+ line: number;
49
+ column: number;
50
+ }
51
+
52
+ export type StatsFormatter = (stats: StatsData) => string;
53
+
54
+ export type ChangeHandler = (value: string, instance: Marzipan) => void;
55
+
56
+ export type KeydownHandler = (event: KeyboardEvent, instance: Marzipan) => void;
57
+
58
+ export interface ToolbarConfig {
59
+ buttons: Array<ToolbarButton | '|'>;
60
+ }
61
+
62
+ export type ToolbarButton =
63
+ | 'bold'
64
+ | 'italic'
65
+ | 'strikethrough'
66
+ | 'code'
67
+ | 'link'
68
+ | 'image'
69
+ | 'quote'
70
+ | 'ul'
71
+ | 'ol'
72
+ | 'hr'
73
+ | 'toggle-plain';
74
+
75
+ export interface TextareaProps {
76
+ [key: string]: any;
77
+ className?: string;
78
+ class?: string;
79
+ style?: Partial<CSSStyleDeclaration> | string;
80
+ 'aria-label'?: string;
81
+ 'data-testid'?: string;
82
+ maxlength?: number;
83
+ rows?: number;
84
+ cols?: number;
85
+ }
86
+
87
+ export interface MarzipanOptions {
88
+ // Typography
89
+ fontSize?: string;
90
+ lineHeight?: number;
91
+ fontFamily?: string;
92
+ padding?: string;
93
+
94
+ // Mobile-specific styles
95
+ mobile?: Partial<MarzipanMobileOptions>;
96
+
97
+ // Textarea properties
98
+ textareaProps?: TextareaProps;
99
+
100
+ // Behavior
101
+ autofocus?: boolean;
102
+ autoResize?: boolean;
103
+ minHeight?: string;
104
+ maxHeight?: string | null;
105
+ placeholder?: string;
106
+ value?: string;
107
+
108
+ // Callbacks
109
+ onChange?: ChangeHandler;
110
+ onKeydown?: KeydownHandler;
111
+
112
+ // Features
113
+ showActiveLineRaw?: boolean;
114
+ showStats?: boolean;
115
+ toolbar?: boolean | ToolbarConfig;
116
+ statsFormatter?: StatsFormatter;
117
+ smartLists?: boolean;
118
+
119
+ // Themes (per-instance)
120
+ theme?: string | MarzipanTheme;
121
+ }
122
+
123
+ export interface RenderOptions {
124
+ cleanHTML?: boolean;
125
+ }
126
+
127
+ export type TargetElement = string | Element | NodeList | Array<Element>;
128
+
129
+ export declare class Marzipan {
130
+ // Static properties
131
+ static instances: WeakMap<Element, Marzipan>;
132
+ static stylesInjected: boolean;
133
+ static globalListenersInitialized: boolean;
134
+ static instanceCount: number;
135
+ static currentTheme: MarzipanTheme;
136
+
137
+ // Static attached utilities
138
+ static MarkdownParser: any;
139
+ static ShortcutsManager: any;
140
+ static themes: { [key: string]: MarzipanTheme };
141
+ static getTheme: (name: string) => MarzipanTheme | null;
142
+
143
+ // Instance properties
144
+ element: Element;
145
+ container: HTMLElement;
146
+ wrapper: HTMLElement;
147
+ textarea: HTMLTextAreaElement;
148
+ preview: HTMLElement;
149
+ statsBar?: HTMLElement;
150
+ toolbar?: any;
151
+ shortcuts: any;
152
+ linkTooltip: any;
153
+
154
+ options: Required<MarzipanOptions>;
155
+ instanceId: number;
156
+ initialized: boolean;
157
+ instanceTheme: string | MarzipanTheme | null;
158
+
159
+ // Constructor
160
+ constructor(target: TargetElement, options?: MarzipanOptions);
161
+
162
+ // Instance methods - Content Management
163
+ getValue(): string;
164
+ setValue(value: string): void;
165
+ getRenderedHTML(options?: RenderOptions): string;
166
+ getPreviewHTML(): string;
167
+ getCleanHTML(): string;
168
+
169
+ // Instance methods - Focus Management
170
+ focus(): void;
171
+ blur(): void;
172
+
173
+ // Instance methods - Display Modes
174
+ showPlainTextarea(show: boolean): boolean;
175
+ showPreviewMode(show: boolean): boolean;
176
+ showStats(show: boolean): void;
177
+
178
+ // Instance methods - Editor State
179
+ updatePreview(): void;
180
+ isInitialized(): boolean;
181
+ reinit(options?: Partial<MarzipanOptions>): void;
182
+ destroy(): void;
183
+
184
+ // Instance methods - Event Handlers (typically internal)
185
+ handleInput(event: Event): void;
186
+ handleKeydown(event: KeyboardEvent): void;
187
+ handleScroll(event: Event): void;
188
+ handleSmartListContinuation(): boolean;
189
+
190
+ // Static methods
191
+ static init(target: TargetElement, options?: MarzipanOptions): Array<Marzipan>;
192
+ static getInstance(element: Element): Marzipan | null;
193
+ static destroyAll(): void;
194
+ static setTheme(theme: string | MarzipanTheme, customColors?: Partial<ThemeColors>): void;
195
+ static injectStyles(force?: boolean): void;
196
+ static initGlobalListeners(): void;
197
+ }
198
+
199
+ // Default export
200
+ export default Marzipan;
201
+
202
+ // Module declaration for environments that need it
203
+ declare module '@pinkpixel/marzipan' {
204
+ export default Marzipan;
205
+ export {
206
+ Marzipan,
207
+ MarzipanOptions,
208
+ MarzipanTheme,
209
+ ThemeColors,
210
+ StatsData,
211
+ StatsFormatter,
212
+ ChangeHandler,
213
+ KeydownHandler,
214
+ ToolbarConfig,
215
+ ToolbarButton,
216
+ TextareaProps,
217
+ RenderOptions,
218
+ TargetElement
219
+ };
220
+ }
221
+
222
+ // Global declaration for browser environments
223
+ declare global {
224
+ interface Window {
225
+ Marzipan: typeof Marzipan;
226
+ }
227
+
228
+ interface Element {
229
+ MarzipanInstance?: Marzipan;
230
+ }
231
+ }
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@pinkpixel/marzipan",
3
+ "version": "1.0.5",
4
+ "description": "Pure TypeScript markdown editor library with overlay preview",
5
+ "license": "Apache-2.0",
6
+ "type": "module",
7
+ "author": "Pink Pixel",
8
+ "email": "admin@pinkpixel.dev",
9
+ "homepage": "https://marzipan.pinkpixel.dev",
10
+ "repository": "https://github.com/pinkpixel-dev/marzipan",
11
+ "issues": "https://github.com/pinkpixel-dev/marzipan/issues",
12
+ "engines": {
13
+ "node": ">=20"
14
+ },
15
+ "main": "./dist/index.js",
16
+ "module": "./dist/index.js",
17
+ "types": "./dist/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "import": "./dist/index.js",
21
+ "types": "./dist/index.d.ts"
22
+ },
23
+ "./plugins/*": {
24
+ "import": "./dist/plugins/*.js",
25
+ "types": "./dist/plugins/*.d.ts"
26
+ }
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "README.md",
31
+ "docs"
32
+ ],
33
+ "scripts": {
34
+ "dev": "vite build --watch",
35
+ "build": "tsc && vite build",
36
+ "lint": "eslint .",
37
+ "prettier": "prettier --write .",
38
+ "typecheck": "tsc --noEmit",
39
+ "prepublishOnly": "npm run build",
40
+ "prepack": "npm run build"
41
+ },
42
+ "keywords": [
43
+ "markdown",
44
+ "editor",
45
+ "typescript",
46
+ "library",
47
+ "lightweight",
48
+ "textarea",
49
+ "overlay",
50
+ "preview",
51
+ "wysiwyg"
52
+ ],
53
+ "devDependencies": {
54
+ "@eslint/js": "^9.36.0",
55
+ "@types/node": "^24.5.2",
56
+ "@typescript-eslint/eslint-plugin": "8.44.1",
57
+ "@typescript-eslint/parser": "8.44.1",
58
+ "eslint": "^9.36.0",
59
+ "globals": "16.4.0",
60
+ "mermaid": "^11.12.0",
61
+ "prettier": "^3.6.2",
62
+ "typescript": "^5.9.2",
63
+ "typescript-eslint": "^8.44.1",
64
+ "vite": "^7.1.7"
65
+ }
66
+ }