quikdown 1.0.4 → 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.
- package/README.md +118 -499
- package/dist/quikdown.cjs +105 -41
- package/dist/quikdown.d.ts +14 -0
- package/dist/quikdown.dark.css +1 -1
- package/dist/quikdown.esm.js +105 -41
- package/dist/quikdown.esm.min.js +2 -2
- package/dist/quikdown.esm.min.js.map +1 -1
- package/dist/quikdown.light.css +1 -1
- package/dist/quikdown.umd.js +105 -41
- package/dist/quikdown.umd.min.js +2 -2
- package/dist/quikdown.umd.min.js.map +1 -1
- package/dist/quikdown_bd.cjs +562 -258
- package/dist/quikdown_bd.d.ts +45 -13
- package/dist/quikdown_bd.esm.js +562 -258
- package/dist/quikdown_bd.esm.min.js +2 -2
- package/dist/quikdown_bd.esm.min.js.map +1 -1
- package/dist/quikdown_bd.umd.js +562 -258
- package/dist/quikdown_bd.umd.min.js +2 -2
- package/dist/quikdown_bd.umd.min.js.map +1 -1
- package/dist/quikdown_edit.cjs +2319 -0
- package/dist/quikdown_edit.d.ts +195 -0
- package/dist/quikdown_edit.esm.js +2317 -0
- package/dist/quikdown_edit.esm.min.js +14 -0
- package/dist/quikdown_edit.esm.min.js.map +1 -0
- package/dist/quikdown_edit.umd.js +2325 -0
- package/dist/quikdown_edit.umd.min.js +14 -0
- package/dist/quikdown_edit.umd.min.js.map +1 -0
- package/package.json +79 -9
- package/dist/quikdown-lex.cjs +0 -810
- package/dist/quikdown-lex.esm.js +0 -808
- package/dist/quikdown-lex.esm.min.js +0 -8
- package/dist/quikdown-lex.esm.min.js.map +0 -1
- package/dist/quikdown-lex.umd.js +0 -816
- package/dist/quikdown-lex.umd.min.js +0 -8
- package/dist/quikdown-lex.umd.min.js.map +0 -1
package/README.md
CHANGED
|
@@ -4,605 +4,229 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/quikdown)
|
|
5
5
|
[](https://github.com/deftio/quikdown)
|
|
6
6
|
[](https://opensource.org/licenses/BSD-2-Clause)
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
- [Features](#features)
|
|
20
|
-
- [Installation](#installation)
|
|
21
|
-
- [Quick Start](#quick-start)
|
|
22
|
-
- [Bidirectional Conversion](#bidirectional-conversion-new)
|
|
23
|
-
- [Supported Markdown](#supported-markdown)
|
|
24
|
-
- [Configuration Options](#configuration-options)
|
|
25
|
-
- [Plugin System](#plugin-system)
|
|
26
|
-
- [Framework Integration](#framework-integration)
|
|
27
|
-
- [API Reference](#api-reference)
|
|
28
|
-
- [Security](#security)
|
|
29
|
-
- [Contributing](#contributing)
|
|
7
|
+
|
|
8
|
+
Quikdown is a small, secure markdown parser with bidirectional conversion. Zero dependencies, XSS protection built-in, extensible via plugins for code highlighting and diagrams, and works in browser and Node.js.
|
|
9
|
+
|
|
10
|
+
For small and fast projects quikdown includes built-in inline styles for a "batteries included" rendering experience, but these can be overridden with themed css (see light and dark examples).
|
|
11
|
+
|
|
12
|
+
- **quikdown.js** (8.7KB) - Markdown to HTML Parser
|
|
13
|
+
- **quikdown_bd.js** (13KB) - Bidirectional (HTML ↔ Markdown) Parser
|
|
14
|
+
- **quikdown_edit.js** (36KB) - Drop-in editor component (HTML ↔ Markdown) with md/split/html views
|
|
15
|
+
|
|
16
|
+
🚀 **[Live Demo](https://deftio.github.io/quikdown/examples/quikdown-live.html)** | **[Editor Demo](https://deftio.github.io/quikdown/examples/qde/)** | **[Documentation](docs/)**
|
|
17
|
+
|
|
18
|
+
📍 **Quick Links:** [Installation](#installation) • [Quick Start](#quick-start) • [API](#api-reference) • [TypeScript](#typescript-support) • [Plugins](#fence-plugins) • [Examples](examples/)
|
|
30
19
|
|
|
31
20
|
## Features
|
|
32
21
|
|
|
33
22
|
- 📦 **Zero dependencies** - No external libraries required
|
|
34
23
|
- 🌐 **Universal** - Works in browsers and Node.js
|
|
35
|
-
- 🚀 **Lightweight** -
|
|
24
|
+
- 🚀 **Lightweight** - 8.7KB (core), 13KB (bidirectional), 36KB (editor)
|
|
36
25
|
- 🔒 **Secure by default** - Built-in XSS protection with URL sanitization
|
|
37
|
-
- 🎨 **Flexible styling** - Inline styles or CSS classes
|
|
26
|
+
- 🎨 **Flexible styling** - Inline styles or CSS classes with theme support
|
|
38
27
|
- 🔌 **Plugin system** - Extensible fence block handlers
|
|
39
28
|
- ⚡ **Fast** - Optimized regex-based parsing
|
|
40
|
-
- 📝 **CommonMark subset** -
|
|
29
|
+
- 📝 **CommonMark subset** - Essential markdown features
|
|
41
30
|
- ✅ **Task Lists** - GitHub-style checkboxes
|
|
42
31
|
- 🔗 **Autolinks** - Automatic URL detection
|
|
43
|
-
- 🔄 **Bidirectional** - Convert HTML back to Markdown (
|
|
32
|
+
- 🔄 **Bidirectional** - Convert HTML back to Markdown (quikdown_bd)
|
|
33
|
+
- 💬 **Lazy linefeeds** - Single newlines become line breaks (configurable)
|
|
34
|
+
- 📱 **Editor component** - Drop-in markdown editor with live preview
|
|
44
35
|
|
|
45
36
|
## Installation
|
|
46
37
|
|
|
38
|
+
Quikdown is available via [NPM](https://www.npmjs.com/package/quikdown) and related [unpkg](https://unpkg.com/quikdown) and [jsdelivr](https://cdn.jsdelivr.net/npm/quikdown)
|
|
39
|
+
|
|
40
|
+
### NPM package
|
|
47
41
|
```bash
|
|
48
42
|
npm install quikdown
|
|
49
43
|
```
|
|
50
44
|
|
|
51
|
-
|
|
45
|
+
### CDN using UNPKG
|
|
52
46
|
|
|
53
|
-
**ES Modules
|
|
47
|
+
**CDN (ES Modules):**
|
|
54
48
|
```html
|
|
55
49
|
<script type="module">
|
|
56
50
|
import quikdown from 'https://unpkg.com/quikdown/dist/quikdown.esm.min.js';
|
|
57
|
-
|
|
58
|
-
const html = quikdown('# Hello World');
|
|
59
|
-
document.body.innerHTML = html;
|
|
51
|
+
document.body.innerHTML = quikdown('# Hello World');
|
|
60
52
|
</script>
|
|
61
53
|
```
|
|
62
54
|
|
|
63
|
-
**
|
|
55
|
+
**CDN (UMD):**
|
|
64
56
|
```html
|
|
65
57
|
<script src="https://unpkg.com/quikdown/dist/quikdown.umd.min.js"></script>
|
|
66
58
|
<script>
|
|
67
|
-
|
|
68
|
-
const html = quikdown('# Hello World');
|
|
59
|
+
document.body.innerHTML = quikdown('# Hello World');
|
|
69
60
|
</script>
|
|
70
61
|
```
|
|
71
62
|
|
|
72
|
-
> **Production tip:** Pin to a specific version for stability (e.g., `https://unpkg.com/quikdown@1.0.4/dist/quikdown.esm.min.js`)
|
|
73
|
-
|
|
74
63
|
## Quick Start
|
|
75
64
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
```javascript
|
|
79
|
-
import quikdown from 'quikdown';
|
|
80
|
-
|
|
81
|
-
const markdown = '# Hello World\n\nThis is **bold** text.';
|
|
82
|
-
const html = quikdown(markdown);
|
|
83
|
-
console.log(html);
|
|
84
|
-
// Output: <h1>Hello World</h1><p>This is <strong>bold</strong> text.</p>
|
|
85
|
-
|
|
86
|
-
// Note: Regular quikdown does NOT support HTML to Markdown conversion
|
|
87
|
-
```
|
|
65
|
+
Quikdown is built in 3 versions. The smallest (quikdown) provides markdown to html conversion only. The next (quikdown_bd) provides markdown to html and html to markdown support. The lightweight editor quikdown_edit allows a bidirectional editor with lazy loading for common fences such as codeblocks, svg, and mermaid diagrams is also provided.
|
|
88
66
|
|
|
89
|
-
###
|
|
67
|
+
### Markdown → HTML (quikdown.js)
|
|
90
68
|
|
|
91
69
|
```javascript
|
|
92
|
-
//
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
70
|
+
// Basic conversion
|
|
71
|
+
const html = quikdown('# Hello World',
|
|
72
|
+
{inline_styles: true} // Use inline styles, more options in API docs
|
|
73
|
+
);
|
|
96
74
|
|
|
97
|
-
|
|
98
|
-
const html = quikdown_bd(markdown);
|
|
75
|
+
document.body.innerHTML = html;
|
|
99
76
|
|
|
100
|
-
// HTML back to Markdown (only available in quikdown_bd)
|
|
101
|
-
const recoveredMarkdown = quikdown_bd.toMarkdown(html);
|
|
102
|
-
console.log(recoveredMarkdown);
|
|
103
|
-
// Output: # Hello World\n\nThis is **bold** text.
|
|
104
77
|
```
|
|
105
78
|
|
|
106
|
-
###
|
|
79
|
+
### Bidirectional Markdown ↔ HTML (quikdown_bd.js)
|
|
107
80
|
|
|
108
81
|
```javascript
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
fence_plugin: myFenceHandler // Custom code fence handler
|
|
112
|
-
});
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
### TypeScript Support
|
|
116
|
-
|
|
117
|
-
quikdown includes TypeScript definitions for better IDE support and type safety:
|
|
118
|
-
|
|
119
|
-
```typescript
|
|
120
|
-
import quikdown, { QuikdownOptions } from 'quikdown';
|
|
121
|
-
|
|
122
|
-
const options: QuikdownOptions = {
|
|
123
|
-
inline_styles: true,
|
|
124
|
-
fence_plugin: (content: string, language: string) => {
|
|
125
|
-
return `<pre class="hljs ${language}">${content}</pre>`;
|
|
126
|
-
}
|
|
127
|
-
};
|
|
82
|
+
// Convert with source tracking
|
|
83
|
+
const htmlString = quikdown_bd(markdown, options);
|
|
128
84
|
|
|
129
|
-
|
|
85
|
+
// Convert HTML back to Markdown
|
|
86
|
+
const markdown = quikdown_bd.toMarkdown(htmlString);
|
|
130
87
|
```
|
|
131
88
|
|
|
132
|
-
|
|
89
|
+
Note: quikdown does not provide a *generic* html to markdown conversion but uses special tags and limited DOM parsing for HTML to markdown conversion. Standard markdown components such as headings, text styles, tables, quotes, etc are supported. For custom fences quikdown relies on its tag system or 3rd party handlers to provide reverse (html to md) conversion.
|
|
133
90
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
### Text Formatting
|
|
137
|
-
- **Bold**: `**text**` or `__text__`
|
|
138
|
-
- *Italic*: `*text*` or `_text_`
|
|
139
|
-
- ~~Strikethrough~~: `~~text~~`
|
|
140
|
-
- `Code`: `` `code` ``
|
|
141
|
-
|
|
142
|
-
### Headings
|
|
143
|
-
```markdown
|
|
144
|
-
# H1 Heading
|
|
145
|
-
## H2 Heading
|
|
146
|
-
### H3 Heading
|
|
147
|
-
#### H4 Heading
|
|
148
|
-
##### H5 Heading
|
|
149
|
-
###### H6 Heading
|
|
150
|
-
```
|
|
91
|
+
### Editor (quikdown_edit.js)
|
|
151
92
|
|
|
152
|
-
|
|
93
|
+
```javascript
|
|
94
|
+
const editor = new QuikdownEditor('#container', {
|
|
95
|
+
mode: 'split', // 'source', 'split', 'preview'
|
|
96
|
+
theme: 'auto', // 'light', 'dark', 'auto'
|
|
97
|
+
plugins: { highlightjs: true, mermaid: true } // built-in fence handlers, see API docs for custom plugins
|
|
98
|
+
});
|
|
153
99
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
- Item 1
|
|
157
|
-
- Item 2
|
|
158
|
-
- Nested item
|
|
159
|
-
* Also works with asterisks
|
|
100
|
+
editor.setMarkdown('# Content \nTo be quik or not to be.'); // provide default content
|
|
101
|
+
const content = editor.getMarkdown(); // get source content, see APIs for getting / setting HTML
|
|
160
102
|
```
|
|
161
103
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
1. First item
|
|
165
|
-
2. Second item
|
|
166
|
-
1. Nested item
|
|
167
|
-
```
|
|
104
|
+
## Other Configuration Options
|
|
105
|
+
quikdown supports built-in styles for a "batteries included" experience or you can bring your own CSS themes. Example css files are provided for basic light and dark themes to get started.
|
|
168
106
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
107
|
+
```javascript
|
|
108
|
+
const html = quikdown(markdown, {
|
|
109
|
+
lazy_linefeeds: true, // Single newlines become <br>
|
|
110
|
+
inline_styles: false, // Use class based CSS instead of inline styles
|
|
111
|
+
fence_plugin: myHandler // Custom code block processor
|
|
112
|
+
});
|
|
174
113
|
```
|
|
175
114
|
|
|
176
|
-
###
|
|
177
|
-
```markdown
|
|
178
|
-
[Link text](https://example.com)
|
|
179
|
-

|
|
180
|
-
|
|
181
|
-
// Autolinks - URLs are automatically linked
|
|
182
|
-
Visit https://github.com for more info
|
|
183
|
-
```
|
|
115
|
+
### Styling Options
|
|
184
116
|
|
|
185
|
-
|
|
186
|
-
````markdown
|
|
117
|
+
**Inline styles:** All formatting uses inline CSS
|
|
187
118
|
```javascript
|
|
188
|
-
|
|
119
|
+
quikdown('**bold**', { inline_styles: true });
|
|
120
|
+
// <strong style="font-weight: bold;">bold</strong>
|
|
189
121
|
```
|
|
190
122
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
### Tables
|
|
198
|
-
```markdown
|
|
199
|
-
| Header 1 | Header 2 |
|
|
200
|
-
|----------|----------|
|
|
201
|
-
| Cell 1 | Cell 2 |
|
|
202
|
-
| Cell 3 | Cell 4 |
|
|
123
|
+
**Class-based styling:** Uses CSS classes (default)
|
|
124
|
+
```javascript
|
|
125
|
+
quikdown('**bold**');
|
|
126
|
+
// <strong>bold</strong>
|
|
127
|
+
// Requires CSS: .quikdown strong { font-weight: bold; }
|
|
128
|
+
// see included dist/quikdown.light.css or quikdown.dark.css
|
|
203
129
|
```
|
|
204
130
|
|
|
205
|
-
###
|
|
206
|
-
- **Blockquotes**: `> Quote text`
|
|
207
|
-
- **Horizontal rules**: `---` or `***` or `___`
|
|
208
|
-
- **Line breaks**: Two spaces at end of line or `<br>`
|
|
131
|
+
### Fence Plugins
|
|
209
132
|
|
|
210
|
-
|
|
133
|
+
Quikdown provides a callback for all fenced text such as code blocks, math, svg etc.
|
|
211
134
|
|
|
212
|
-
|
|
213
|
-
When `true`, uses inline styles for formatting. When `false`, uses CSS classes.
|
|
214
|
-
|
|
215
|
-
```javascript
|
|
216
|
-
// With inline_styles: true
|
|
217
|
-
quikdown('**bold**', { inline_styles: true });
|
|
218
|
-
// Output: <strong style="font-weight: bold;">bold</strong>
|
|
219
|
-
|
|
220
|
-
// With inline_styles: false (default)
|
|
221
|
-
quikdown('**bold**', { inline_styles: false });
|
|
222
|
-
// Output: <strong>bold</strong>
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
### `fence_plugin` (function)
|
|
226
|
-
Custom handler for fenced code blocks. Useful for syntax highlighting or diagrams.
|
|
135
|
+
Handle code blocks with custom languages:
|
|
227
136
|
|
|
228
137
|
```javascript
|
|
229
138
|
function fencePlugin(code, language) {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
139
|
+
if (language === 'mermaid') {
|
|
140
|
+
// Process with mermaid library and return rendered diagram
|
|
141
|
+
const id = 'mermaid-' + Math.random().toString(36).substr(2, 9);
|
|
142
|
+
setTimeout(() => mermaid.render(id + '-svg', code).then(result => {
|
|
143
|
+
document.getElementById(id).innerHTML = result.svg;
|
|
144
|
+
}), 0);
|
|
145
|
+
return `<div id="${id}" class="mermaid">Loading diagram...</div>`;
|
|
146
|
+
}
|
|
147
|
+
return `<pre>${code}</pre>`;
|
|
148
|
+
// Return undefined for default handling
|
|
234
149
|
}
|
|
235
150
|
|
|
236
151
|
const html = quikdown(markdown, { fence_plugin: fencePlugin });
|
|
237
152
|
```
|
|
238
153
|
|
|
239
|
-
## Plugin System
|
|
240
|
-
|
|
241
|
-
For a complete plugin development guide, see [docs/plugin-guide.md](docs/plugin-guide.md)
|
|
242
|
-
|
|
243
|
-
### Creating a Fence Plugin
|
|
244
154
|
|
|
245
|
-
|
|
155
|
+
## TypeScript Support
|
|
246
156
|
|
|
247
|
-
|
|
248
|
-
function myFencePlugin(code, language) {
|
|
249
|
-
// Handle specific languages
|
|
250
|
-
if (language === 'graph') {
|
|
251
|
-
return renderGraph(code);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// Add syntax highlighting
|
|
255
|
-
if (language && hljs.getLanguage(language)) {
|
|
256
|
-
const highlighted = hljs.highlight(code, { language }).value;
|
|
257
|
-
return `<pre><code class="language-${language}">${highlighted}</code></pre>`;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// Return undefined for default handling
|
|
261
|
-
return undefined;
|
|
262
|
-
}
|
|
263
|
-
```
|
|
157
|
+
quikdown includes TypeScript definitions for better IDE support and type safety:
|
|
264
158
|
|
|
265
|
-
|
|
159
|
+
``` javascript
|
|
160
|
+
import quikdown, { QuikdownOptions } from 'quikdown';
|
|
266
161
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
// Render with mermaid.js after DOM update
|
|
272
|
-
setTimeout(() => {
|
|
273
|
-
mermaid.render(id + '-svg', code).then(result => {
|
|
274
|
-
document.getElementById(id).innerHTML = result.svg;
|
|
275
|
-
});
|
|
276
|
-
}, 0);
|
|
277
|
-
return `<div id="${id}" class="mermaid">Loading diagram...</div>`;
|
|
162
|
+
const options: QuikdownOptions = {
|
|
163
|
+
inline_styles: true,
|
|
164
|
+
fence_plugin: (content: string, language: string) => {
|
|
165
|
+
return `<pre class="hljs ${language}">${content}</pre>`;
|
|
278
166
|
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
const html = quikdown(markdownWithMermaid, {
|
|
282
|
-
fence_plugin: mermaidPlugin
|
|
283
|
-
});
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
## Security
|
|
287
|
-
|
|
288
|
-
For detailed security information, see [docs/security.md](docs/security.md)
|
|
289
|
-
|
|
290
|
-
quikdown includes built-in XSS protection:
|
|
167
|
+
};
|
|
291
168
|
|
|
292
|
-
|
|
293
|
-
- Attributes are sanitized
|
|
294
|
-
- JavaScript URLs are blocked
|
|
295
|
-
- Only safe markdown constructs are converted to HTML
|
|
169
|
+
const html: string = quikdown(markdown, options);
|
|
296
170
|
|
|
297
|
-
```javascript
|
|
298
|
-
const unsafe = '<script>alert("XSS")</script> **bold**';
|
|
299
|
-
const safe = quikdown(unsafe);
|
|
300
|
-
// Output: <script>alert("XSS")</script> <strong>bold</strong>
|
|
301
171
|
```
|
|
302
172
|
|
|
303
|
-
##
|
|
173
|
+
## Supported Markdown
|
|
304
174
|
|
|
305
|
-
|
|
175
|
+
**Text formatting:** `**bold**`, `*italic*`, `~~strikethrough~~`, `` `code` ``
|
|
306
176
|
|
|
307
|
-
|
|
177
|
+
**Headings:** `# H1` through `###### H6`
|
|
308
178
|
|
|
309
|
-
|
|
179
|
+
**Lists:**
|
|
310
180
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
181
|
+
- Unordered lists
|
|
182
|
+
1. Ordered lists
|
|
183
|
+
- [x] Task lists
|
|
314
184
|
|
|
315
|
-
|
|
316
|
-
const quikdown_bd = require('quikdown/bd');
|
|
185
|
+
**Links:** `[text](url)` and automatic URL detection
|
|
317
186
|
|
|
318
|
-
|
|
319
|
-
<script src="https://unpkg.com/quikdown/dist/quikdown_bd.umd.min.js"></script>
|
|
320
|
-
<script>
|
|
321
|
-
// Available as window.quikdown_bd
|
|
322
|
-
const html = quikdown_bd(markdown);
|
|
323
|
-
</script>
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
### Basic Usage
|
|
187
|
+
**Code blocks:**
|
|
327
188
|
|
|
328
189
|
```javascript
|
|
329
|
-
|
|
330
|
-
import quikdown_bd from 'quikdown/bd';
|
|
331
|
-
|
|
332
|
-
// Markdown to HTML with source tracking
|
|
333
|
-
const html = quikdown_bd('**Hello** world', { bidirectional: true });
|
|
334
|
-
console.log(html);
|
|
335
|
-
// <strong data-qd="**">Hello</strong> world
|
|
336
|
-
|
|
337
|
-
// HTML back to Markdown (only available in quikdown_bd)
|
|
338
|
-
const markdown = quikdown_bd.toMarkdown(html);
|
|
339
|
-
console.log(markdown);
|
|
340
|
-
// **Hello** world
|
|
341
|
-
|
|
342
|
-
// Note: Regular quikdown does NOT have toMarkdown method
|
|
343
|
-
// This will fail: quikdown.toMarkdown(html) // ❌ Error
|
|
190
|
+
console.log('syntax highlighting support via plugins');
|
|
344
191
|
```
|
|
345
192
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
- **Live Editors**: Build WYSIWYG markdown editors where users can edit in either view
|
|
349
|
-
- **Content Migration**: Convert existing HTML content to Markdown
|
|
350
|
-
- **Round-trip Preservation**: Maintain markdown source formatting through HTML conversion
|
|
351
|
-
- **Collaborative Editing**: Enable rich-text editing while storing content as Markdown
|
|
352
|
-
|
|
353
|
-
### Browser Example
|
|
354
|
-
|
|
355
|
-
```html
|
|
356
|
-
<div id="editor" contenteditable="true"></div>
|
|
357
|
-
<script type="module">
|
|
358
|
-
import quikdown_bd from 'https://unpkg.com/quikdown/dist/quikdown_bd.esm.min.js';
|
|
359
|
-
|
|
360
|
-
const editor = document.getElementById('editor');
|
|
361
|
-
const markdown = '# Edit me\n\n**Bold** and *italic*';
|
|
362
|
-
|
|
363
|
-
// Convert to HTML and display
|
|
364
|
-
editor.innerHTML = quikdown_bd(markdown, { bidirectional: true });
|
|
365
|
-
|
|
366
|
-
// Convert back to Markdown when needed
|
|
367
|
-
editor.addEventListener('blur', () => {
|
|
368
|
-
const updatedMarkdown = quikdown_bd.toMarkdown(editor);
|
|
369
|
-
console.log('Updated markdown:', updatedMarkdown);
|
|
370
|
-
});
|
|
371
|
-
</script>
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
For complete documentation, see [Bidirectional Documentation](docs/quikdown-bidirectional.md).
|
|
375
|
-
|
|
376
|
-
## Quikdown Lexer Version
|
|
377
|
-
|
|
378
|
-
An experimental lexer-based implementation is available for testing. See [docs/lexer-implementation.md](docs/lexer-implementation.md) for details.
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
## Framework Integration
|
|
382
|
-
|
|
383
|
-
quikdown integrates seamlessly with modern JavaScript frameworks:
|
|
384
|
-
|
|
385
|
-
- **React** - Hooks, components, and Next.js support
|
|
386
|
-
- **Vue** - Composition API, Options API, and Nuxt support
|
|
387
|
-
- **Svelte** - Reactive statements and stores
|
|
388
|
-
- **Angular** - Components, services, and pipes
|
|
389
|
-
|
|
390
|
-
See the [Framework Integration Guide](docs/framework-integration.md) for detailed examples and best practices.
|
|
193
|
+
**Tables, blockquotes, horizontal rules** - See [documentation](docs/) for complete syntax reference
|
|
391
194
|
|
|
392
195
|
## API Reference
|
|
393
196
|
|
|
394
197
|
For complete API documentation, see [docs/api-reference.md](docs/api-reference.md)
|
|
395
198
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
#### `quikdown(markdown, options?)`
|
|
399
|
-
|
|
400
|
-
Main function to convert markdown to HTML.
|
|
401
|
-
|
|
402
|
-
**Parameters:**
|
|
403
|
-
- `markdown` (string): The markdown text to convert
|
|
404
|
-
- `options` (object, optional):
|
|
405
|
-
- `inline_styles` (boolean): Use inline styles instead of classes
|
|
406
|
-
- `fence_plugin` (function): Custom fence block handler
|
|
407
|
-
|
|
408
|
-
**Returns:** HTML string
|
|
409
|
-
|
|
410
|
-
#### `quikdown.configure(options)`
|
|
411
|
-
|
|
412
|
-
Creates a configured instance of the parser.
|
|
413
|
-
|
|
414
|
-
```javascript
|
|
415
|
-
const myParser = quikdown.configure({
|
|
416
|
-
inline_styles: true,
|
|
417
|
-
fence_plugin: myPlugin
|
|
418
|
-
});
|
|
419
|
-
|
|
420
|
-
// Use the configured parser
|
|
421
|
-
const html = myParser(markdown);
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
#### `quikdown.emitStyles(prefix?, theme?)`
|
|
425
|
-
|
|
426
|
-
Returns CSS styles for quikdown HTML output when not using inline styles.
|
|
427
|
-
|
|
428
|
-
```javascript
|
|
429
|
-
// Get light theme CSS
|
|
430
|
-
const lightStyles = quikdown.emitStyles();
|
|
431
|
-
|
|
432
|
-
// Get dark theme CSS
|
|
433
|
-
const darkStyles = quikdown.emitStyles('quikdown-', 'dark');
|
|
434
|
-
```
|
|
435
|
-
|
|
436
|
-
### Bidirectional API
|
|
437
|
-
|
|
438
|
-
**⚠️ These methods are only available in `quikdown_bd`, not in regular `quikdown`:**
|
|
439
|
-
|
|
440
|
-
#### `quikdown_bd(markdown, options?)`
|
|
441
|
-
|
|
442
|
-
Converts markdown to HTML with source tracking for bidirectional conversion.
|
|
443
|
-
|
|
444
|
-
#### `quikdown_bd.toMarkdown(htmlOrElement)`
|
|
445
|
-
|
|
446
|
-
Converts HTML back to Markdown. **This method only exists in `quikdown_bd`.**
|
|
447
|
-
|
|
448
|
-
**Parameters:**
|
|
449
|
-
- `htmlOrElement` (string | HTMLElement): HTML string or DOM element
|
|
450
|
-
|
|
451
|
-
**Returns:** Markdown string
|
|
452
|
-
|
|
453
|
-
```javascript
|
|
454
|
-
// ✅ Correct - using quikdown_bd
|
|
455
|
-
import quikdown_bd from 'quikdown/bd';
|
|
456
|
-
const markdown = quikdown_bd.toMarkdown(html);
|
|
457
|
-
|
|
458
|
-
// ❌ Wrong - regular quikdown doesn't have toMarkdown
|
|
459
|
-
import quikdown from 'quikdown';
|
|
460
|
-
const markdown = quikdown.toMarkdown(html); // Error: toMarkdown is not a function
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
See [API Reference](docs/api-reference.md) for complete documentation.
|
|
464
|
-
|
|
465
|
-
## Theming
|
|
466
|
-
|
|
467
|
-
QuikDown supports flexible theming through container-based CSS scoping:
|
|
468
|
-
|
|
469
|
-
### Using Pre-built Themes
|
|
470
|
-
|
|
471
|
-
```html
|
|
472
|
-
<!-- Load theme CSS files -->
|
|
473
|
-
<link rel="stylesheet" href="quikdown.light.css">
|
|
474
|
-
<link rel="stylesheet" href="quikdown.dark.css">
|
|
475
|
-
|
|
476
|
-
<!-- Apply themes via container classes -->
|
|
477
|
-
<div class="quikdown-light">
|
|
478
|
-
<!-- Light themed content -->
|
|
479
|
-
</div>
|
|
480
|
-
|
|
481
|
-
<div class="quikdown-dark">
|
|
482
|
-
<!-- Dark themed content -->
|
|
483
|
-
</div>
|
|
484
|
-
```
|
|
485
|
-
|
|
486
|
-
### Theme Architecture
|
|
487
|
-
|
|
488
|
-
- **Structural styles**: Shared across all themes (margins, padding, font-sizes)
|
|
489
|
-
- **Theme colors**: Scoped to container classes (`.quikdown-light`, `.quikdown-dark`)
|
|
490
|
-
- **No conflicts**: Multiple themes can coexist on the same page
|
|
491
|
-
- **No default theme**: Without a container class, only structural styles apply
|
|
492
|
-
|
|
493
|
-
### Inline Styles
|
|
494
|
-
|
|
495
|
-
For a batteries-included approach without CSS files:
|
|
496
|
-
|
|
497
|
-
```javascript
|
|
498
|
-
// Use inline styles (always light theme currently)
|
|
499
|
-
const html = quikdown(markdown, { inline_styles: true });
|
|
500
|
-
```
|
|
501
|
-
|
|
502
|
-
## Browser Usage
|
|
503
|
-
|
|
504
|
-
### ES Modules (Recommended)
|
|
505
|
-
|
|
506
|
-
```html
|
|
507
|
-
<!DOCTYPE html>
|
|
508
|
-
<html>
|
|
509
|
-
<head>
|
|
510
|
-
<meta charset="UTF-8">
|
|
511
|
-
</head>
|
|
512
|
-
<body>
|
|
513
|
-
<div id="output"></div>
|
|
514
|
-
<script type="module">
|
|
515
|
-
import quikdown from 'https://unpkg.com/quikdown/dist/quikdown.esm.min.js';
|
|
516
|
-
|
|
517
|
-
const markdown = '# Hello quikdown!\n\nSupports **bold** and *italic* text.';
|
|
518
|
-
const html = quikdown(markdown, { inline_styles: true });
|
|
519
|
-
document.getElementById('output').innerHTML = html;
|
|
520
|
-
</script>
|
|
521
|
-
</body>
|
|
522
|
-
</html>
|
|
523
|
-
```
|
|
524
|
-
|
|
525
|
-
### UMD Script Tag (Legacy)
|
|
526
|
-
|
|
527
|
-
```html
|
|
528
|
-
<!DOCTYPE html>
|
|
529
|
-
<html>
|
|
530
|
-
<head>
|
|
531
|
-
<script src="https://unpkg.com/quikdown/dist/quikdown.umd.min.js"></script>
|
|
532
|
-
</head>
|
|
533
|
-
<body>
|
|
534
|
-
<div id="output"></div>
|
|
535
|
-
<script>
|
|
536
|
-
const markdown = '# Hello quikdown!';
|
|
537
|
-
const html = quikdown(markdown, { inline_styles: true });
|
|
538
|
-
document.getElementById('output').innerHTML = html;
|
|
539
|
-
</script>
|
|
540
|
-
</body>
|
|
541
|
-
</html>
|
|
542
|
-
```
|
|
199
|
+
## Security
|
|
543
200
|
|
|
544
|
-
|
|
201
|
+
All HTML is escaped by default. Only safe markdown constructs become HTML:
|
|
545
202
|
|
|
546
203
|
```javascript
|
|
547
|
-
const
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
const html = quikdown(markdown);
|
|
551
|
-
|
|
552
|
-
// Use in Express, etc.
|
|
553
|
-
res.send(html);
|
|
204
|
+
const unsafe = '<script>alert("XSS")</script> **bold**';
|
|
205
|
+
const safe = quikdown(unsafe);
|
|
206
|
+
// <script>alert("XSS")</script> <strong>bold</strong>
|
|
554
207
|
```
|
|
555
208
|
|
|
556
|
-
##
|
|
557
|
-
|
|
558
|
-
quikdown is optimized for speed:
|
|
559
|
-
|
|
560
|
-
- Single-pass regex parsing
|
|
561
|
-
- Minimal memory allocation
|
|
562
|
-
- No AST generation
|
|
563
|
-
- Efficient string operations
|
|
209
|
+
## Framework Integration
|
|
564
210
|
|
|
565
|
-
|
|
211
|
+
Works with React, Vue, Svelte, Angular. See [Framework Integration Guide](docs/framework-integration.md) for examples.
|
|
566
212
|
|
|
567
213
|
## Limitations
|
|
568
214
|
|
|
569
|
-
quikdown
|
|
570
|
-
|
|
571
|
-
- HTML blocks (for security)
|
|
572
|
-
- Reference-style links
|
|
215
|
+
For size and security, quikdown doesn't support:
|
|
216
|
+
- Reference-style links
|
|
573
217
|
- Footnotes
|
|
574
218
|
- Definition lists
|
|
575
|
-
- Complex table alignment
|
|
576
|
-
- Nested blockquotes with different markers
|
|
577
|
-
|
|
578
|
-
These omissions keep the parser small, fast, and secure.
|
|
579
219
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
1. Fork the repository
|
|
585
|
-
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
|
|
586
|
-
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
|
|
587
|
-
4. Push to the branch (`git push origin feature/AmazingFeature`)
|
|
588
|
-
5. Open a Pull Request
|
|
589
|
-
|
|
590
|
-
## Testing
|
|
591
|
-
|
|
592
|
-
```bash
|
|
593
|
-
# Run tests
|
|
594
|
-
npm test
|
|
595
|
-
|
|
596
|
-
# Watch mode
|
|
597
|
-
npm run test:watch
|
|
598
|
-
|
|
599
|
-
# Coverage report
|
|
600
|
-
npm run test:coverage
|
|
220
|
+
Note that raw html, svg, etc can be rendered using appropriate fences
|
|
221
|
+
```html
|
|
222
|
+
<h1>My HTML Content</h1>
|
|
223
|
+
<p>Some HTML</p>
|
|
601
224
|
```
|
|
225
|
+
as long as an appropriate fence plugin is provided. See API docs for example or try out in quikdown_edit.js which has built-in support for HTML with XSS prevention.
|
|
602
226
|
|
|
603
227
|
## License
|
|
604
228
|
|
|
605
|
-
BSD 2-Clause
|
|
229
|
+
BSD 2-Clause - see [LICENSE.txt](LICENSE.txt)
|
|
606
230
|
|
|
607
231
|
## Acknowledgments
|
|
608
232
|
|
|
@@ -611,14 +235,9 @@ BSD 2-Clause License - see [LICENSE.txt](LICENSE.txt) file for details.
|
|
|
611
235
|
- CommonMark spec for markdown standardization
|
|
612
236
|
|
|
613
237
|
|
|
614
|
-
Choose quikdown when you need:
|
|
615
|
-
- A lightweight solution
|
|
616
|
-
- Built-in security
|
|
617
|
-
- Simple plugin system
|
|
618
|
-
- Zero dependencies
|
|
619
|
-
|
|
620
|
-
|
|
621
238
|
## Support
|
|
622
239
|
|
|
623
|
-
-
|
|
240
|
+
- 📖 [Documentation](docs/)
|
|
241
|
+
- 🐛 [Issues](https://github.com/deftio/quikdown/issues)
|
|
242
|
+
- 📦 [Examples](examples/)
|
|
624
243
|
|