quikdown 1.0.2 → 1.0.3

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.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * quikdown - Lightweight Markdown Parser
3
- * @version 1.0.2
3
+ * @version 1.0.3
4
4
  * @license BSD-2-Clause
5
5
  * @copyright DeftIO 2025
6
6
  */
@@ -10,11 +10,6 @@
10
10
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.quikdown = factory());
11
11
  })(this, (function () { 'use strict';
12
12
 
13
- // Auto-generated version file - DO NOT EDIT MANUALLY
14
- // This file is automatically updated by tools/updateVersion.js
15
-
16
- const quikdownVersion = "1.0.2";
17
-
18
13
  /**
19
14
  * quikdown - A minimal markdown parser optimized for chat/LLM output
20
15
  * Supports tables, code blocks, lists, and common formatting
@@ -26,64 +21,71 @@
26
21
  * @returns {string} - The rendered HTML
27
22
  */
28
23
 
24
+ // Version will be injected at build time
25
+ const quikdownVersion = '1.0.3';
29
26
 
30
- function quikdown(markdown, options = {}) {
31
- if (!markdown || typeof markdown !== 'string') {
32
- return '';
33
- }
34
-
35
- const { fence_plugin, inline_styles = false } = options;
27
+ // Constants for reuse
28
+ const CLASS_PREFIX = 'quikdown-';
29
+ const PLACEHOLDER_CB = '§CB';
30
+ const PLACEHOLDER_IC = '§IC';
36
31
 
37
- // Style definitions - minimal, matching emitStyles
38
- const styles = {
39
- h1: 'font-size: 2em; font-weight: 600; margin: 0.67em 0; text-align: left',
40
- h2: 'font-size: 1.5em; font-weight: 600; margin: 0.83em 0',
41
- h3: 'font-size: 1.25em; font-weight: 600; margin: 1em 0',
42
- h4: 'font-size: 1em; font-weight: 600; margin: 1.33em 0',
43
- h5: 'font-size: 0.875em; font-weight: 600; margin: 1.67em 0',
44
- h6: 'font-size: 0.85em; font-weight: 600; margin: 2em 0',
45
- pre: 'background: #f4f4f4; padding: 10px; border-radius: 4px; overflow-x: auto; margin: 1em 0',
46
- code: 'background: #f0f0f0; padding: 2px 4px; border-radius: 3px; font-family: monospace',
47
- blockquote: 'border-left: 4px solid #ddd; margin-left: 0; padding-left: 1em',
48
- table: 'border-collapse: collapse; width: 100%; margin: 1em 0',
49
- thead: '',
50
- tbody: '',
51
- tr: '',
52
- th: 'border: 1px solid #ddd; padding: 8px; background-color: #f2f2f2; font-weight: bold; text-align: left',
53
- td: 'border: 1px solid #ddd; padding: 8px; text-align: left',
54
- hr: 'border: none; border-top: 1px solid #ddd; margin: 1em 0',
55
- img: 'max-width: 100%; height: auto',
56
- a: 'color: #0066cc; text-decoration: underline',
57
- strong: 'font-weight: bold',
58
- em: 'font-style: italic',
59
- del: 'text-decoration: line-through',
60
- ul: 'margin: 0.5em 0; padding-left: 2em',
61
- ol: 'margin: 0.5em 0; padding-left: 2em',
62
- li: 'margin: 0.25em 0',
63
- br: ''
64
- };
32
+ // Escape map at module level
33
+ const ESC_MAP = {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'};
65
34
 
66
- // Helper to get class or style attribute
67
- function getAttr(tag, additionalStyle = '') {
35
+ // Single source of truth for all style definitions - optimized
36
+ const QUIKDOWN_STYLES = {
37
+ h1: 'font-size:2em;font-weight:600;margin:.67em 0;text-align:left',
38
+ h2: 'font-size:1.5em;font-weight:600;margin:.83em 0',
39
+ h3: 'font-size:1.25em;font-weight:600;margin:1em 0',
40
+ h4: 'font-size:1em;font-weight:600;margin:1.33em 0',
41
+ h5: 'font-size:.875em;font-weight:600;margin:1.67em 0',
42
+ h6: 'font-size:.85em;font-weight:600;margin:2em 0',
43
+ pre: 'background:#f4f4f4;padding:10px;border-radius:4px;overflow-x:auto;margin:1em 0',
44
+ code: 'background:#f0f0f0;padding:2px 4px;border-radius:3px;font-family:monospace',
45
+ blockquote: 'border-left:4px solid #ddd;margin-left:0;padding-left:1em',
46
+ table: 'border-collapse:collapse;width:100%;margin:1em 0',
47
+ th: 'border:1px solid #ddd;padding:8px;background-color:#f2f2f2;font-weight:bold;text-align:left',
48
+ td: 'border:1px solid #ddd;padding:8px;text-align:left',
49
+ hr: 'border:none;border-top:1px solid #ddd;margin:1em 0',
50
+ img: 'max-width:100%;height:auto',
51
+ a: 'color:#06c;text-decoration:underline',
52
+ strong: 'font-weight:bold',
53
+ em: 'font-style:italic',
54
+ del: 'text-decoration:line-through',
55
+ ul: 'margin:.5em 0;padding-left:2em',
56
+ ol: 'margin:.5em 0;padding-left:2em',
57
+ li: 'margin:.25em 0',
58
+ // Task list specific styles
59
+ 'task-item': 'list-style:none',
60
+ 'task-checkbox': 'margin-right:.5em'
61
+ };
62
+
63
+ // Factory function to create getAttr for a given context
64
+ function createGetAttr(inline_styles, styles) {
65
+ return function(tag, additionalStyle = '') {
68
66
  if (inline_styles) {
69
- const style = styles[tag] || '';
70
- const fullStyle = additionalStyle ? `${style}; ${additionalStyle}` : style;
71
- return fullStyle ? ` style="${fullStyle}"` : '';
67
+ const style = styles[tag];
68
+ if (!style && !additionalStyle) return '';
69
+ const fullStyle = additionalStyle ? (style ? `${style};${additionalStyle}` : additionalStyle) : style;
70
+ return ` style="${fullStyle}"`;
72
71
  } else {
73
- return ` class="quikdown-${tag}"`;
72
+ return ` class="${CLASS_PREFIX}${tag}"`;
74
73
  }
74
+ };
75
+ }
76
+
77
+ function quikdown(markdown, options = {}) {
78
+ if (!markdown || typeof markdown !== 'string') {
79
+ return '';
75
80
  }
81
+
82
+ const { fence_plugin, inline_styles = false } = options;
83
+ const styles = QUIKDOWN_STYLES; // Use module-level styles
84
+ const getAttr = createGetAttr(inline_styles, styles); // Create getAttr once
76
85
 
77
86
  // Escape HTML entities to prevent XSS
78
87
  function escapeHtml(text) {
79
- const map = {
80
- '&': '&amp;',
81
- '<': '&lt;',
82
- '>': '&gt;',
83
- '"': '&quot;',
84
- "'": '&#39;'
85
- };
86
- return text.replace(/[&<>"']/g, m => map[m]);
88
+ return text.replace(/[&<>"']/g, m => ESC_MAP[m]);
87
89
  }
88
90
 
89
91
  // Sanitize URLs to prevent XSS attacks
@@ -93,7 +95,6 @@
93
95
  // If unsafe URLs are explicitly allowed, return as-is
94
96
  if (allowUnsafe) return url;
95
97
 
96
- // Trim and lowercase for checking
97
98
  const trimmedUrl = url.trim();
98
99
  const lowerUrl = trimmedUrl.toLowerCase();
99
100
 
@@ -125,7 +126,7 @@
125
126
  // Match paired fences - ``` with ``` and ~~~ with ~~~
126
127
  // Fence must be at start of line
127
128
  html = html.replace(/^(```|~~~)([^\n]*)\n([\s\S]*?)^\1$/gm, (match, fence, lang, code) => {
128
- const placeholder = `%%%CODEBLOCK${codeBlocks.length}%%%`;
129
+ const placeholder = `${PLACEHOLDER_CB}${codeBlocks.length}§`;
129
130
 
130
131
  // Trim the language specification
131
132
  const langTrimmed = lang ? lang.trim() : '';
@@ -149,7 +150,7 @@
149
150
 
150
151
  // Extract inline code
151
152
  html = html.replace(/`([^`]+)`/g, (match, code) => {
152
- const placeholder = `%%%INLINECODE${inlineCodes.length}%%%`;
153
+ const placeholder = `${PLACEHOLDER_IC}${inlineCodes.length}§`;
153
154
  inlineCodes.push(escapeHtml(code));
154
155
  return placeholder;
155
156
  });
@@ -160,7 +161,7 @@
160
161
  // Phase 2: Process block elements
161
162
 
162
163
  // Process tables
163
- html = processTable(html, inline_styles, styles);
164
+ html = processTable(html, getAttr);
164
165
 
165
166
  // Process headings (supports optional trailing #'s)
166
167
  html = html.replace(/^(#{1,6})\s+(.+?)\s*#*$/gm, (match, hashes, content) => {
@@ -177,7 +178,7 @@
177
178
  html = html.replace(/^---+$/gm, `<hr${getAttr('hr')}>`);
178
179
 
179
180
  // Process lists
180
- html = processLists(html, inline_styles, styles);
181
+ html = processLists(html, getAttr, inline_styles);
181
182
 
182
183
  // Phase 3: Process inline elements
183
184
 
@@ -202,16 +203,18 @@
202
203
  return `${prefix}<a${getAttr('a')} href="${sanitizedUrl}" rel="noopener noreferrer">${url}</a>`;
203
204
  });
204
205
 
205
- // Bold (must use non-greedy matching)
206
- html = html.replace(/\*\*(.+?)\*\*/g, `<strong${getAttr('strong')}>$1</strong>`);
207
- html = html.replace(/__(.+?)__/g, `<strong${getAttr('strong')}>$1</strong>`);
208
-
209
- // Italic (must not match bold markers)
210
- html = html.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, `<em${getAttr('em')}>$1</em>`);
211
- html = html.replace(/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g, `<em${getAttr('em')}>$1</em>`);
212
-
213
- // Strikethrough
214
- html = html.replace(/~~(.+?)~~/g, `<del${getAttr('del')}>$1</del>`);
206
+ // Process inline formatting (bold, italic, strikethrough)
207
+ const inlinePatterns = [
208
+ [/\*\*(.+?)\*\*/g, 'strong'],
209
+ [/__(.+?)__/g, 'strong'],
210
+ [/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, 'em'],
211
+ [/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g, 'em'],
212
+ [/~~(.+?)~~/g, 'del']
213
+ ];
214
+
215
+ inlinePatterns.forEach(([pattern, tag]) => {
216
+ html = html.replace(pattern, `<${tag}${getAttr(tag)}>$1</${tag}>`);
217
+ });
215
218
 
216
219
  // Line breaks (two spaces at end of line)
217
220
  html = html.replace(/ $/gm, `<br${getAttr('br')}>`);
@@ -220,21 +223,26 @@
220
223
  html = html.replace(/\n\n+/g, '</p><p>');
221
224
  html = '<p>' + html + '</p>';
222
225
 
223
- // Clean up empty paragraphs and unwrap block elements (account for attributes)
224
- html = html.replace(/<p><\/p>/g, '');
225
- html = html.replace(/<p>(<h[1-6][^>]*>)/g, '$1');
226
- html = html.replace(/(<\/h[1-6]>)<\/p>/g, '$1');
227
- html = html.replace(/<p>(<blockquote[^>]*>)/g, '$1');
228
- html = html.replace(/(<\/blockquote>)<\/p>/g, '$1');
229
- html = html.replace(/<p>(<ul[^>]*>|<ol[^>]*>)/g, '$1');
230
- html = html.replace(/(<\/ul>|<\/ol>)<\/p>/g, '$1');
231
- html = html.replace(/<p>(<hr[^>]*>)<\/p>/g, '$1');
232
- html = html.replace(/<p>(<table[^>]*>)/g, '$1');
233
- html = html.replace(/(<\/table>)<\/p>/g, '$1');
234
- html = html.replace(/<p>(<pre[^>]*>)/g, '$1');
235
- html = html.replace(/(<\/pre>)<\/p>/g, '$1');
236
- // Also unwrap code block placeholders
237
- html = html.replace(/<p>(%%%CODEBLOCK\d+%%%)<\/p>/g, '$1');
226
+ // Clean up empty paragraphs and unwrap block elements
227
+ const cleanupPatterns = [
228
+ [/<p><\/p>/g, ''],
229
+ [/<p>(<h[1-6][^>]*>)/g, '$1'],
230
+ [/(<\/h[1-6]>)<\/p>/g, '$1'],
231
+ [/<p>(<blockquote[^>]*>)/g, '$1'],
232
+ [/(<\/blockquote>)<\/p>/g, '$1'],
233
+ [/<p>(<ul[^>]*>|<ol[^>]*>)/g, '$1'],
234
+ [/(<\/ul>|<\/ol>)<\/p>/g, '$1'],
235
+ [/<p>(<hr[^>]*>)<\/p>/g, '$1'],
236
+ [/<p>(<table[^>]*>)/g, '$1'],
237
+ [/(<\/table>)<\/p>/g, '$1'],
238
+ [/<p>(<pre[^>]*>)/g, '$1'],
239
+ [/(<\/pre>)<\/p>/g, '$1'],
240
+ [new RegExp(`<p>(${PLACEHOLDER_CB}\\d)<\/p>`, 'g'), '$1']
241
+ ];
242
+
243
+ cleanupPatterns.forEach(([pattern, replacement]) => {
244
+ html = html.replace(pattern, replacement);
245
+ });
238
246
 
239
247
  // Phase 4: Restore code blocks and inline code
240
248
 
@@ -258,13 +266,13 @@
258
266
  replacement = `<pre${getAttr('pre')}><code${codeAttr}>${block.code}</code></pre>`;
259
267
  }
260
268
 
261
- const placeholder = `%%%CODEBLOCK${i}%%%`;
269
+ const placeholder = `${PLACEHOLDER_CB}${i}§`;
262
270
  html = html.replace(placeholder, replacement);
263
271
  });
264
272
 
265
273
  // Restore inline code
266
274
  inlineCodes.forEach((code, i) => {
267
- const placeholder = `%%%INLINECODE${i}%%%`;
275
+ const placeholder = `${PLACEHOLDER_IC}${i}§`;
268
276
  html = html.replace(placeholder, `<code${getAttr('code')}>${code}</code>`);
269
277
  });
270
278
 
@@ -274,31 +282,21 @@
274
282
  /**
275
283
  * Process inline markdown formatting
276
284
  */
277
- function processInlineMarkdown(text, inline_styles, styles) {
278
- // Helper to get attributes
279
- function getAttr(tag, additionalStyle = '') {
280
- if (inline_styles) {
281
- const style = styles[tag] || '';
282
- const fullStyle = additionalStyle ? `${style}; ${additionalStyle}` : style;
283
- return fullStyle ? ` style="${fullStyle}"` : '';
284
- } else {
285
- return ` class="quikdown-${tag}"`;
286
- }
287
- }
288
-
289
- // Process bold
290
- text = text.replace(/\*\*(.+?)\*\*/g, `<strong${getAttr('strong')}>$1</strong>`);
291
- text = text.replace(/__(.+?)__/g, `<strong${getAttr('strong')}>$1</strong>`);
292
-
293
- // Process italic (must not match bold markers)
294
- text = text.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, `<em${getAttr('em')}>$1</em>`);
295
- text = text.replace(/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g, `<em${getAttr('em')}>$1</em>`);
296
-
297
- // Process strikethrough
298
- text = text.replace(/~~(.+?)~~/g, `<del${getAttr('del')}>$1</del>`);
299
-
300
- // Process inline code
301
- text = text.replace(/`([^`]+)`/g, `<code${getAttr('code')}>$1</code>`);
285
+ function processInlineMarkdown(text, getAttr) {
286
+
287
+ // Process inline formatting patterns
288
+ const patterns = [
289
+ [/\*\*(.+?)\*\*/g, 'strong'],
290
+ [/__(.+?)__/g, 'strong'],
291
+ [/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, 'em'],
292
+ [/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g, 'em'],
293
+ [/~~(.+?)~~/g, 'del'],
294
+ [/`([^`]+)`/g, 'code']
295
+ ];
296
+
297
+ patterns.forEach(([pattern, tag]) => {
298
+ text = text.replace(pattern, `<${tag}${getAttr(tag)}>$1</${tag}>`);
299
+ });
302
300
 
303
301
  return text;
304
302
  }
@@ -306,7 +304,7 @@
306
304
  /**
307
305
  * Process markdown tables
308
306
  */
309
- function processTable(text, inline_styles, styles) {
307
+ function processTable(text, getAttr) {
310
308
  const lines = text.split('\n');
311
309
  const result = [];
312
310
  let inTable = false;
@@ -326,7 +324,7 @@
326
324
  // Not a table line
327
325
  if (inTable) {
328
326
  // Process the accumulated table
329
- const tableHtml = buildTable(tableLines, inline_styles, styles);
327
+ const tableHtml = buildTable(tableLines, getAttr);
330
328
  if (tableHtml) {
331
329
  result.push(tableHtml);
332
330
  } else {
@@ -342,7 +340,7 @@
342
340
 
343
341
  // Handle table at end of text
344
342
  if (inTable && tableLines.length > 0) {
345
- const tableHtml = buildTable(tableLines, inline_styles, styles);
343
+ const tableHtml = buildTable(tableLines, getAttr);
346
344
  if (tableHtml) {
347
345
  result.push(tableHtml);
348
346
  } else {
@@ -356,17 +354,7 @@
356
354
  /**
357
355
  * Build an HTML table from markdown table lines
358
356
  */
359
- function buildTable(lines, inline_styles, styles) {
360
- // Helper to get attributes
361
- function getAttr(tag, additionalStyle = '') {
362
- if (inline_styles) {
363
- const style = styles[tag] || '';
364
- const fullStyle = additionalStyle ? `${style}; ${additionalStyle}` : style;
365
- return fullStyle ? ` style="${fullStyle}"` : '';
366
- } else {
367
- return ` class="quikdown-${tag}"`;
368
- }
369
- }
357
+ function buildTable(lines, getAttr) {
370
358
 
371
359
  if (lines.length < 2) return null;
372
360
 
@@ -406,8 +394,8 @@
406
394
  // Handle pipes at start/end or not
407
395
  const cells = line.trim().replace(/^\|/, '').replace(/\|$/, '').split('|');
408
396
  cells.forEach((cell, i) => {
409
- const alignStyle = alignments[i] && alignments[i] !== 'left' ? `text-align: ${alignments[i]}` : '';
410
- const processedCell = processInlineMarkdown(cell.trim(), inline_styles, styles);
397
+ const alignStyle = alignments[i] && alignments[i] !== 'left' ? `text-align:${alignments[i]}` : '';
398
+ const processedCell = processInlineMarkdown(cell.trim(), getAttr);
411
399
  html += `<th${getAttr('th', alignStyle)}>${processedCell}</th>\n`;
412
400
  });
413
401
  html += '</tr>\n';
@@ -423,8 +411,8 @@
423
411
  // Handle pipes at start/end or not
424
412
  const cells = line.trim().replace(/^\|/, '').replace(/\|$/, '').split('|');
425
413
  cells.forEach((cell, i) => {
426
- const alignStyle = alignments[i] && alignments[i] !== 'left' ? `text-align: ${alignments[i]}` : '';
427
- const processedCell = processInlineMarkdown(cell.trim(), inline_styles, styles);
414
+ const alignStyle = alignments[i] && alignments[i] !== 'left' ? `text-align:${alignments[i]}` : '';
415
+ const processedCell = processInlineMarkdown(cell.trim(), getAttr);
428
416
  html += `<td${getAttr('td', alignStyle)}>${processedCell}</td>\n`;
429
417
  });
430
418
  html += '</tr>\n';
@@ -439,17 +427,7 @@
439
427
  /**
440
428
  * Process markdown lists (ordered and unordered)
441
429
  */
442
- function processLists(text, inline_styles, styles) {
443
- // Helper to get attributes
444
- function getAttr(tag, additionalStyle = '') {
445
- if (inline_styles) {
446
- const style = styles[tag] || '';
447
- const fullStyle = additionalStyle ? `${style}; ${additionalStyle}` : style;
448
- return fullStyle ? ` style="${fullStyle}"` : '';
449
- } else {
450
- return ` class="quikdown-${tag}"`;
451
- }
452
- }
430
+ function processLists(text, getAttr, inline_styles) {
453
431
 
454
432
  const lines = text.split('\n');
455
433
  const result = [];
@@ -473,10 +451,10 @@
473
451
  const [, checked, taskContent] = taskMatch;
474
452
  const isChecked = checked.toLowerCase() === 'x';
475
453
  const checkboxAttr = inline_styles
476
- ? ' style="margin-right: 0.5em"'
477
- : ' class="quikdown-task-checkbox"';
454
+ ? ' style="margin-right:.5em"'
455
+ : ` class="${CLASS_PREFIX}task-checkbox"`;
478
456
  listItemContent = `<input type="checkbox"${checkboxAttr}${isChecked ? ' checked' : ''} disabled> ${taskContent}`;
479
- taskListClass = inline_styles ? ' style="list-style: none"' : ' class="quikdown-task-item"';
457
+ taskListClass = inline_styles ? ' style="list-style:none"' : ` class="${CLASS_PREFIX}task-item"`;
480
458
  }
481
459
 
482
460
  // Close deeper levels
@@ -524,39 +502,56 @@
524
502
 
525
503
  /**
526
504
  * Emit CSS styles for quikdown elements
505
+ * @param {string} prefix - Optional class prefix (default: 'quikdown-')
506
+ * @param {string} theme - Optional theme: 'light' (default) or 'dark'
527
507
  * @returns {string} CSS string with quikdown styles
528
508
  */
529
- quikdown.emitStyles = function() {
530
- const styles = {
531
- h1: 'font-size: 2em; font-weight: 600; margin: 0.67em 0; text-align: left',
532
- h2: 'font-size: 1.5em; font-weight: 600; margin: 0.83em 0',
533
- h3: 'font-size: 1.25em; font-weight: 600; margin: 1em 0',
534
- h4: 'font-size: 1em; font-weight: 600; margin: 1.33em 0',
535
- h5: 'font-size: 0.875em; font-weight: 600; margin: 1.67em 0',
536
- h6: 'font-size: 0.85em; font-weight: 600; margin: 2em 0',
537
- pre: 'background: #f4f4f4; padding: 10px; border-radius: 4px; overflow-x: auto; margin: 1em 0',
538
- code: 'background: #f0f0f0; padding: 2px 4px; border-radius: 3px; font-family: monospace',
539
- blockquote: 'border-left: 4px solid #ddd; margin-left: 0; padding-left: 1em',
540
- table: 'border-collapse: collapse; width: 100%; margin: 1em 0',
541
- th: 'border: 1px solid #ddd; padding: 8px; background-color: #f2f2f2; font-weight: bold; text-align: left',
542
- td: 'border: 1px solid #ddd; padding: 8px; text-align: left',
543
- hr: 'border: none; border-top: 1px solid #ddd; margin: 1em 0',
544
- img: 'max-width: 100%; height: auto',
545
- a: 'color: #0066cc; text-decoration: underline',
546
- strong: 'font-weight: bold',
547
- em: 'font-style: italic',
548
- del: 'text-decoration: line-through',
549
- ul: 'margin: 0.5em 0; padding-left: 2em',
550
- ol: 'margin: 0.5em 0; padding-left: 2em',
551
- li: 'margin: 0.25em 0',
552
- 'task-item': 'list-style: none',
553
- 'task-checkbox': 'margin-right: 0.5em'
509
+ quikdown.emitStyles = function(prefix = 'quikdown-', theme = 'light') {
510
+ const styles = QUIKDOWN_STYLES;
511
+
512
+ // Define theme color overrides
513
+ const themeOverrides = {
514
+ dark: {
515
+ '#f4f4f4': '#2a2a2a', // pre background
516
+ '#f0f0f0': '#2a2a2a', // code background
517
+ '#f2f2f2': '#2a2a2a', // th background
518
+ '#ddd': '#3a3a3a', // borders
519
+ '#06c': '#6db3f2', // links
520
+ _textColor: '#e0e0e0'
521
+ },
522
+ light: {
523
+ _textColor: '#333' // Explicit text color for light theme
524
+ }
554
525
  };
555
526
 
556
527
  let css = '';
557
528
  for (const [tag, style] of Object.entries(styles)) {
558
529
  if (style) {
559
- css += `.quikdown-${tag} { ${style} }\n`;
530
+ let themedStyle = style;
531
+
532
+ // Apply theme overrides if dark theme
533
+ if (theme === 'dark' && themeOverrides.dark) {
534
+ // Replace colors
535
+ for (const [oldColor, newColor] of Object.entries(themeOverrides.dark)) {
536
+ if (!oldColor.startsWith('_')) {
537
+ themedStyle = themedStyle.replace(new RegExp(oldColor, 'g'), newColor);
538
+ }
539
+ }
540
+
541
+ // Add text color for certain elements in dark theme
542
+ const needsTextColor = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'td', 'li', 'blockquote'];
543
+ if (needsTextColor.includes(tag)) {
544
+ themedStyle += `;color:${themeOverrides.dark._textColor}`;
545
+ }
546
+ } else if (theme === 'light' && themeOverrides.light) {
547
+ // Add explicit text color for light theme elements too
548
+ const needsTextColor = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'td', 'li', 'blockquote'];
549
+ if (needsTextColor.includes(tag)) {
550
+ themedStyle += `;color:${themeOverrides.light._textColor}`;
551
+ }
552
+ }
553
+
554
+ css += `.${prefix}${tag} { ${themedStyle} }\n`;
560
555
  }
561
556
  }
562
557
 
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * quikdown - Lightweight Markdown Parser
3
- * @version 1.0.2
3
+ * @version 1.0.3
4
4
  * @license BSD-2-Clause
5
5
  * @copyright DeftIO 2025
6
6
  */
7
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).quikdown=t()}(this,function(){"use strict";function e(e,t={}){if(!e||"string"!=typeof e)return"";const{fence_plugin:o,inline_styles:r=!1}=t,l={h1:"font-size: 2em; font-weight: 600; margin: 0.67em 0; text-align: left",h2:"font-size: 1.5em; font-weight: 600; margin: 0.83em 0",h3:"font-size: 1.25em; font-weight: 600; margin: 1em 0",h4:"font-size: 1em; font-weight: 600; margin: 1.33em 0",h5:"font-size: 0.875em; font-weight: 600; margin: 1.67em 0",h6:"font-size: 0.85em; font-weight: 600; margin: 2em 0",pre:"background: #f4f4f4; padding: 10px; border-radius: 4px; overflow-x: auto; margin: 1em 0",code:"background: #f0f0f0; padding: 2px 4px; border-radius: 3px; font-family: monospace",blockquote:"border-left: 4px solid #ddd; margin-left: 0; padding-left: 1em",table:"border-collapse: collapse; width: 100%; margin: 1em 0",thead:"",tbody:"",tr:"",th:"border: 1px solid #ddd; padding: 8px; background-color: #f2f2f2; font-weight: bold; text-align: left",td:"border: 1px solid #ddd; padding: 8px; text-align: left",hr:"border: none; border-top: 1px solid #ddd; margin: 1em 0",img:"max-width: 100%; height: auto",a:"color: #0066cc; text-decoration: underline",strong:"font-weight: bold",em:"font-style: italic",del:"text-decoration: line-through",ul:"margin: 0.5em 0; padding-left: 2em",ol:"margin: 0.5em 0; padding-left: 2em",li:"margin: 0.25em 0",br:""};function i(e,t=""){if(r){const n=l[e]||"",o=t?`${n}; ${t}`:n;return o?` style="${o}"`:""}return` class="quikdown-${e}"`}function a(e){const t={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};return e.replace(/[&<>"']/g,e=>t[e])}function s(e,t=!1){if(!e)return"";if(t)return e;const n=e.trim(),o=n.toLowerCase(),r=["javascript:","vbscript:","data:"];for(const e of r)if(o.startsWith(e))return"data:"===e&&o.startsWith("data:image/")?n:"#";return n}let c=e;const d=[],p=[];return c=c.replace(/^(```|~~~)([^\n]*)\n([\s\S]*?)^\1$/gm,(e,t,n,r)=>{const l=`%%%CODEBLOCK${d.length}%%%`,i=n?n.trim():"";return o&&"function"==typeof o?d.push({lang:i,code:r.trimEnd(),custom:!0}):d.push({lang:i,code:a(r.trimEnd()),custom:!1}),l}),c=c.replace(/`([^`]+)`/g,(e,t)=>{const n=`%%%INLINECODE${p.length}%%%`;return p.push(a(t)),n}),c=a(c),c=function(e,t,o){const r=e.split("\n"),l=[];let i=!1,a=[];for(let e=0;e<r.length;e++){const s=r[e].trim();if(s.includes("|")&&(s.startsWith("|")||/[^\\|]/.test(s)))i||(i=!0,a=[]),a.push(s);else{if(i){const e=n(a,t,o);e?l.push(e):l.push(...a),i=!1,a=[]}l.push(r[e])}}if(i&&a.length>0){const e=n(a,t,o);e?l.push(e):l.push(...a)}return l.join("\n")}(c,r,l),c=c.replace(/^(#{1,6})\s+(.+?)\s*#*$/gm,(e,t,n)=>{const o=t.length;return`<h${o}${i("h"+o)}>${n}</h${o}>`}),c=c.replace(/^&gt;\s+(.+)$/gm,`<blockquote${i("blockquote")}>$1</blockquote>`),c=c.replace(/<\/blockquote>\n<blockquote>/g,"\n"),c=c.replace(/^---+$/gm,`<hr${i("hr")}>`),c=function(e,t,n){function o(e,o=""){if(t){const t=n[e]||"",r=o?`${t}; ${o}`:t;return r?` style="${r}"`:""}return` class="quikdown-${e}"`}const r=e.split("\n"),l=[];let i=[];for(let e=0;e<r.length;e++){const n=r[e],a=n.match(/^(\s*)([*\-+]|\d+\.)\s+(.+)$/);if(a){const[,e,n,r]=a,s=Math.floor(e.length/2),c=/^\d+\./.test(n),d=c?"ol":"ul";let p=r,g="";const f=r.match(/^\[([x ])\]\s+(.*)$/i);if(f&&!c){const[,e,n]=f,o="x"===e.toLowerCase();p=`<input type="checkbox"${t?' style="margin-right: 0.5em"':' class="quikdown-task-checkbox"'}${o?" checked":""} disabled> ${n}`,g=t?' style="list-style: none"':' class="quikdown-task-item"'}for(;i.length>s+1;){const e=i.pop();l.push(`</${e.type}>`)}if(i.length===s)i.push({type:d,level:s}),l.push(`<${d}${o(d)}>`);else if(i.length===s+1){const e=i[i.length-1];e.type!==d&&(l.push(`</${e.type}>`),i.pop(),i.push({type:d,level:s}),l.push(`<${d}${o(d)}>`))}const u=g||o("li");l.push(`<li${u}>${p}</li>`)}else{for(;i.length>0;){const e=i.pop();l.push(`</${e.type}>`)}l.push(n)}}for(;i.length>0;){const e=i.pop();l.push(`</${e.type}>`)}return l.join("\n")}(c,r,l),c=c.replace(/!\[([^\]]*)\]\(([^)]+)\)/g,(e,n,o)=>{const r=s(o,t.allow_unsafe_urls);return`<img${i("img")} src="${r}" alt="${n}">`}),c=c.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(e,n,o)=>{const r=s(o,t.allow_unsafe_urls),l=/^https?:\/\//i.test(r)?' rel="noopener noreferrer"':"";return`<a${i("a")} href="${r}"${l}>${n}</a>`}),c=c.replace(/(^|\s)(https?:\/\/[^\s<]+)/g,(e,n,o)=>{const r=s(o,t.allow_unsafe_urls);return`${n}<a${i("a")} href="${r}" rel="noopener noreferrer">${o}</a>`}),c=c.replace(/\*\*(.+?)\*\*/g,`<strong${i("strong")}>$1</strong>`),c=c.replace(/__(.+?)__/g,`<strong${i("strong")}>$1</strong>`),c=c.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,`<em${i("em")}>$1</em>`),c=c.replace(/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g,`<em${i("em")}>$1</em>`),c=c.replace(/~~(.+?)~~/g,`<del${i("del")}>$1</del>`),c=c.replace(/ $/gm,`<br${i("br")}>`),c=c.replace(/\n\n+/g,"</p><p>"),c="<p>"+c+"</p>",c=c.replace(/<p><\/p>/g,""),c=c.replace(/<p>(<h[1-6][^>]*>)/g,"$1"),c=c.replace(/(<\/h[1-6]>)<\/p>/g,"$1"),c=c.replace(/<p>(<blockquote[^>]*>)/g,"$1"),c=c.replace(/(<\/blockquote>)<\/p>/g,"$1"),c=c.replace(/<p>(<ul[^>]*>|<ol[^>]*>)/g,"$1"),c=c.replace(/(<\/ul>|<\/ol>)<\/p>/g,"$1"),c=c.replace(/<p>(<hr[^>]*>)<\/p>/g,"$1"),c=c.replace(/<p>(<table[^>]*>)/g,"$1"),c=c.replace(/(<\/table>)<\/p>/g,"$1"),c=c.replace(/<p>(<pre[^>]*>)/g,"$1"),c=c.replace(/(<\/pre>)<\/p>/g,"$1"),c=c.replace(/<p>(%%%CODEBLOCK\d+%%%)<\/p>/g,"$1"),d.forEach((e,t)=>{let n;if(e.custom&&o){if(n=o(e.code,e.lang),void 0===n){const t=!r&&e.lang?` class="language-${e.lang}"`:"",o=r?i("code"):t;n=`<pre${i("pre")}><code${o}>${a(e.code)}</code></pre>`}}else{const t=!r&&e.lang?` class="language-${e.lang}"`:"",o=r?i("code"):t;n=`<pre${i("pre")}><code${o}>${e.code}</code></pre>`}const l=`%%%CODEBLOCK${t}%%%`;c=c.replace(l,n)}),p.forEach((e,t)=>{const n=`%%%INLINECODE${t}%%%`;c=c.replace(n,`<code${i("code")}>${e}</code>`)}),c.trim()}function t(e,t,n){function o(e,o=""){if(t){const t=n[e]||"",r=o?`${t}; ${o}`:t;return r?` style="${r}"`:""}return` class="quikdown-${e}"`}return e=(e=(e=(e=(e=(e=e.replace(/\*\*(.+?)\*\*/g,`<strong${o("strong")}>$1</strong>`)).replace(/__(.+?)__/g,`<strong${o("strong")}>$1</strong>`)).replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,`<em${o("em")}>$1</em>`)).replace(/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g,`<em${o("em")}>$1</em>`)).replace(/~~(.+?)~~/g,`<del${o("del")}>$1</del>`)).replace(/`([^`]+)`/g,`<code${o("code")}>$1</code>`)}function n(e,n,o){function r(e,t=""){if(n){const n=o[e]||"",r=t?`${n}; ${t}`:n;return r?` style="${r}"`:""}return` class="quikdown-${e}"`}if(e.length<2)return null;let l=-1;for(let t=1;t<e.length;t++)if(/^\|?[\s\-:|]+\|?$/.test(e[t])&&e[t].includes("-")){l=t;break}if(-1===l)return null;const i=e.slice(0,l),a=e.slice(l+1),s=e[l].trim().replace(/^\|/,"").replace(/\|$/,"").split("|").map(e=>{const t=e.trim();return t.startsWith(":")&&t.endsWith(":")?"center":t.endsWith(":")?"right":"left"});let c=`<table${r("table")}>\n`;return i.length>0&&(c+=`<thead${r("thead")}>\n`,i.forEach(e=>{c+=`<tr${r("tr")}>\n`;e.trim().replace(/^\|/,"").replace(/\|$/,"").split("|").forEach((e,l)=>{const i=s[l]&&"left"!==s[l]?`text-align: ${s[l]}`:"",a=t(e.trim(),n,o);c+=`<th${r("th",i)}>${a}</th>\n`}),c+="</tr>\n"}),c+="</thead>\n"),a.length>0&&(c+=`<tbody${r("tbody")}>\n`,a.forEach(e=>{c+=`<tr${r("tr")}>\n`;e.trim().replace(/^\|/,"").replace(/\|$/,"").split("|").forEach((e,l)=>{const i=s[l]&&"left"!==s[l]?`text-align: ${s[l]}`:"",a=t(e.trim(),n,o);c+=`<td${r("td",i)}>${a}</td>\n`}),c+="</tr>\n"}),c+="</tbody>\n"),c+="</table>",c}return e.emitStyles=function(){const e={h1:"font-size: 2em; font-weight: 600; margin: 0.67em 0; text-align: left",h2:"font-size: 1.5em; font-weight: 600; margin: 0.83em 0",h3:"font-size: 1.25em; font-weight: 600; margin: 1em 0",h4:"font-size: 1em; font-weight: 600; margin: 1.33em 0",h5:"font-size: 0.875em; font-weight: 600; margin: 1.67em 0",h6:"font-size: 0.85em; font-weight: 600; margin: 2em 0",pre:"background: #f4f4f4; padding: 10px; border-radius: 4px; overflow-x: auto; margin: 1em 0",code:"background: #f0f0f0; padding: 2px 4px; border-radius: 3px; font-family: monospace",blockquote:"border-left: 4px solid #ddd; margin-left: 0; padding-left: 1em",table:"border-collapse: collapse; width: 100%; margin: 1em 0",th:"border: 1px solid #ddd; padding: 8px; background-color: #f2f2f2; font-weight: bold; text-align: left",td:"border: 1px solid #ddd; padding: 8px; text-align: left",hr:"border: none; border-top: 1px solid #ddd; margin: 1em 0",img:"max-width: 100%; height: auto",a:"color: #0066cc; text-decoration: underline",strong:"font-weight: bold",em:"font-style: italic",del:"text-decoration: line-through",ul:"margin: 0.5em 0; padding-left: 2em",ol:"margin: 0.5em 0; padding-left: 2em",li:"margin: 0.25em 0","task-item":"list-style: none","task-checkbox":"margin-right: 0.5em"};let t="";for(const[n,o]of Object.entries(e))o&&(t+=`.quikdown-${n} { ${o} }\n`);return t},e.configure=function(t){return function(n){return e(n,t)}},e.version="1.0.2","undefined"!=typeof module&&module.exports&&(module.exports=e),"undefined"!=typeof window&&(window.quikdown=e),e});
7
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).quikdown=t()}(this,function(){"use strict";const e="quikdown-",t="§CB",n={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},o={h1:"font-size:2em;font-weight:600;margin:.67em 0;text-align:left",h2:"font-size:1.5em;font-weight:600;margin:.83em 0",h3:"font-size:1.25em;font-weight:600;margin:1em 0",h4:"font-size:1em;font-weight:600;margin:1.33em 0",h5:"font-size:.875em;font-weight:600;margin:1.67em 0",h6:"font-size:.85em;font-weight:600;margin:2em 0",pre:"background:#f4f4f4;padding:10px;border-radius:4px;overflow-x:auto;margin:1em 0",code:"background:#f0f0f0;padding:2px 4px;border-radius:3px;font-family:monospace",blockquote:"border-left:4px solid #ddd;margin-left:0;padding-left:1em",table:"border-collapse:collapse;width:100%;margin:1em 0",th:"border:1px solid #ddd;padding:8px;background-color:#f2f2f2;font-weight:bold;text-align:left",td:"border:1px solid #ddd;padding:8px;text-align:left",hr:"border:none;border-top:1px solid #ddd;margin:1em 0",img:"max-width:100%;height:auto",a:"color:#06c;text-decoration:underline",strong:"font-weight:bold",em:"font-style:italic",del:"text-decoration:line-through",ul:"margin:.5em 0;padding-left:2em",ol:"margin:.5em 0;padding-left:2em",li:"margin:.25em 0","task-item":"list-style:none","task-checkbox":"margin-right:.5em"};function r(r,l={}){if(!r||"string"!=typeof r)return"";const{fence_plugin:s,inline_styles:c=!1}=l,a=function(t,n){return function(o,r=""){if(t){const e=n[o];return e||r?` style="${r?e?`${e};${r}`:r:e}"`:""}return` class="${e}${o}"`}}(c,o);function p(e){return e.replace(/[&<>"']/g,e=>n[e])}function f(e,t=!1){if(!e)return"";if(t)return e;const n=e.trim(),o=n.toLowerCase(),r=["javascript:","vbscript:","data:"];for(const e of r)if(o.startsWith(e))return"data:"===e&&o.startsWith("data:image/")?n:"#";return n}let g=r;const d=[],u=[];g=g.replace(/^(```|~~~)([^\n]*)\n([\s\S]*?)^\1$/gm,(e,n,o,r)=>{const l=`${t}${d.length}§`,i=o?o.trim():"";return s&&"function"==typeof s?d.push({lang:i,code:r.trimEnd(),custom:!0}):d.push({lang:i,code:p(r.trimEnd()),custom:!1}),l}),g=g.replace(/`([^`]+)`/g,(e,t)=>{const n=`§IC${u.length}§`;return u.push(p(t)),n}),g=p(g),g=function(e,t){const n=e.split("\n"),o=[];let r=!1,l=[];for(let e=0;e<n.length;e++){const s=n[e].trim();if(s.includes("|")&&(s.startsWith("|")||/[^\\|]/.test(s)))r||(r=!0,l=[]),l.push(s);else{if(r){const e=i(l,t);e?o.push(e):o.push(...l),r=!1,l=[]}o.push(n[e])}}if(r&&l.length>0){const e=i(l,t);e?o.push(e):o.push(...l)}return o.join("\n")}(g,a),g=g.replace(/^(#{1,6})\s+(.+?)\s*#*$/gm,(e,t,n)=>{const o=t.length;return`<h${o}${a("h"+o)}>${n}</h${o}>`}),g=g.replace(/^&gt;\s+(.+)$/gm,`<blockquote${a("blockquote")}>$1</blockquote>`),g=g.replace(/<\/blockquote>\n<blockquote>/g,"\n"),g=g.replace(/^---+$/gm,`<hr${a("hr")}>`),g=function(t,n,o){const r=t.split("\n"),l=[];let i=[];for(let t=0;t<r.length;t++){const s=r[t],c=s.match(/^(\s*)([*\-+]|\d+\.)\s+(.+)$/);if(c){const[,t,r,s]=c,a=Math.floor(t.length/2),p=/^\d+\./.test(r),f=p?"ol":"ul";let g=s,d="";const u=s.match(/^\[([x ])\]\s+(.*)$/i);if(u&&!p){const[,t,n]=u,r="x"===t.toLowerCase();g=`<input type="checkbox"${o?' style="margin-right:.5em"':` class="${e}task-checkbox"`}${r?" checked":""} disabled> ${n}`,d=o?' style="list-style:none"':` class="${e}task-item"`}for(;i.length>a+1;){const e=i.pop();l.push(`</${e.type}>`)}if(i.length===a)i.push({type:f,level:a}),l.push(`<${f}${n(f)}>`);else if(i.length===a+1){const e=i[i.length-1];e.type!==f&&(l.push(`</${e.type}>`),i.pop(),i.push({type:f,level:a}),l.push(`<${f}${n(f)}>`))}const h=d||n("li");l.push(`<li${h}>${g}</li>`)}else{for(;i.length>0;){const e=i.pop();l.push(`</${e.type}>`)}l.push(s)}}for(;i.length>0;){const e=i.pop();l.push(`</${e.type}>`)}return l.join("\n")}(g,a,c),g=g.replace(/!\[([^\]]*)\]\(([^)]+)\)/g,(e,t,n)=>{const o=f(n,l.allow_unsafe_urls);return`<img${a("img")} src="${o}" alt="${t}">`}),g=g.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(e,t,n)=>{const o=f(n,l.allow_unsafe_urls),r=/^https?:\/\//i.test(o)?' rel="noopener noreferrer"':"";return`<a${a("a")} href="${o}"${r}>${t}</a>`}),g=g.replace(/(^|\s)(https?:\/\/[^\s<]+)/g,(e,t,n)=>{const o=f(n,l.allow_unsafe_urls);return`${t}<a${a("a")} href="${o}" rel="noopener noreferrer">${n}</a>`});[[/\*\*(.+?)\*\*/g,"strong"],[/__(.+?)__/g,"strong"],[/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,"em"],[/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g,"em"],[/~~(.+?)~~/g,"del"]].forEach(([e,t])=>{g=g.replace(e,`<${t}${a(t)}>$1</${t}>`)}),g=g.replace(/ $/gm,`<br${a("br")}>`),g=g.replace(/\n\n+/g,"</p><p>"),g="<p>"+g+"</p>";return[[/<p><\/p>/g,""],[/<p>(<h[1-6][^>]*>)/g,"$1"],[/(<\/h[1-6]>)<\/p>/g,"$1"],[/<p>(<blockquote[^>]*>)/g,"$1"],[/(<\/blockquote>)<\/p>/g,"$1"],[/<p>(<ul[^>]*>|<ol[^>]*>)/g,"$1"],[/(<\/ul>|<\/ol>)<\/p>/g,"$1"],[/<p>(<hr[^>]*>)<\/p>/g,"$1"],[/<p>(<table[^>]*>)/g,"$1"],[/(<\/table>)<\/p>/g,"$1"],[/<p>(<pre[^>]*>)/g,"$1"],[/(<\/pre>)<\/p>/g,"$1"],[new RegExp(`<p>(${t}\\d)</p>`,"g"),"$1"]].forEach(([e,t])=>{g=g.replace(e,t)}),d.forEach((e,n)=>{let o;if(e.custom&&s){if(o=s(e.code,e.lang),void 0===o){const t=!c&&e.lang?` class="language-${e.lang}"`:"",n=c?a("code"):t;o=`<pre${a("pre")}><code${n}>${p(e.code)}</code></pre>`}}else{const t=!c&&e.lang?` class="language-${e.lang}"`:"",n=c?a("code"):t;o=`<pre${a("pre")}><code${n}>${e.code}</code></pre>`}const r=`${t}${n}§`;g=g.replace(r,o)}),u.forEach((e,t)=>{const n=`§IC${t}§`;g=g.replace(n,`<code${a("code")}>${e}</code>`)}),g.trim()}function l(e,t){return[[/\*\*(.+?)\*\*/g,"strong"],[/__(.+?)__/g,"strong"],[/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,"em"],[/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g,"em"],[/~~(.+?)~~/g,"del"],[/`([^`]+)`/g,"code"]].forEach(([n,o])=>{e=e.replace(n,`<${o}${t(o)}>$1</${o}>`)}),e}function i(e,t){if(e.length<2)return null;let n=-1;for(let t=1;t<e.length;t++)if(/^\|?[\s\-:|]+\|?$/.test(e[t])&&e[t].includes("-")){n=t;break}if(-1===n)return null;const o=e.slice(0,n),r=e.slice(n+1),i=e[n].trim().replace(/^\|/,"").replace(/\|$/,"").split("|").map(e=>{const t=e.trim();return t.startsWith(":")&&t.endsWith(":")?"center":t.endsWith(":")?"right":"left"});let s=`<table${t("table")}>\n`;return o.length>0&&(s+=`<thead${t("thead")}>\n`,o.forEach(e=>{s+=`<tr${t("tr")}>\n`;e.trim().replace(/^\|/,"").replace(/\|$/,"").split("|").forEach((e,n)=>{const o=i[n]&&"left"!==i[n]?`text-align:${i[n]}`:"",r=l(e.trim(),t);s+=`<th${t("th",o)}>${r}</th>\n`}),s+="</tr>\n"}),s+="</thead>\n"),r.length>0&&(s+=`<tbody${t("tbody")}>\n`,r.forEach(e=>{s+=`<tr${t("tr")}>\n`;e.trim().replace(/^\|/,"").replace(/\|$/,"").split("|").forEach((e,n)=>{const o=i[n]&&"left"!==i[n]?`text-align:${i[n]}`:"",r=l(e.trim(),t);s+=`<td${t("td",o)}>${r}</td>\n`}),s+="</tr>\n"}),s+="</tbody>\n"),s+="</table>",s}return r.emitStyles=function(e="quikdown-",t="light"){const n=o,r={"#f4f4f4":"#2a2a2a","#f0f0f0":"#2a2a2a","#f2f2f2":"#2a2a2a","#ddd":"#3a3a3a","#06c":"#6db3f2",_textColor:"#e0e0e0"},l={_textColor:"#333"};let i="";for(const[o,s]of Object.entries(n))if(s){let n=s;if("dark"===t&&r){for(const[e,t]of Object.entries(r))e.startsWith("_")||(n=n.replace(new RegExp(e,"g"),t));["h1","h2","h3","h4","h5","h6","td","li","blockquote"].includes(o)&&(n+=`;color:${r._textColor}`)}else if("light"===t&&l){["h1","h2","h3","h4","h5","h6","td","li","blockquote"].includes(o)&&(n+=`;color:${l._textColor}`)}i+=`.${e}${o} { ${n} }\n`}return i},r.configure=function(e){return function(t){return r(t,e)}},r.version="1.0.3","undefined"!=typeof module&&module.exports&&(module.exports=r),"undefined"!=typeof window&&(window.quikdown=r),r});
8
8
  //# sourceMappingURL=quikdown.umd.min.js.map