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,14 +1,9 @@
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
- // Auto-generated version file - DO NOT EDIT MANUALLY
8
- // This file is automatically updated by tools/updateVersion.js
9
-
10
- const quikdownVersion = "1.0.2";
11
-
12
7
  /**
13
8
  * quikdown - A minimal markdown parser optimized for chat/LLM output
14
9
  * Supports tables, code blocks, lists, and common formatting
@@ -20,64 +15,71 @@ const quikdownVersion = "1.0.2";
20
15
  * @returns {string} - The rendered HTML
21
16
  */
22
17
 
18
+ // Version will be injected at build time
19
+ const quikdownVersion = '1.0.3';
23
20
 
24
- function quikdown(markdown, options = {}) {
25
- if (!markdown || typeof markdown !== 'string') {
26
- return '';
27
- }
28
-
29
- const { fence_plugin, inline_styles = false } = options;
21
+ // Constants for reuse
22
+ const CLASS_PREFIX = 'quikdown-';
23
+ const PLACEHOLDER_CB = '§CB';
24
+ const PLACEHOLDER_IC = '§IC';
30
25
 
31
- // Style definitions - minimal, matching emitStyles
32
- const styles = {
33
- h1: 'font-size: 2em; font-weight: 600; margin: 0.67em 0; text-align: left',
34
- h2: 'font-size: 1.5em; font-weight: 600; margin: 0.83em 0',
35
- h3: 'font-size: 1.25em; font-weight: 600; margin: 1em 0',
36
- h4: 'font-size: 1em; font-weight: 600; margin: 1.33em 0',
37
- h5: 'font-size: 0.875em; font-weight: 600; margin: 1.67em 0',
38
- h6: 'font-size: 0.85em; font-weight: 600; margin: 2em 0',
39
- pre: 'background: #f4f4f4; padding: 10px; border-radius: 4px; overflow-x: auto; margin: 1em 0',
40
- code: 'background: #f0f0f0; padding: 2px 4px; border-radius: 3px; font-family: monospace',
41
- blockquote: 'border-left: 4px solid #ddd; margin-left: 0; padding-left: 1em',
42
- table: 'border-collapse: collapse; width: 100%; margin: 1em 0',
43
- thead: '',
44
- tbody: '',
45
- tr: '',
46
- th: 'border: 1px solid #ddd; padding: 8px; background-color: #f2f2f2; font-weight: bold; text-align: left',
47
- td: 'border: 1px solid #ddd; padding: 8px; text-align: left',
48
- hr: 'border: none; border-top: 1px solid #ddd; margin: 1em 0',
49
- img: 'max-width: 100%; height: auto',
50
- a: 'color: #0066cc; text-decoration: underline',
51
- strong: 'font-weight: bold',
52
- em: 'font-style: italic',
53
- del: 'text-decoration: line-through',
54
- ul: 'margin: 0.5em 0; padding-left: 2em',
55
- ol: 'margin: 0.5em 0; padding-left: 2em',
56
- li: 'margin: 0.25em 0',
57
- br: ''
58
- };
26
+ // Escape map at module level
27
+ const ESC_MAP = {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'};
59
28
 
60
- // Helper to get class or style attribute
61
- function getAttr(tag, additionalStyle = '') {
29
+ // Single source of truth for all style definitions - optimized
30
+ const QUIKDOWN_STYLES = {
31
+ h1: 'font-size:2em;font-weight:600;margin:.67em 0;text-align:left',
32
+ h2: 'font-size:1.5em;font-weight:600;margin:.83em 0',
33
+ h3: 'font-size:1.25em;font-weight:600;margin:1em 0',
34
+ h4: 'font-size:1em;font-weight:600;margin:1.33em 0',
35
+ h5: 'font-size:.875em;font-weight:600;margin:1.67em 0',
36
+ h6: 'font-size:.85em;font-weight:600;margin:2em 0',
37
+ pre: 'background:#f4f4f4;padding:10px;border-radius:4px;overflow-x:auto;margin:1em 0',
38
+ code: 'background:#f0f0f0;padding:2px 4px;border-radius:3px;font-family:monospace',
39
+ blockquote: 'border-left:4px solid #ddd;margin-left:0;padding-left:1em',
40
+ table: 'border-collapse:collapse;width:100%;margin:1em 0',
41
+ th: 'border:1px solid #ddd;padding:8px;background-color:#f2f2f2;font-weight:bold;text-align:left',
42
+ td: 'border:1px solid #ddd;padding:8px;text-align:left',
43
+ hr: 'border:none;border-top:1px solid #ddd;margin:1em 0',
44
+ img: 'max-width:100%;height:auto',
45
+ a: 'color:#06c;text-decoration:underline',
46
+ strong: 'font-weight:bold',
47
+ em: 'font-style:italic',
48
+ del: 'text-decoration:line-through',
49
+ ul: 'margin:.5em 0;padding-left:2em',
50
+ ol: 'margin:.5em 0;padding-left:2em',
51
+ li: 'margin:.25em 0',
52
+ // Task list specific styles
53
+ 'task-item': 'list-style:none',
54
+ 'task-checkbox': 'margin-right:.5em'
55
+ };
56
+
57
+ // Factory function to create getAttr for a given context
58
+ function createGetAttr(inline_styles, styles) {
59
+ return function(tag, additionalStyle = '') {
62
60
  if (inline_styles) {
63
- const style = styles[tag] || '';
64
- const fullStyle = additionalStyle ? `${style}; ${additionalStyle}` : style;
65
- return fullStyle ? ` style="${fullStyle}"` : '';
61
+ const style = styles[tag];
62
+ if (!style && !additionalStyle) return '';
63
+ const fullStyle = additionalStyle ? (style ? `${style};${additionalStyle}` : additionalStyle) : style;
64
+ return ` style="${fullStyle}"`;
66
65
  } else {
67
- return ` class="quikdown-${tag}"`;
66
+ return ` class="${CLASS_PREFIX}${tag}"`;
68
67
  }
68
+ };
69
+ }
70
+
71
+ function quikdown(markdown, options = {}) {
72
+ if (!markdown || typeof markdown !== 'string') {
73
+ return '';
69
74
  }
75
+
76
+ const { fence_plugin, inline_styles = false } = options;
77
+ const styles = QUIKDOWN_STYLES; // Use module-level styles
78
+ const getAttr = createGetAttr(inline_styles, styles); // Create getAttr once
70
79
 
71
80
  // Escape HTML entities to prevent XSS
72
81
  function escapeHtml(text) {
73
- const map = {
74
- '&': '&amp;',
75
- '<': '&lt;',
76
- '>': '&gt;',
77
- '"': '&quot;',
78
- "'": '&#39;'
79
- };
80
- return text.replace(/[&<>"']/g, m => map[m]);
82
+ return text.replace(/[&<>"']/g, m => ESC_MAP[m]);
81
83
  }
82
84
 
83
85
  // Sanitize URLs to prevent XSS attacks
@@ -87,7 +89,6 @@ function quikdown(markdown, options = {}) {
87
89
  // If unsafe URLs are explicitly allowed, return as-is
88
90
  if (allowUnsafe) return url;
89
91
 
90
- // Trim and lowercase for checking
91
92
  const trimmedUrl = url.trim();
92
93
  const lowerUrl = trimmedUrl.toLowerCase();
93
94
 
@@ -119,7 +120,7 @@ function quikdown(markdown, options = {}) {
119
120
  // Match paired fences - ``` with ``` and ~~~ with ~~~
120
121
  // Fence must be at start of line
121
122
  html = html.replace(/^(```|~~~)([^\n]*)\n([\s\S]*?)^\1$/gm, (match, fence, lang, code) => {
122
- const placeholder = `%%%CODEBLOCK${codeBlocks.length}%%%`;
123
+ const placeholder = `${PLACEHOLDER_CB}${codeBlocks.length}§`;
123
124
 
124
125
  // Trim the language specification
125
126
  const langTrimmed = lang ? lang.trim() : '';
@@ -143,7 +144,7 @@ function quikdown(markdown, options = {}) {
143
144
 
144
145
  // Extract inline code
145
146
  html = html.replace(/`([^`]+)`/g, (match, code) => {
146
- const placeholder = `%%%INLINECODE${inlineCodes.length}%%%`;
147
+ const placeholder = `${PLACEHOLDER_IC}${inlineCodes.length}§`;
147
148
  inlineCodes.push(escapeHtml(code));
148
149
  return placeholder;
149
150
  });
@@ -154,7 +155,7 @@ function quikdown(markdown, options = {}) {
154
155
  // Phase 2: Process block elements
155
156
 
156
157
  // Process tables
157
- html = processTable(html, inline_styles, styles);
158
+ html = processTable(html, getAttr);
158
159
 
159
160
  // Process headings (supports optional trailing #'s)
160
161
  html = html.replace(/^(#{1,6})\s+(.+?)\s*#*$/gm, (match, hashes, content) => {
@@ -171,7 +172,7 @@ function quikdown(markdown, options = {}) {
171
172
  html = html.replace(/^---+$/gm, `<hr${getAttr('hr')}>`);
172
173
 
173
174
  // Process lists
174
- html = processLists(html, inline_styles, styles);
175
+ html = processLists(html, getAttr, inline_styles);
175
176
 
176
177
  // Phase 3: Process inline elements
177
178
 
@@ -196,16 +197,18 @@ function quikdown(markdown, options = {}) {
196
197
  return `${prefix}<a${getAttr('a')} href="${sanitizedUrl}" rel="noopener noreferrer">${url}</a>`;
197
198
  });
198
199
 
199
- // Bold (must use non-greedy matching)
200
- html = html.replace(/\*\*(.+?)\*\*/g, `<strong${getAttr('strong')}>$1</strong>`);
201
- html = html.replace(/__(.+?)__/g, `<strong${getAttr('strong')}>$1</strong>`);
202
-
203
- // Italic (must not match bold markers)
204
- html = html.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, `<em${getAttr('em')}>$1</em>`);
205
- html = html.replace(/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g, `<em${getAttr('em')}>$1</em>`);
206
-
207
- // Strikethrough
208
- html = html.replace(/~~(.+?)~~/g, `<del${getAttr('del')}>$1</del>`);
200
+ // Process inline formatting (bold, italic, strikethrough)
201
+ const inlinePatterns = [
202
+ [/\*\*(.+?)\*\*/g, 'strong'],
203
+ [/__(.+?)__/g, 'strong'],
204
+ [/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, 'em'],
205
+ [/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g, 'em'],
206
+ [/~~(.+?)~~/g, 'del']
207
+ ];
208
+
209
+ inlinePatterns.forEach(([pattern, tag]) => {
210
+ html = html.replace(pattern, `<${tag}${getAttr(tag)}>$1</${tag}>`);
211
+ });
209
212
 
210
213
  // Line breaks (two spaces at end of line)
211
214
  html = html.replace(/ $/gm, `<br${getAttr('br')}>`);
@@ -214,21 +217,26 @@ function quikdown(markdown, options = {}) {
214
217
  html = html.replace(/\n\n+/g, '</p><p>');
215
218
  html = '<p>' + html + '</p>';
216
219
 
217
- // Clean up empty paragraphs and unwrap block elements (account for attributes)
218
- html = html.replace(/<p><\/p>/g, '');
219
- html = html.replace(/<p>(<h[1-6][^>]*>)/g, '$1');
220
- html = html.replace(/(<\/h[1-6]>)<\/p>/g, '$1');
221
- html = html.replace(/<p>(<blockquote[^>]*>)/g, '$1');
222
- html = html.replace(/(<\/blockquote>)<\/p>/g, '$1');
223
- html = html.replace(/<p>(<ul[^>]*>|<ol[^>]*>)/g, '$1');
224
- html = html.replace(/(<\/ul>|<\/ol>)<\/p>/g, '$1');
225
- html = html.replace(/<p>(<hr[^>]*>)<\/p>/g, '$1');
226
- html = html.replace(/<p>(<table[^>]*>)/g, '$1');
227
- html = html.replace(/(<\/table>)<\/p>/g, '$1');
228
- html = html.replace(/<p>(<pre[^>]*>)/g, '$1');
229
- html = html.replace(/(<\/pre>)<\/p>/g, '$1');
230
- // Also unwrap code block placeholders
231
- html = html.replace(/<p>(%%%CODEBLOCK\d+%%%)<\/p>/g, '$1');
220
+ // Clean up empty paragraphs and unwrap block elements
221
+ const cleanupPatterns = [
222
+ [/<p><\/p>/g, ''],
223
+ [/<p>(<h[1-6][^>]*>)/g, '$1'],
224
+ [/(<\/h[1-6]>)<\/p>/g, '$1'],
225
+ [/<p>(<blockquote[^>]*>)/g, '$1'],
226
+ [/(<\/blockquote>)<\/p>/g, '$1'],
227
+ [/<p>(<ul[^>]*>|<ol[^>]*>)/g, '$1'],
228
+ [/(<\/ul>|<\/ol>)<\/p>/g, '$1'],
229
+ [/<p>(<hr[^>]*>)<\/p>/g, '$1'],
230
+ [/<p>(<table[^>]*>)/g, '$1'],
231
+ [/(<\/table>)<\/p>/g, '$1'],
232
+ [/<p>(<pre[^>]*>)/g, '$1'],
233
+ [/(<\/pre>)<\/p>/g, '$1'],
234
+ [new RegExp(`<p>(${PLACEHOLDER_CB}\\d)<\/p>`, 'g'), '$1']
235
+ ];
236
+
237
+ cleanupPatterns.forEach(([pattern, replacement]) => {
238
+ html = html.replace(pattern, replacement);
239
+ });
232
240
 
233
241
  // Phase 4: Restore code blocks and inline code
234
242
 
@@ -252,13 +260,13 @@ function quikdown(markdown, options = {}) {
252
260
  replacement = `<pre${getAttr('pre')}><code${codeAttr}>${block.code}</code></pre>`;
253
261
  }
254
262
 
255
- const placeholder = `%%%CODEBLOCK${i}%%%`;
263
+ const placeholder = `${PLACEHOLDER_CB}${i}§`;
256
264
  html = html.replace(placeholder, replacement);
257
265
  });
258
266
 
259
267
  // Restore inline code
260
268
  inlineCodes.forEach((code, i) => {
261
- const placeholder = `%%%INLINECODE${i}%%%`;
269
+ const placeholder = `${PLACEHOLDER_IC}${i}§`;
262
270
  html = html.replace(placeholder, `<code${getAttr('code')}>${code}</code>`);
263
271
  });
264
272
 
@@ -268,31 +276,21 @@ function quikdown(markdown, options = {}) {
268
276
  /**
269
277
  * Process inline markdown formatting
270
278
  */
271
- function processInlineMarkdown(text, inline_styles, styles) {
272
- // Helper to get attributes
273
- function getAttr(tag, additionalStyle = '') {
274
- if (inline_styles) {
275
- const style = styles[tag] || '';
276
- const fullStyle = additionalStyle ? `${style}; ${additionalStyle}` : style;
277
- return fullStyle ? ` style="${fullStyle}"` : '';
278
- } else {
279
- return ` class="quikdown-${tag}"`;
280
- }
281
- }
282
-
283
- // Process bold
284
- text = text.replace(/\*\*(.+?)\*\*/g, `<strong${getAttr('strong')}>$1</strong>`);
285
- text = text.replace(/__(.+?)__/g, `<strong${getAttr('strong')}>$1</strong>`);
286
-
287
- // Process italic (must not match bold markers)
288
- text = text.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, `<em${getAttr('em')}>$1</em>`);
289
- text = text.replace(/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g, `<em${getAttr('em')}>$1</em>`);
290
-
291
- // Process strikethrough
292
- text = text.replace(/~~(.+?)~~/g, `<del${getAttr('del')}>$1</del>`);
293
-
294
- // Process inline code
295
- text = text.replace(/`([^`]+)`/g, `<code${getAttr('code')}>$1</code>`);
279
+ function processInlineMarkdown(text, getAttr) {
280
+
281
+ // Process inline formatting patterns
282
+ const patterns = [
283
+ [/\*\*(.+?)\*\*/g, 'strong'],
284
+ [/__(.+?)__/g, 'strong'],
285
+ [/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, 'em'],
286
+ [/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g, 'em'],
287
+ [/~~(.+?)~~/g, 'del'],
288
+ [/`([^`]+)`/g, 'code']
289
+ ];
290
+
291
+ patterns.forEach(([pattern, tag]) => {
292
+ text = text.replace(pattern, `<${tag}${getAttr(tag)}>$1</${tag}>`);
293
+ });
296
294
 
297
295
  return text;
298
296
  }
@@ -300,7 +298,7 @@ function processInlineMarkdown(text, inline_styles, styles) {
300
298
  /**
301
299
  * Process markdown tables
302
300
  */
303
- function processTable(text, inline_styles, styles) {
301
+ function processTable(text, getAttr) {
304
302
  const lines = text.split('\n');
305
303
  const result = [];
306
304
  let inTable = false;
@@ -320,7 +318,7 @@ function processTable(text, inline_styles, styles) {
320
318
  // Not a table line
321
319
  if (inTable) {
322
320
  // Process the accumulated table
323
- const tableHtml = buildTable(tableLines, inline_styles, styles);
321
+ const tableHtml = buildTable(tableLines, getAttr);
324
322
  if (tableHtml) {
325
323
  result.push(tableHtml);
326
324
  } else {
@@ -336,7 +334,7 @@ function processTable(text, inline_styles, styles) {
336
334
 
337
335
  // Handle table at end of text
338
336
  if (inTable && tableLines.length > 0) {
339
- const tableHtml = buildTable(tableLines, inline_styles, styles);
337
+ const tableHtml = buildTable(tableLines, getAttr);
340
338
  if (tableHtml) {
341
339
  result.push(tableHtml);
342
340
  } else {
@@ -350,17 +348,7 @@ function processTable(text, inline_styles, styles) {
350
348
  /**
351
349
  * Build an HTML table from markdown table lines
352
350
  */
353
- function buildTable(lines, inline_styles, styles) {
354
- // Helper to get attributes
355
- function getAttr(tag, additionalStyle = '') {
356
- if (inline_styles) {
357
- const style = styles[tag] || '';
358
- const fullStyle = additionalStyle ? `${style}; ${additionalStyle}` : style;
359
- return fullStyle ? ` style="${fullStyle}"` : '';
360
- } else {
361
- return ` class="quikdown-${tag}"`;
362
- }
363
- }
351
+ function buildTable(lines, getAttr) {
364
352
 
365
353
  if (lines.length < 2) return null;
366
354
 
@@ -400,8 +388,8 @@ function buildTable(lines, inline_styles, styles) {
400
388
  // Handle pipes at start/end or not
401
389
  const cells = line.trim().replace(/^\|/, '').replace(/\|$/, '').split('|');
402
390
  cells.forEach((cell, i) => {
403
- const alignStyle = alignments[i] && alignments[i] !== 'left' ? `text-align: ${alignments[i]}` : '';
404
- const processedCell = processInlineMarkdown(cell.trim(), inline_styles, styles);
391
+ const alignStyle = alignments[i] && alignments[i] !== 'left' ? `text-align:${alignments[i]}` : '';
392
+ const processedCell = processInlineMarkdown(cell.trim(), getAttr);
405
393
  html += `<th${getAttr('th', alignStyle)}>${processedCell}</th>\n`;
406
394
  });
407
395
  html += '</tr>\n';
@@ -417,8 +405,8 @@ function buildTable(lines, inline_styles, styles) {
417
405
  // Handle pipes at start/end or not
418
406
  const cells = line.trim().replace(/^\|/, '').replace(/\|$/, '').split('|');
419
407
  cells.forEach((cell, i) => {
420
- const alignStyle = alignments[i] && alignments[i] !== 'left' ? `text-align: ${alignments[i]}` : '';
421
- const processedCell = processInlineMarkdown(cell.trim(), inline_styles, styles);
408
+ const alignStyle = alignments[i] && alignments[i] !== 'left' ? `text-align:${alignments[i]}` : '';
409
+ const processedCell = processInlineMarkdown(cell.trim(), getAttr);
422
410
  html += `<td${getAttr('td', alignStyle)}>${processedCell}</td>\n`;
423
411
  });
424
412
  html += '</tr>\n';
@@ -433,17 +421,7 @@ function buildTable(lines, inline_styles, styles) {
433
421
  /**
434
422
  * Process markdown lists (ordered and unordered)
435
423
  */
436
- function processLists(text, inline_styles, styles) {
437
- // Helper to get attributes
438
- function getAttr(tag, additionalStyle = '') {
439
- if (inline_styles) {
440
- const style = styles[tag] || '';
441
- const fullStyle = additionalStyle ? `${style}; ${additionalStyle}` : style;
442
- return fullStyle ? ` style="${fullStyle}"` : '';
443
- } else {
444
- return ` class="quikdown-${tag}"`;
445
- }
446
- }
424
+ function processLists(text, getAttr, inline_styles) {
447
425
 
448
426
  const lines = text.split('\n');
449
427
  const result = [];
@@ -467,10 +445,10 @@ function processLists(text, inline_styles, styles) {
467
445
  const [, checked, taskContent] = taskMatch;
468
446
  const isChecked = checked.toLowerCase() === 'x';
469
447
  const checkboxAttr = inline_styles
470
- ? ' style="margin-right: 0.5em"'
471
- : ' class="quikdown-task-checkbox"';
448
+ ? ' style="margin-right:.5em"'
449
+ : ` class="${CLASS_PREFIX}task-checkbox"`;
472
450
  listItemContent = `<input type="checkbox"${checkboxAttr}${isChecked ? ' checked' : ''} disabled> ${taskContent}`;
473
- taskListClass = inline_styles ? ' style="list-style: none"' : ' class="quikdown-task-item"';
451
+ taskListClass = inline_styles ? ' style="list-style:none"' : ` class="${CLASS_PREFIX}task-item"`;
474
452
  }
475
453
 
476
454
  // Close deeper levels
@@ -518,39 +496,56 @@ function processLists(text, inline_styles, styles) {
518
496
 
519
497
  /**
520
498
  * Emit CSS styles for quikdown elements
499
+ * @param {string} prefix - Optional class prefix (default: 'quikdown-')
500
+ * @param {string} theme - Optional theme: 'light' (default) or 'dark'
521
501
  * @returns {string} CSS string with quikdown styles
522
502
  */
523
- quikdown.emitStyles = function() {
524
- const styles = {
525
- h1: 'font-size: 2em; font-weight: 600; margin: 0.67em 0; text-align: left',
526
- h2: 'font-size: 1.5em; font-weight: 600; margin: 0.83em 0',
527
- h3: 'font-size: 1.25em; font-weight: 600; margin: 1em 0',
528
- h4: 'font-size: 1em; font-weight: 600; margin: 1.33em 0',
529
- h5: 'font-size: 0.875em; font-weight: 600; margin: 1.67em 0',
530
- h6: 'font-size: 0.85em; font-weight: 600; margin: 2em 0',
531
- pre: 'background: #f4f4f4; padding: 10px; border-radius: 4px; overflow-x: auto; margin: 1em 0',
532
- code: 'background: #f0f0f0; padding: 2px 4px; border-radius: 3px; font-family: monospace',
533
- blockquote: 'border-left: 4px solid #ddd; margin-left: 0; padding-left: 1em',
534
- table: 'border-collapse: collapse; width: 100%; margin: 1em 0',
535
- th: 'border: 1px solid #ddd; padding: 8px; background-color: #f2f2f2; font-weight: bold; text-align: left',
536
- td: 'border: 1px solid #ddd; padding: 8px; text-align: left',
537
- hr: 'border: none; border-top: 1px solid #ddd; margin: 1em 0',
538
- img: 'max-width: 100%; height: auto',
539
- a: 'color: #0066cc; text-decoration: underline',
540
- strong: 'font-weight: bold',
541
- em: 'font-style: italic',
542
- del: 'text-decoration: line-through',
543
- ul: 'margin: 0.5em 0; padding-left: 2em',
544
- ol: 'margin: 0.5em 0; padding-left: 2em',
545
- li: 'margin: 0.25em 0',
546
- 'task-item': 'list-style: none',
547
- 'task-checkbox': 'margin-right: 0.5em'
503
+ quikdown.emitStyles = function(prefix = 'quikdown-', theme = 'light') {
504
+ const styles = QUIKDOWN_STYLES;
505
+
506
+ // Define theme color overrides
507
+ const themeOverrides = {
508
+ dark: {
509
+ '#f4f4f4': '#2a2a2a', // pre background
510
+ '#f0f0f0': '#2a2a2a', // code background
511
+ '#f2f2f2': '#2a2a2a', // th background
512
+ '#ddd': '#3a3a3a', // borders
513
+ '#06c': '#6db3f2', // links
514
+ _textColor: '#e0e0e0'
515
+ },
516
+ light: {
517
+ _textColor: '#333' // Explicit text color for light theme
518
+ }
548
519
  };
549
520
 
550
521
  let css = '';
551
522
  for (const [tag, style] of Object.entries(styles)) {
552
523
  if (style) {
553
- css += `.quikdown-${tag} { ${style} }\n`;
524
+ let themedStyle = style;
525
+
526
+ // Apply theme overrides if dark theme
527
+ if (theme === 'dark' && themeOverrides.dark) {
528
+ // Replace colors
529
+ for (const [oldColor, newColor] of Object.entries(themeOverrides.dark)) {
530
+ if (!oldColor.startsWith('_')) {
531
+ themedStyle = themedStyle.replace(new RegExp(oldColor, 'g'), newColor);
532
+ }
533
+ }
534
+
535
+ // Add text color for certain elements in dark theme
536
+ const needsTextColor = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'td', 'li', 'blockquote'];
537
+ if (needsTextColor.includes(tag)) {
538
+ themedStyle += `;color:${themeOverrides.dark._textColor}`;
539
+ }
540
+ } else if (theme === 'light' && themeOverrides.light) {
541
+ // Add explicit text color for light theme elements too
542
+ const needsTextColor = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'td', 'li', 'blockquote'];
543
+ if (needsTextColor.includes(tag)) {
544
+ themedStyle += `;color:${themeOverrides.light._textColor}`;
545
+ }
546
+ }
547
+
548
+ css += `.${prefix}${tag} { ${themedStyle} }\n`;
554
549
  }
555
550
  }
556
551
 
@@ -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(e,t={}){if(!e||"string"!=typeof e)return"";const{fence_plugin:r,inline_styles:o=!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(o){const n=l[e]||"",r=t?`${n}; ${t}`:n;return r?` style="${r}"`:""}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(),r=n.toLowerCase(),o=["javascript:","vbscript:","data:"];for(const e of o)if(r.startsWith(e))return"data:"===e&&r.startsWith("data:image/")?n:"#";return n}let c=e;const p=[],d=[];return c=c.replace(/^(```|~~~)([^\n]*)\n([\s\S]*?)^\1$/gm,(e,t,n,o)=>{const l=`%%%CODEBLOCK${p.length}%%%`,i=n?n.trim():"";return r&&"function"==typeof r?p.push({lang:i,code:o.trimEnd(),custom:!0}):p.push({lang:i,code:a(o.trimEnd()),custom:!1}),l}),c=c.replace(/`([^`]+)`/g,(e,t)=>{const n=`%%%INLINECODE${d.length}%%%`;return d.push(a(t)),n}),c=a(c),c=function(e,t,r){const o=e.split("\n"),l=[];let i=!1,a=[];for(let e=0;e<o.length;e++){const s=o[e].trim();if(s.includes("|")&&(s.startsWith("|")||/[^\\|]/.test(s)))i||(i=!0,a=[]),a.push(s);else{if(i){const e=n(a,t,r);e?l.push(e):l.push(...a),i=!1,a=[]}l.push(o[e])}}if(i&&a.length>0){const e=n(a,t,r);e?l.push(e):l.push(...a)}return l.join("\n")}(c,o,l),c=c.replace(/^(#{1,6})\s+(.+?)\s*#*$/gm,(e,t,n)=>{const r=t.length;return`<h${r}${i("h"+r)}>${n}</h${r}>`}),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 r(e,r=""){if(t){const t=n[e]||"",o=r?`${t}; ${r}`:t;return o?` style="${o}"`:""}return` class="quikdown-${e}"`}const o=e.split("\n"),l=[];let i=[];for(let e=0;e<o.length;e++){const n=o[e],a=n.match(/^(\s*)([*\-+]|\d+\.)\s+(.+)$/);if(a){const[,e,n,o]=a,s=Math.floor(e.length/2),c=/^\d+\./.test(n),p=c?"ol":"ul";let d=o,g="";const f=o.match(/^\[([x ])\]\s+(.*)$/i);if(f&&!c){const[,e,n]=f,r="x"===e.toLowerCase();d=`<input type="checkbox"${t?' style="margin-right: 0.5em"':' class="quikdown-task-checkbox"'}${r?" 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:p,level:s}),l.push(`<${p}${r(p)}>`);else if(i.length===s+1){const e=i[i.length-1];e.type!==p&&(l.push(`</${e.type}>`),i.pop(),i.push({type:p,level:s}),l.push(`<${p}${r(p)}>`))}const u=g||r("li");l.push(`<li${u}>${d}</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,o,l),c=c.replace(/!\[([^\]]*)\]\(([^)]+)\)/g,(e,n,r)=>{const o=s(r,t.allow_unsafe_urls);return`<img${i("img")} src="${o}" alt="${n}">`}),c=c.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(e,n,r)=>{const o=s(r,t.allow_unsafe_urls),l=/^https?:\/\//i.test(o)?' rel="noopener noreferrer"':"";return`<a${i("a")} href="${o}"${l}>${n}</a>`}),c=c.replace(/(^|\s)(https?:\/\/[^\s<]+)/g,(e,n,r)=>{const o=s(r,t.allow_unsafe_urls);return`${n}<a${i("a")} href="${o}" rel="noopener noreferrer">${r}</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"),p.forEach((e,t)=>{let n;if(e.custom&&r){if(n=r(e.code,e.lang),void 0===n){const t=!o&&e.lang?` class="language-${e.lang}"`:"",r=o?i("code"):t;n=`<pre${i("pre")}><code${r}>${a(e.code)}</code></pre>`}}else{const t=!o&&e.lang?` class="language-${e.lang}"`:"",r=o?i("code"):t;n=`<pre${i("pre")}><code${r}>${e.code}</code></pre>`}const l=`%%%CODEBLOCK${t}%%%`;c=c.replace(l,n)}),d.forEach((e,t)=>{const n=`%%%INLINECODE${t}%%%`;c=c.replace(n,`<code${i("code")}>${e}</code>`)}),c.trim()}function t(e,t,n){function r(e,r=""){if(t){const t=n[e]||"",o=r?`${t}; ${r}`:t;return o?` style="${o}"`:""}return` class="quikdown-${e}"`}return e=(e=(e=(e=(e=(e=e.replace(/\*\*(.+?)\*\*/g,`<strong${r("strong")}>$1</strong>`)).replace(/__(.+?)__/g,`<strong${r("strong")}>$1</strong>`)).replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,`<em${r("em")}>$1</em>`)).replace(/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g,`<em${r("em")}>$1</em>`)).replace(/~~(.+?)~~/g,`<del${r("del")}>$1</del>`)).replace(/`([^`]+)`/g,`<code${r("code")}>$1</code>`)}function n(e,n,r){function o(e,t=""){if(n){const n=r[e]||"",o=t?`${n}; ${t}`:n;return o?` style="${o}"`:""}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${o("table")}>\n`;return i.length>0&&(c+=`<thead${o("thead")}>\n`,i.forEach(e=>{c+=`<tr${o("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,r);c+=`<th${o("th",i)}>${a}</th>\n`}),c+="</tr>\n"}),c+="</thead>\n"),a.length>0&&(c+=`<tbody${o("tbody")}>\n`,a.forEach(e=>{c+=`<tr${o("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,r);c+=`<td${o("td",i)}>${a}</td>\n`}),c+="</tr>\n"}),c+="</tbody>\n"),c+="</table>",c}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,r]of Object.entries(e))r&&(t+=`.quikdown-${n} { ${r} }\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);export{e as default};
7
+ 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:i,inline_styles:a=!1}=l,c=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}"`}}(a,o);function p(e){return e.replace(/[&<>"']/g,e=>n[e])}function g(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 f=r;const d=[],h=[];f=f.replace(/^(```|~~~)([^\n]*)\n([\s\S]*?)^\1$/gm,(e,n,o,r)=>{const l=`${t}${d.length}§`,s=o?o.trim():"";return i&&"function"==typeof i?d.push({lang:s,code:r.trimEnd(),custom:!0}):d.push({lang:s,code:p(r.trimEnd()),custom:!1}),l}),f=f.replace(/`([^`]+)`/g,(e,t)=>{const n=`§IC${h.length}§`;return h.push(p(t)),n}),f=p(f),f=function(e,t){const n=e.split("\n"),o=[];let r=!1,l=[];for(let e=0;e<n.length;e++){const i=n[e].trim();if(i.includes("|")&&(i.startsWith("|")||/[^\\|]/.test(i)))r||(r=!0,l=[]),l.push(i);else{if(r){const e=s(l,t);e?o.push(e):o.push(...l),r=!1,l=[]}o.push(n[e])}}if(r&&l.length>0){const e=s(l,t);e?o.push(e):o.push(...l)}return o.join("\n")}(f,c),f=f.replace(/^(#{1,6})\s+(.+?)\s*#*$/gm,(e,t,n)=>{const o=t.length;return`<h${o}${c("h"+o)}>${n}</h${o}>`}),f=f.replace(/^&gt;\s+(.+)$/gm,`<blockquote${c("blockquote")}>$1</blockquote>`),f=f.replace(/<\/blockquote>\n<blockquote>/g,"\n"),f=f.replace(/^---+$/gm,`<hr${c("hr")}>`),f=function(t,n,o){const r=t.split("\n"),l=[];let s=[];for(let t=0;t<r.length;t++){const i=r[t],a=i.match(/^(\s*)([*\-+]|\d+\.)\s+(.+)$/);if(a){const[,t,r,i]=a,c=Math.floor(t.length/2),p=/^\d+\./.test(r),g=p?"ol":"ul";let f=i,d="";const h=i.match(/^\[([x ])\]\s+(.*)$/i);if(h&&!p){const[,t,n]=h,r="x"===t.toLowerCase();f=`<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(;s.length>c+1;){const e=s.pop();l.push(`</${e.type}>`)}if(s.length===c)s.push({type:g,level:c}),l.push(`<${g}${n(g)}>`);else if(s.length===c+1){const e=s[s.length-1];e.type!==g&&(l.push(`</${e.type}>`),s.pop(),s.push({type:g,level:c}),l.push(`<${g}${n(g)}>`))}const u=d||n("li");l.push(`<li${u}>${f}</li>`)}else{for(;s.length>0;){const e=s.pop();l.push(`</${e.type}>`)}l.push(i)}}for(;s.length>0;){const e=s.pop();l.push(`</${e.type}>`)}return l.join("\n")}(f,c,a),f=f.replace(/!\[([^\]]*)\]\(([^)]+)\)/g,(e,t,n)=>{const o=g(n,l.allow_unsafe_urls);return`<img${c("img")} src="${o}" alt="${t}">`}),f=f.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(e,t,n)=>{const o=g(n,l.allow_unsafe_urls),r=/^https?:\/\//i.test(o)?' rel="noopener noreferrer"':"";return`<a${c("a")} href="${o}"${r}>${t}</a>`}),f=f.replace(/(^|\s)(https?:\/\/[^\s<]+)/g,(e,t,n)=>{const o=g(n,l.allow_unsafe_urls);return`${t}<a${c("a")} href="${o}" rel="noopener noreferrer">${n}</a>`});[[/\*\*(.+?)\*\*/g,"strong"],[/__(.+?)__/g,"strong"],[/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g,"em"],[/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g,"em"],[/~~(.+?)~~/g,"del"]].forEach(([e,t])=>{f=f.replace(e,`<${t}${c(t)}>$1</${t}>`)}),f=f.replace(/ $/gm,`<br${c("br")}>`),f=f.replace(/\n\n+/g,"</p><p>"),f="<p>"+f+"</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])=>{f=f.replace(e,t)}),d.forEach((e,n)=>{let o;if(e.custom&&i){if(o=i(e.code,e.lang),void 0===o){const t=!a&&e.lang?` class="language-${e.lang}"`:"",n=a?c("code"):t;o=`<pre${c("pre")}><code${n}>${p(e.code)}</code></pre>`}}else{const t=!a&&e.lang?` class="language-${e.lang}"`:"",n=a?c("code"):t;o=`<pre${c("pre")}><code${n}>${e.code}</code></pre>`}const r=`${t}${n}§`;f=f.replace(r,o)}),h.forEach((e,t)=>{const n=`§IC${t}§`;f=f.replace(n,`<code${c("code")}>${e}</code>`)}),f.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 s(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),s=e[n].trim().replace(/^\|/,"").replace(/\|$/,"").split("|").map(e=>{const t=e.trim();return t.startsWith(":")&&t.endsWith(":")?"center":t.endsWith(":")?"right":"left"});let i=`<table${t("table")}>\n`;return o.length>0&&(i+=`<thead${t("thead")}>\n`,o.forEach(e=>{i+=`<tr${t("tr")}>\n`;e.trim().replace(/^\|/,"").replace(/\|$/,"").split("|").forEach((e,n)=>{const o=s[n]&&"left"!==s[n]?`text-align:${s[n]}`:"",r=l(e.trim(),t);i+=`<th${t("th",o)}>${r}</th>\n`}),i+="</tr>\n"}),i+="</thead>\n"),r.length>0&&(i+=`<tbody${t("tbody")}>\n`,r.forEach(e=>{i+=`<tr${t("tr")}>\n`;e.trim().replace(/^\|/,"").replace(/\|$/,"").split("|").forEach((e,n)=>{const o=s[n]&&"left"!==s[n]?`text-align:${s[n]}`:"",r=l(e.trim(),t);i+=`<td${t("td",o)}>${r}</td>\n`}),i+="</tr>\n"}),i+="</tbody>\n"),i+="</table>",i}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 s="";for(const[o,i]of Object.entries(n))if(i){let n=i;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}`)}s+=`.${e}${o} { ${n} }\n`}return s},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);export{r as default};
8
8
  //# sourceMappingURL=quikdown.esm.min.js.map