@yannelli/live-markdown-vue 1.0.0

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.
Files changed (2) hide show
  1. package/README.md +299 -0
  2. package/package.json +74 -0
package/README.md ADDED
@@ -0,0 +1,299 @@
1
+ # Vue 3 Markdown Editor
2
+
3
+ A Vue 3 markdown editor component built as a drop-in replacement for textarea. Based on EasyMDE with full TypeScript support.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install live-markdown-vue
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Basic Usage
14
+
15
+ ```vue
16
+ <script setup>
17
+ import { ref } from 'vue'
18
+ import { MarkdownEditor } from 'live-markdown-vue'
19
+ import 'live-markdown-vue/style.css'
20
+
21
+ const content = ref('')
22
+ </script>
23
+
24
+ <template>
25
+ <MarkdownEditor v-model="content" placeholder="Start writing..." />
26
+ </template>
27
+ ```
28
+
29
+ ### With All Options
30
+
31
+ ```vue
32
+ <script setup>
33
+ import { ref } from 'vue'
34
+ import { MarkdownEditor } from 'live-markdown-vue'
35
+ import 'live-markdown-vue/style.css'
36
+
37
+ const content = ref('# Hello World')
38
+
39
+ function handleUpload(file, onSuccess, onError) {
40
+ // Upload to your server
41
+ uploadToServer(file)
42
+ .then(url => onSuccess(url))
43
+ .catch(err => onError(err.message))
44
+ }
45
+ </script>
46
+
47
+ <template>
48
+ <MarkdownEditor
49
+ v-model="content"
50
+ placeholder="Start writing markdown..."
51
+ min-height="300px"
52
+ max-height="600px"
53
+ :autofocus="true"
54
+ :spellcheck="false"
55
+ :can-attach-files="true"
56
+ :file-attachments-max-size="5120"
57
+ :file-attachments-accepted-types="['image/png', 'image/jpeg', 'image/gif']"
58
+ :toolbar-buttons="[
59
+ ['bold', 'italic', 'strike'],
60
+ ['heading', 'blockquote', 'codeBlock'],
61
+ ['bulletList', 'orderedList'],
62
+ ['link', 'table'],
63
+ ['undo', 'redo']
64
+ ]"
65
+ direction="ltr"
66
+ @change="handleChange"
67
+ @blur="handleBlur"
68
+ @focus="handleFocus"
69
+ @upload="handleUpload"
70
+ />
71
+ </template>
72
+ ```
73
+
74
+ ### Disabled State (Read-only HTML Preview)
75
+
76
+ ```vue
77
+ <template>
78
+ <MarkdownEditor
79
+ v-model="content"
80
+ :disabled="true"
81
+ />
82
+ </template>
83
+ ```
84
+
85
+ ## Props
86
+
87
+ | Prop | Type | Default | Description |
88
+ |------|------|---------|-------------|
89
+ | `modelValue` | `string` | `''` | The markdown content (v-model) |
90
+ | `disabled` | `boolean` | `false` | Renders as HTML when true |
91
+ | `placeholder` | `string` | `''` | Placeholder text |
92
+ | `minHeight` | `string` | `'200px'` | Minimum editor height |
93
+ | `maxHeight` | `string` | `undefined` | Maximum editor height |
94
+ | `autofocus` | `boolean` | `false` | Focus on mount |
95
+ | `spellcheck` | `boolean` | `false` | Enable browser spellcheck |
96
+ | `toolbarButtons` | `string[][]` | See below | Toolbar button groups |
97
+ | `canAttachFiles` | `boolean` | `false` | Enable file attachments |
98
+ | `fileAttachmentsMaxSize` | `number` | `undefined` | Max file size in KB |
99
+ | `fileAttachmentsAcceptedTypes` | `string[]` | `undefined` | Accepted MIME types |
100
+ | `debounceMs` | `number` | `300` | Debounce delay for changes |
101
+ | `translations` | `object` | English | Button translations |
102
+ | `direction` | `'ltr' \| 'rtl'` | `'ltr'` | Text direction |
103
+
104
+ ### Default Toolbar Buttons
105
+
106
+ ```javascript
107
+ [
108
+ ['bold', 'italic', 'strike'],
109
+ ['heading', 'blockquote', 'codeBlock'],
110
+ ['bulletList', 'orderedList'],
111
+ ['link', 'table'],
112
+ ['undo', 'redo']
113
+ ]
114
+ ```
115
+
116
+ ### Available Toolbar Buttons
117
+
118
+ - `bold` - Bold text
119
+ - `italic` - Italic text
120
+ - `strike` - Strikethrough text
121
+ - `heading` - Cycle through heading levels
122
+ - `blockquote` - Block quote
123
+ - `codeBlock` - Code block
124
+ - `bulletList` - Unordered list
125
+ - `orderedList` - Ordered list
126
+ - `link` - Insert link
127
+ - `table` - Insert table
128
+ - `attachFiles` - Attach files (requires `canAttachFiles`)
129
+ - `undo` - Undo
130
+ - `redo` - Redo
131
+ - `preview` - Toggle preview
132
+ - `sideBySide` - Side-by-side edit/preview
133
+ - `fullscreen` - Fullscreen mode
134
+
135
+ ## Events
136
+
137
+ | Event | Payload | Description |
138
+ |-------|---------|-------------|
139
+ | `update:modelValue` | `string` | Emitted when content changes |
140
+ | `change` | `string` | Debounced content change |
141
+ | `blur` | - | Editor lost focus |
142
+ | `focus` | - | Editor gained focus |
143
+ | `upload` | `(file, onSuccess, onError)` | File upload requested |
144
+
145
+ ## Exposed Methods
146
+
147
+ Access via template ref:
148
+
149
+ ```vue
150
+ <script setup>
151
+ import { ref } from 'vue'
152
+
153
+ const editorRef = ref()
154
+
155
+ function focusEditor() {
156
+ editorRef.value?.focus()
157
+ }
158
+
159
+ function getContent() {
160
+ return editorRef.value?.getValue()
161
+ }
162
+ </script>
163
+
164
+ <template>
165
+ <MarkdownEditor ref="editorRef" v-model="content" />
166
+ </template>
167
+ ```
168
+
169
+ | Method | Returns | Description |
170
+ |--------|---------|-------------|
171
+ | `focus()` | - | Focus the editor |
172
+ | `blur()` | - | Blur the editor |
173
+ | `getValue()` | `string` | Get current content |
174
+ | `setValue(value)` | - | Set content |
175
+ | `getEditor()` | `EasyMDE \| null` | Get EasyMDE instance |
176
+
177
+ ## Customization
178
+
179
+ ### Custom Translations
180
+
181
+ ```vue
182
+ <MarkdownEditor
183
+ v-model="content"
184
+ :translations="{
185
+ bold: 'Fett',
186
+ italic: 'Kursiv',
187
+ strike: 'Durchgestrichen',
188
+ link: 'Link',
189
+ heading: 'Überschrift',
190
+ blockquote: 'Zitat',
191
+ codeBlock: 'Code',
192
+ bulletList: 'Liste',
193
+ orderedList: 'Nummerierte Liste',
194
+ table: 'Tabelle',
195
+ attachFiles: 'Dateien',
196
+ undo: 'Rückgängig',
197
+ redo: 'Wiederholen',
198
+ preview: 'Vorschau',
199
+ sideBySide: 'Nebeneinander',
200
+ fullscreen: 'Vollbild'
201
+ }"
202
+ />
203
+ ```
204
+
205
+ ### Dark Mode
206
+
207
+ The editor supports dark mode through multiple methods:
208
+
209
+ **1. Parent `.dark` class (Tailwind CSS compatible):**
210
+
211
+ ```vue
212
+ <template>
213
+ <div class="dark">
214
+ <MarkdownEditor v-model="content" />
215
+ </div>
216
+ </template>
217
+ ```
218
+
219
+ **2. Direct class on container:**
220
+
221
+ ```vue
222
+ <template>
223
+ <MarkdownEditor class="dark" v-model="content" />
224
+ </template>
225
+ ```
226
+
227
+ **3. Automatic system detection:**
228
+
229
+ The editor automatically detects `prefers-color-scheme: dark` and applies dark mode styles.
230
+
231
+ **Force light mode:**
232
+
233
+ To force light mode when the system prefers dark, add the `.light` class:
234
+
235
+ ```vue
236
+ <template>
237
+ <MarkdownEditor class="light" v-model="content" />
238
+ </template>
239
+ ```
240
+
241
+ ### CSS Customization
242
+
243
+ The component uses CSS custom properties for theming. Override these variables to customize colors:
244
+
245
+ ```css
246
+ .markdown-editor-container {
247
+ --mde-bg: #ffffff;
248
+ --mde-bg-secondary: #f8fafc;
249
+ --mde-bg-tertiary: #f3f4f6;
250
+ --mde-bg-code: #1f2937;
251
+ --mde-border: #e2e8f0;
252
+ --mde-border-light: #e5e7eb;
253
+ --mde-text: #374151;
254
+ --mde-text-muted: #6b7280;
255
+ --mde-text-toolbar: #64748b;
256
+ --mde-text-code: #f9fafb;
257
+ --mde-link: #2563eb;
258
+ --mde-link-hover: #1d4ed8;
259
+ --mde-hover: #e2e8f0;
260
+ --mde-cursor: #000000;
261
+ }
262
+ ```
263
+
264
+ You can also override specific styles:
265
+
266
+ ```css
267
+ /* Override editor styles */
268
+ .markdown-editor-container .EasyMDEContainer {
269
+ border-color: #your-color;
270
+ }
271
+
272
+ .markdown-editor-container .editor-toolbar {
273
+ background-color: #your-bg;
274
+ }
275
+
276
+ .markdown-editor-container .CodeMirror {
277
+ font-family: 'Your Font', monospace;
278
+ }
279
+ ```
280
+
281
+ ## Development
282
+
283
+ ```bash
284
+ # Install dependencies
285
+ npm install
286
+
287
+ # Start dev server
288
+ npm run dev
289
+
290
+ # Run tests
291
+ npm test
292
+
293
+ # Build for production
294
+ npm run build
295
+ ```
296
+
297
+ ## License
298
+
299
+ MIT
package/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "@yannelli/live-markdown-vue",
3
+ "author": "Ryan Yannelli <ryanyannelli@gmail.com> (https://ryanyannelli.com)",
4
+ "homepage": "https://github.com/yannelli/live-markdown-vue",
5
+ "version": "1.0.0",
6
+ "description": "A Vue 3 markdown editor component with live preview, built as a drop-in replacement for textarea",
7
+ "type": "module",
8
+ "main": "./dist/live-markdown-vue.umd.cjs",
9
+ "module": "./dist/live-markdown-vue.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/live-markdown-vue.js",
14
+ "require": "./dist/live-markdown-vue.umd.cjs",
15
+ "types": "./dist/index.d.ts"
16
+ },
17
+ "./style.css": "./dist/style.css"
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "scripts": {
23
+ "dev": "vite",
24
+ "build": "vue-tsc -b && vite build",
25
+ "preview": "vite preview",
26
+ "test": "vitest",
27
+ "test:run": "vitest run",
28
+ "test:coverage": "vitest run --coverage",
29
+ "lint": "eslint . --ext .vue,.js,.ts,.tsx --fix",
30
+ "type-check": "vue-tsc --noEmit"
31
+ },
32
+ "dependencies": {
33
+ "dompurify": "^3.2.3",
34
+ "easymde": "^2.18.0",
35
+ "marked": "^15.0.4"
36
+ },
37
+ "peerDependencies": {
38
+ "vue": "^3.4.0"
39
+ },
40
+ "devDependencies": {
41
+ "@types/dompurify": "^3.0.5",
42
+ "@types/node": "^22.10.2",
43
+ "@vitejs/plugin-vue": "^5.2.1",
44
+ "@vitest/coverage-v8": "^4.0.16",
45
+ "@vue/test-utils": "^2.4.6",
46
+ "happy-dom": "^20.0.11",
47
+ "typescript": "~5.7.2",
48
+ "vite": "^6.0.5",
49
+ "vite-plugin-dts": "^4.3.0",
50
+ "vitest": "^4.0.16",
51
+ "vue": "^3.5.13",
52
+ "vue-tsc": "^2.2.0"
53
+ },
54
+ "keywords": [
55
+ "vue",
56
+ "vue3",
57
+ "markdown",
58
+ "editor",
59
+ "textarea",
60
+ "codemirror",
61
+ "easymde"
62
+ ],
63
+ "license": "MIT",
64
+ "repository": {
65
+ "type": "git",
66
+ "url": "git+https://github.com/yannelli/live-markdown-vue.git"
67
+ },
68
+ "directories": {
69
+ "test": "tests"
70
+ },
71
+ "bugs": {
72
+ "url": "https://github.com/yannelli/live-markdown-vue/issues"
73
+ }
74
+ }