quikdown 1.0.3 → 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 CHANGED
@@ -4,459 +4,229 @@
4
4
  [![npm version](https://img.shields.io/npm/v/quikdown.svg)](https://www.npmjs.com/package/quikdown)
5
5
  [![Coverage Status](https://img.shields.io/badge/coverage-99%25-blue.svg)](https://github.com/deftio/quikdown)
6
6
  [![License: BSD-2-Clause](https://img.shields.io/badge/License-BSD%202--Clause-blue.svg)](https://opensource.org/licenses/BSD-2-Clause)
7
- [![Bundle Size](https://img.shields.io/badge/minified-<10KB-blue.svg)](https://github.com/deftio/quikdown/tree/main/dist)
8
7
 
9
- A lightweight, fast markdown parser with built-in XSS protection. Quikdown works in both browser and Node.js environments. Via its fenced plug-in support it can support highlighted code blocks, diagrams, and other custom fenced content.
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.
10
9
 
11
- 🚀 **[Try Live Demo](https://deftio.github.io/quikdown/examples/quikdown-live.html)** - Interactive markdown editor with real-time preview
12
- 📚 **[View Examples](examples/)** - Additional demos and test pages
13
- 📖 **[Read Documentation](docs/)** - Architecture, security, API reference, and plugin guide
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/)
14
19
 
15
20
  ## Features
16
21
 
17
- - 🚀 **Lightweight** - Under 10KB minified
18
- - 🔒 **Secure by default** - Built-in XSS protection with URL sanitization
19
- - 🎨 **Flexible styling** - Inline styles or CSS classes including light and dark mode generation, custom themes
20
- - 🔌 **Plugin system** - Extensible fence block handlers
21
22
  - 📦 **Zero dependencies** - No external libraries required
22
23
  - 🌐 **Universal** - Works in browsers and Node.js
24
+ - 🚀 **Lightweight** - 8.7KB (core), 13KB (bidirectional), 36KB (editor)
25
+ - 🔒 **Secure by default** - Built-in XSS protection with URL sanitization
26
+ - 🎨 **Flexible styling** - Inline styles or CSS classes with theme support
27
+ - 🔌 **Plugin system** - Extensible fence block handlers
23
28
  - ⚡ **Fast** - Optimized regex-based parsing
24
- - 📝 **CommonMark subset** - Supports essential markdown features
29
+ - 📝 **CommonMark subset** - Essential markdown features
25
30
  - ✅ **Task Lists** - GitHub-style checkboxes
26
31
  - 🔗 **Autolinks** - Automatic URL detection
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
27
35
 
28
36
  ## Installation
29
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
30
41
  ```bash
31
42
  npm install quikdown
32
43
  ```
33
44
 
34
- Or via CDN:
45
+ ### CDN using UNPKG
35
46
 
36
- **ES Modules (recommended for modern applications):**
47
+ **CDN (ES Modules):**
37
48
  ```html
38
49
  <script type="module">
39
50
  import quikdown from 'https://unpkg.com/quikdown/dist/quikdown.esm.min.js';
40
-
41
- const html = quikdown('# Hello World');
42
- document.body.innerHTML = html;
51
+ document.body.innerHTML = quikdown('# Hello World');
43
52
  </script>
44
53
  ```
45
54
 
46
- **UMD (for legacy browser support):**
55
+ **CDN (UMD):**
47
56
  ```html
48
57
  <script src="https://unpkg.com/quikdown/dist/quikdown.umd.min.js"></script>
49
58
  <script>
50
- // Available as window.quikdown
51
- const html = quikdown('# Hello World');
59
+ document.body.innerHTML = quikdown('# Hello World');
52
60
  </script>
53
61
  ```
54
62
 
55
- > **Production tip:** Pin to a specific version for stability (e.g., `https://unpkg.com/quikdown@1.0.3/dist/quikdown.esm.min.js`)
56
-
57
63
  ## Quick Start
58
64
 
59
- ### Basic Usage
60
-
61
- ```javascript
62
- import quikdown from 'quikdown';
63
-
64
- const markdown = '# Hello World\n\nThis is **bold** text.';
65
- const html = quikdown(markdown);
66
- console.log(html);
67
- // Output: <h1>Hello World</h1><p>This is <strong>bold</strong> text.</p>
68
- ```
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.
69
66
 
70
- ### With Options
67
+ ### Markdown → HTML (quikdown.js)
71
68
 
72
69
  ```javascript
73
- const html = quikdown(markdown, {
74
- inline_styles: true, // Use inline styles instead of classes
75
- fence_plugin: myFenceHandler // Custom code fence handler
76
- });
77
- ```
78
-
79
- ### TypeScript Support
80
-
81
- quikdown includes TypeScript definitions for better IDE support and type safety:
82
-
83
- ```typescript
84
- import quikdown, { QuikdownOptions } from 'quikdown';
85
-
86
- const options: QuikdownOptions = {
87
- inline_styles: true,
88
- fence_plugin: (content: string, language: string) => {
89
- return `<pre class="hljs ${language}">${content}</pre>`;
90
- }
91
- };
92
-
93
- const html: string = quikdown(markdown, options);
94
- ```
95
-
96
- ## Supported Markdown
97
-
98
- quikdown supports a practical subset of CommonMark:
99
-
100
- ### Text Formatting
101
- - **Bold**: `**text**` or `__text__`
102
- - *Italic*: `*text*` or `_text_`
103
- - ~~Strikethrough~~: `~~text~~`
104
- - `Code`: `` `code` ``
105
-
106
- ### Headings
107
- ```markdown
108
- # H1 Heading
109
- ## H2 Heading
110
- ### H3 Heading
111
- #### H4 Heading
112
- ##### H5 Heading
113
- ###### H6 Heading
114
- ```
115
-
116
- ### Lists
70
+ // Basic conversion
71
+ const html = quikdown('# Hello World',
72
+ {inline_styles: true} // Use inline styles, more options in API docs
73
+ );
117
74
 
118
- Unordered:
119
- ```markdown
120
- - Item 1
121
- - Item 2
122
- - Nested item
123
- * Also works with asterisks
124
- ```
125
-
126
- Ordered:
127
- ```markdown
128
- 1. First item
129
- 2. Second item
130
- 1. Nested item
131
- ```
75
+ document.body.innerHTML = html;
132
76
 
133
- Task Lists:
134
- ```markdown
135
- - [x] Completed task
136
- - [ ] Pending task
137
- - [ ] Another todo
138
77
  ```
139
78
 
140
- ### Links and Images
141
- ```markdown
142
- [Link text](https://example.com)
143
- ![Alt text](image.jpg)
144
-
145
- // Autolinks - URLs are automatically linked
146
- Visit https://github.com for more info
147
- ```
79
+ ### Bidirectional Markdown ↔ HTML (quikdown_bd.js)
148
80
 
149
- ### Code Blocks
150
- ````markdown
151
81
  ```javascript
152
- console.log('Hello, world!');
153
- ```
82
+ // Convert with source tracking
83
+ const htmlString = quikdown_bd(markdown, options);
154
84
 
155
- // Also supports ~~~ fences
156
- ~~~python
157
- print("Hello, world!")
158
- ~~~
159
- ````
160
-
161
- ### Tables
162
- ```markdown
163
- | Header 1 | Header 2 |
164
- |----------|----------|
165
- | Cell 1 | Cell 2 |
166
- | Cell 3 | Cell 4 |
85
+ // Convert HTML back to Markdown
86
+ const markdown = quikdown_bd.toMarkdown(htmlString);
167
87
  ```
168
88
 
169
- ### Other Elements
170
- - **Blockquotes**: `> Quote text`
171
- - **Horizontal rules**: `---` or `***` or `___`
172
- - **Line breaks**: Two spaces at end of line or `<br>`
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.
173
90
 
174
- ## Configuration Options
175
-
176
- ### `inline_styles` (boolean)
177
- When `true`, uses inline styles for formatting. When `false`, uses CSS classes.
91
+ ### Editor (quikdown_edit.js)
178
92
 
179
93
  ```javascript
180
- // With inline_styles: true
181
- quikdown('**bold**', { inline_styles: true });
182
- // Output: <strong style="font-weight: bold;">bold</strong>
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
+ });
183
99
 
184
- // With inline_styles: false (default)
185
- quikdown('**bold**', { inline_styles: false });
186
- // Output: <strong>bold</strong>
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
187
102
  ```
188
103
 
189
- ### `fence_plugin` (function)
190
- Custom handler for fenced code blocks. Useful for syntax highlighting or diagrams.
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.
191
106
 
192
107
  ```javascript
193
- function fencePlugin(code, language) {
194
- if (language === 'mermaid') {
195
- return `<div class="mermaid">${code}</div>`;
196
- }
197
- // Return undefined to use default handling
198
- }
199
-
200
- const html = quikdown(markdown, { fence_plugin: fencePlugin });
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
+ });
201
113
  ```
202
114
 
203
- ## Plugin System
204
-
205
- For a complete plugin development guide, see [docs/plugin-guide.md](docs/plugin-guide.md)
206
-
207
- ### Creating a Fence Plugin
208
-
209
- Fence plugins allow you to customize how code blocks are rendered:
115
+ ### Styling Options
210
116
 
117
+ **Inline styles:** All formatting uses inline CSS
211
118
  ```javascript
212
- function myFencePlugin(code, language) {
213
- // Handle specific languages
214
- if (language === 'graph') {
215
- return renderGraph(code);
216
- }
217
-
218
- // Add syntax highlighting
219
- if (language && hljs.getLanguage(language)) {
220
- const highlighted = hljs.highlight(code, { language }).value;
221
- return `<pre><code class="language-${language}">${highlighted}</code></pre>`;
222
- }
223
-
224
- // Return undefined for default handling
225
- return undefined;
226
- }
119
+ quikdown('**bold**', { inline_styles: true });
120
+ // <strong style="font-weight: bold;">bold</strong>
227
121
  ```
228
122
 
229
- ### Example: Mermaid Diagrams
230
-
123
+ **Class-based styling:** Uses CSS classes (default)
231
124
  ```javascript
232
- function mermaidPlugin(code, language) {
233
- if (language === 'mermaid') {
234
- const id = 'mermaid-' + Math.random().toString(36).substr(2, 9);
235
- // Render with mermaid.js after DOM update
236
- setTimeout(() => {
237
- mermaid.render(id + '-svg', code).then(result => {
238
- document.getElementById(id).innerHTML = result.svg;
239
- });
240
- }, 0);
241
- return `<div id="${id}" class="mermaid">Loading diagram...</div>`;
242
- }
243
- }
244
-
245
- const html = quikdown(markdownWithMermaid, {
246
- fence_plugin: mermaidPlugin
247
- });
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
248
129
  ```
249
130
 
250
- ## Security
251
-
252
- For detailed security information, see [docs/security.md](docs/security.md)
131
+ ### Fence Plugins
253
132
 
254
- quikdown includes built-in XSS protection:
133
+ Quikdown provides a callback for all fenced text such as code blocks, math, svg etc.
255
134
 
256
- - All HTML tags in markdown are escaped by default
257
- - Attributes are sanitized
258
- - JavaScript URLs are blocked
259
- - Only safe markdown constructs are converted to HTML
135
+ Handle code blocks with custom languages:
260
136
 
261
137
  ```javascript
262
- const unsafe = '<script>alert("XSS")</script> **bold**';
263
- const safe = quikdown(unsafe);
264
- // Output: &lt;script&gt;alert("XSS")&lt;/script&gt; <strong>bold</strong>
265
- ```
266
-
267
- ## Quikdown Lexer Version
268
- An experimental lexer-based implementation is available for testing. See [docs/lexer-implementation.md](docs/lexer-implementation.md) for details.
269
-
270
-
271
- ## API Reference
272
-
273
- For complete API documentation, see [docs/api-reference.md](docs/api-reference.md)
274
-
275
- ### `quikdown(markdown, options?)`
138
+ function fencePlugin(code, language) {
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
149
+ }
276
150
 
277
- Main function to convert markdown to HTML.
151
+ const html = quikdown(markdown, { fence_plugin: fencePlugin });
152
+ ```
278
153
 
279
- **Parameters:**
280
- - `markdown` (string): The markdown text to convert
281
- - `options` (object, optional):
282
- - `inline_styles` (boolean): Use inline styles instead of classes
283
- - `fence_plugin` (function): Custom fence block handler
284
154
 
285
- **Returns:** HTML string
155
+ ## TypeScript Support
286
156
 
287
- ### `quikdown.configure(options)`
157
+ quikdown includes TypeScript definitions for better IDE support and type safety:
288
158
 
289
- Creates a configured instance of the parser.
159
+ ``` javascript
160
+ import quikdown, { QuikdownOptions } from 'quikdown';
290
161
 
291
- ```javascript
292
- const myParser = quikdown.configure({
162
+ const options: QuikdownOptions = {
293
163
  inline_styles: true,
294
- fence_plugin: myPlugin
295
- });
296
-
297
- // Use the configured parser
298
- const html = myParser(markdown);
299
- ```
300
-
301
- ### `quikdown.emitStyles(prefix?, theme?)`
302
-
303
- Returns CSS styles for quikdown HTML output when not using inline styles.
304
-
305
- **Parameters:**
306
- - `prefix` (string, optional): CSS class prefix (default: 'quikdown-')
307
- - `theme` (string, optional): Theme name - 'light' or 'dark' (default: 'light')
308
-
309
- ```javascript
310
- // Get light theme CSS
311
- const lightStyles = quikdown.emitStyles();
164
+ fence_plugin: (content: string, language: string) => {
165
+ return `<pre class="hljs ${language}">${content}</pre>`;
166
+ }
167
+ };
312
168
 
313
- // Get dark theme CSS
314
- const darkStyles = quikdown.emitStyles('quikdown-', 'dark');
169
+ const html: string = quikdown(markdown, options);
315
170
 
316
- // Add to your stylesheet or <style> tag
317
171
  ```
318
172
 
319
- ## Theming
320
-
321
- QuikDown supports flexible theming through container-based CSS scoping:
173
+ ## Supported Markdown
322
174
 
323
- ### Using Pre-built Themes
175
+ **Text formatting:** `**bold**`, `*italic*`, `~~strikethrough~~`, `` `code` ``
324
176
 
325
- ```html
326
- <!-- Load theme CSS files -->
327
- <link rel="stylesheet" href="quikdown.light.css">
328
- <link rel="stylesheet" href="quikdown.dark.css">
329
-
330
- <!-- Apply themes via container classes -->
331
- <div class="quikdown-light">
332
- <!-- Light themed content -->
333
- </div>
334
-
335
- <div class="quikdown-dark">
336
- <!-- Dark themed content -->
337
- </div>
338
- ```
177
+ **Headings:** `# H1` through `###### H6`
339
178
 
340
- ### Theme Architecture
179
+ **Lists:**
341
180
 
342
- - **Structural styles**: Shared across all themes (margins, padding, font-sizes)
343
- - **Theme colors**: Scoped to container classes (`.quikdown-light`, `.quikdown-dark`)
344
- - **No conflicts**: Multiple themes can coexist on the same page
345
- - **No default theme**: Without a container class, only structural styles apply
181
+ - Unordered lists
182
+ 1. Ordered lists
183
+ - [x] Task lists
346
184
 
347
- ### Inline Styles
185
+ **Links:** `[text](url)` and automatic URL detection
348
186
 
349
- For a batteries-included approach without CSS files:
187
+ **Code blocks:**
350
188
 
351
189
  ```javascript
352
- // Use inline styles (always light theme currently)
353
- const html = quikdown(markdown, { inline_styles: true });
190
+ console.log('syntax highlighting support via plugins');
354
191
  ```
355
192
 
356
- ## Browser Usage
357
-
358
- ### ES Modules (Recommended)
193
+ **Tables, blockquotes, horizontal rules** - See [documentation](docs/) for complete syntax reference
359
194
 
360
- ```html
361
- <!DOCTYPE html>
362
- <html>
363
- <head>
364
- <meta charset="UTF-8">
365
- </head>
366
- <body>
367
- <div id="output"></div>
368
- <script type="module">
369
- import quikdown from 'https://unpkg.com/quikdown/dist/quikdown.esm.min.js';
370
-
371
- const markdown = '# Hello quikdown!\n\nSupports **bold** and *italic* text.';
372
- const html = quikdown(markdown, { inline_styles: true });
373
- document.getElementById('output').innerHTML = html;
374
- </script>
375
- </body>
376
- </html>
377
- ```
195
+ ## API Reference
378
196
 
379
- ### UMD Script Tag (Legacy)
197
+ For complete API documentation, see [docs/api-reference.md](docs/api-reference.md)
380
198
 
381
- ```html
382
- <!DOCTYPE html>
383
- <html>
384
- <head>
385
- <script src="https://unpkg.com/quikdown/dist/quikdown.umd.min.js"></script>
386
- </head>
387
- <body>
388
- <div id="output"></div>
389
- <script>
390
- const markdown = '# Hello quikdown!';
391
- const html = quikdown(markdown, { inline_styles: true });
392
- document.getElementById('output').innerHTML = html;
393
- </script>
394
- </body>
395
- </html>
396
- ```
199
+ ## Security
397
200
 
398
- ## Node.js Usage
201
+ All HTML is escaped by default. Only safe markdown constructs become HTML:
399
202
 
400
203
  ```javascript
401
- const quikdown = require('quikdown');
402
-
403
- const markdown = '# Server-side Markdown';
404
- const html = quikdown(markdown);
405
-
406
- // Use in Express, etc.
407
- res.send(html);
204
+ const unsafe = '<script>alert("XSS")</script> **bold**';
205
+ const safe = quikdown(unsafe);
206
+ // &lt;script&gt;alert("XSS")&lt;/script&gt; <strong>bold</strong>
408
207
  ```
409
208
 
410
- ## Performance
411
-
412
- quikdown is optimized for speed:
209
+ ## Framework Integration
413
210
 
414
- - Single-pass regex parsing
415
- - Minimal memory allocation
416
- - No AST generation
417
- - Efficient string operations
418
-
419
- Benchmarks show quikdown performs comparably to larger markdown parsers while maintaining a much smaller footprint.
211
+ Works with React, Vue, Svelte, Angular. See [Framework Integration Guide](docs/framework-integration.md) for examples.
420
212
 
421
213
  ## Limitations
422
214
 
423
- quikdown intentionally doesn't support:
424
-
425
- - HTML blocks (for security)
426
- - Reference-style links
215
+ For size and security, quikdown doesn't support:
216
+ - Reference-style links
427
217
  - Footnotes
428
218
  - Definition lists
429
- - Complex table alignment
430
- - Nested blockquotes with different markers
431
-
432
- These omissions keep the parser small, fast, and secure.
433
-
434
- ## Contributing
435
-
436
- Contributions are welcome! Please feel free to submit a Pull Request.
437
-
438
- 1. Fork the repository
439
- 2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
440
- 3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
441
- 4. Push to the branch (`git push origin feature/AmazingFeature`)
442
- 5. Open a Pull Request
443
219
 
444
- ## Testing
445
-
446
- ```bash
447
- # Run tests
448
- npm test
449
-
450
- # Watch mode
451
- npm run test:watch
452
-
453
- # Coverage report
454
- 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>
455
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.
456
226
 
457
227
  ## License
458
228
 
459
- BSD 2-Clause License - see [LICENSE.txt](LICENSE.txt) file for details.
229
+ BSD 2-Clause - see [LICENSE.txt](LICENSE.txt)
460
230
 
461
231
  ## Acknowledgments
462
232
 
@@ -465,14 +235,9 @@ BSD 2-Clause License - see [LICENSE.txt](LICENSE.txt) file for details.
465
235
  - CommonMark spec for markdown standardization
466
236
 
467
237
 
468
- Choose quikdown when you need:
469
- - A lightweight solution
470
- - Built-in security
471
- - Simple plugin system
472
- - Zero dependencies
473
-
474
-
475
238
  ## Support
476
239
 
477
- - 🐛 Issues: [GitHub Issues](https://github.com/deftio/quikdown/issues)
240
+ - 📖 [Documentation](docs/)
241
+ - 🐛 [Issues](https://github.com/deftio/quikdown/issues)
242
+ - 📦 [Examples](examples/)
478
243