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.
- package/README.md +114 -17
- package/dist/quikdown-lex.cjs +810 -0
- package/dist/quikdown-lex.esm.js +808 -0
- package/dist/quikdown-lex.esm.min.js +8 -0
- package/dist/quikdown-lex.esm.min.js.map +1 -0
- package/dist/quikdown-lex.umd.js +816 -0
- package/dist/quikdown-lex.umd.min.js +8 -0
- package/dist/quikdown-lex.umd.min.js.map +1 -0
- package/dist/quikdown.cjs +164 -169
- package/dist/quikdown.d.ts +70 -0
- package/dist/quikdown.dark.css +115 -56
- package/dist/quikdown.dark.min.css +2 -0
- package/dist/quikdown.esm.js +164 -169
- package/dist/quikdown.esm.min.js +2 -2
- package/dist/quikdown.esm.min.js.map +1 -1
- package/dist/quikdown.light.css +84 -52
- package/dist/quikdown.light.min.css +2 -0
- package/dist/quikdown.umd.js +164 -169
- package/dist/quikdown.umd.min.js +2 -2
- package/dist/quikdown.umd.min.js.map +1 -1
- package/package.json +8 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quikdown.esm.min.js","sources":["../src/quikdown.js","../src/quikdown_version.js"],"sourcesContent":["/**\n * quikdown - A minimal markdown parser optimized for chat/LLM output\n * Supports tables, code blocks, lists, and common formatting\n * @param {string} markdown - The markdown source text\n * @param {Object} options - Optional configuration object\n * @param {Function} options.fence_plugin - Custom renderer for fenced code blocks\n * (content, fence_string) => html string\n * @param {boolean} options.inline_styles - If true, uses inline styles instead of classes\n * @returns {string} - The rendered HTML\n */\n\nimport quikdownVersion from './quikdown_version.js';\n\nfunction quikdown(markdown, options = {}) {\n if (!markdown || typeof markdown !== 'string') {\n return '';\n }\n \n const { fence_plugin, inline_styles = false } = options;\n\n // Style definitions - minimal, matching emitStyles\n const styles = {\n h1: 'font-size: 2em; font-weight: 600; margin: 0.67em 0; text-align: left',\n h2: 'font-size: 1.5em; font-weight: 600; margin: 0.83em 0',\n h3: 'font-size: 1.25em; font-weight: 600; margin: 1em 0',\n h4: 'font-size: 1em; font-weight: 600; margin: 1.33em 0',\n h5: 'font-size: 0.875em; font-weight: 600; margin: 1.67em 0',\n h6: 'font-size: 0.85em; font-weight: 600; margin: 2em 0',\n pre: 'background: #f4f4f4; padding: 10px; border-radius: 4px; overflow-x: auto; margin: 1em 0',\n code: 'background: #f0f0f0; padding: 2px 4px; border-radius: 3px; font-family: monospace',\n blockquote: 'border-left: 4px solid #ddd; margin-left: 0; padding-left: 1em',\n table: 'border-collapse: collapse; width: 100%; margin: 1em 0',\n thead: '',\n tbody: '',\n tr: '',\n th: 'border: 1px solid #ddd; padding: 8px; background-color: #f2f2f2; font-weight: bold; text-align: left',\n td: 'border: 1px solid #ddd; padding: 8px; text-align: left',\n hr: 'border: none; border-top: 1px solid #ddd; margin: 1em 0',\n img: 'max-width: 100%; height: auto',\n a: 'color: #0066cc; text-decoration: underline',\n strong: 'font-weight: bold',\n em: 'font-style: italic',\n del: 'text-decoration: line-through',\n ul: 'margin: 0.5em 0; padding-left: 2em',\n ol: 'margin: 0.5em 0; padding-left: 2em',\n li: 'margin: 0.25em 0',\n br: ''\n };\n\n // Helper to get class or style attribute\n function getAttr(tag, additionalStyle = '') {\n if (inline_styles) {\n const style = styles[tag] || '';\n const fullStyle = additionalStyle ? `${style}; ${additionalStyle}` : style;\n return fullStyle ? ` style=\"${fullStyle}\"` : '';\n } else {\n return ` class=\"quikdown-${tag}\"`;\n }\n }\n\n // Escape HTML entities to prevent XSS\n function escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return text.replace(/[&<>\"']/g, m => map[m]);\n }\n \n // Sanitize URLs to prevent XSS attacks\n function sanitizeUrl(url, allowUnsafe = false) {\n if (!url) return '';\n \n // If unsafe URLs are explicitly allowed, return as-is\n if (allowUnsafe) return url;\n \n // Trim and lowercase for checking\n const trimmedUrl = url.trim();\n const lowerUrl = trimmedUrl.toLowerCase();\n \n // Block dangerous protocols\n const dangerousProtocols = ['javascript:', 'vbscript:', 'data:'];\n \n for (const protocol of dangerousProtocols) {\n if (lowerUrl.startsWith(protocol)) {\n // Exception: Allow data:image/* for images\n if (protocol === 'data:' && lowerUrl.startsWith('data:image/')) {\n return trimmedUrl;\n }\n // Return safe empty link for dangerous protocols\n return '#';\n }\n }\n \n return trimmedUrl;\n }\n\n // Process the markdown in phases\n let html = markdown;\n \n // Phase 1: Extract and protect code blocks and inline code\n const codeBlocks = [];\n const inlineCodes = [];\n \n // Extract fenced code blocks first (supports both ``` and ~~~)\n // Match paired fences - ``` with ``` and ~~~ with ~~~\n // Fence must be at start of line\n html = html.replace(/^(```|~~~)([^\\n]*)\\n([\\s\\S]*?)^\\1$/gm, (match, fence, lang, code) => {\n const placeholder = `%%%CODEBLOCK${codeBlocks.length}%%%`;\n \n // Trim the language specification\n const langTrimmed = lang ? lang.trim() : '';\n \n // If custom fence plugin is provided, use it\n if (fence_plugin && typeof fence_plugin === 'function') {\n codeBlocks.push({\n lang: langTrimmed,\n code: code.trimEnd(),\n custom: true\n });\n } else {\n codeBlocks.push({\n lang: langTrimmed,\n code: escapeHtml(code.trimEnd()),\n custom: false\n });\n }\n return placeholder;\n });\n \n // Extract inline code\n html = html.replace(/`([^`]+)`/g, (match, code) => {\n const placeholder = `%%%INLINECODE${inlineCodes.length}%%%`;\n inlineCodes.push(escapeHtml(code));\n return placeholder;\n });\n \n // Now escape HTML in the rest of the content\n html = escapeHtml(html);\n \n // Phase 2: Process block elements\n \n // Process tables\n html = processTable(html, inline_styles, styles);\n \n // Process headings (supports optional trailing #'s)\n html = html.replace(/^(#{1,6})\\s+(.+?)\\s*#*$/gm, (match, hashes, content) => {\n const level = hashes.length;\n return `<h${level}${getAttr('h' + level)}>${content}</h${level}>`;\n });\n \n // Process blockquotes (must handle escaped > since we already escaped HTML)\n html = html.replace(/^>\\s+(.+)$/gm, `<blockquote${getAttr('blockquote')}>$1</blockquote>`);\n // Merge consecutive blockquotes\n html = html.replace(/<\\/blockquote>\\n<blockquote>/g, '\\n');\n \n // Process horizontal rules\n html = html.replace(/^---+$/gm, `<hr${getAttr('hr')}>`);\n \n // Process lists\n html = processLists(html, inline_styles, styles);\n \n // Phase 3: Process inline elements\n \n // Images (must come before links, with URL sanitization)\n html = html.replace(/!\\[([^\\]]*)\\]\\(([^)]+)\\)/g, (match, alt, src) => {\n const sanitizedSrc = sanitizeUrl(src, options.allow_unsafe_urls);\n return `<img${getAttr('img')} src=\"${sanitizedSrc}\" alt=\"${alt}\">`;\n });\n \n // Links (with URL sanitization)\n html = html.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, text, href) => {\n // Sanitize URL to prevent XSS\n const sanitizedHref = sanitizeUrl(href, options.allow_unsafe_urls);\n const isExternal = /^https?:\\/\\//i.test(sanitizedHref);\n const rel = isExternal ? ' rel=\"noopener noreferrer\"' : '';\n return `<a${getAttr('a')} href=\"${sanitizedHref}\"${rel}>${text}</a>`;\n });\n \n // Autolinks - convert bare URLs to clickable links\n html = html.replace(/(^|\\s)(https?:\\/\\/[^\\s<]+)/g, (match, prefix, url) => {\n const sanitizedUrl = sanitizeUrl(url, options.allow_unsafe_urls);\n return `${prefix}<a${getAttr('a')} href=\"${sanitizedUrl}\" rel=\"noopener noreferrer\">${url}</a>`;\n });\n \n // Bold (must use non-greedy matching)\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, `<strong${getAttr('strong')}>$1</strong>`);\n html = html.replace(/__(.+?)__/g, `<strong${getAttr('strong')}>$1</strong>`);\n \n // Italic (must not match bold markers)\n html = html.replace(/(?<!\\*)\\*(?!\\*)(.+?)(?<!\\*)\\*(?!\\*)/g, `<em${getAttr('em')}>$1</em>`);\n html = html.replace(/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g, `<em${getAttr('em')}>$1</em>`);\n \n // Strikethrough\n html = html.replace(/~~(.+?)~~/g, `<del${getAttr('del')}>$1</del>`);\n \n // Line breaks (two spaces at end of line)\n html = html.replace(/ $/gm, `<br${getAttr('br')}>`);\n \n // Paragraphs (double newlines)\n html = html.replace(/\\n\\n+/g, '</p><p>');\n html = '<p>' + html + '</p>';\n \n // Clean up empty paragraphs and unwrap block elements (account for attributes)\n html = html.replace(/<p><\\/p>/g, '');\n html = html.replace(/<p>(<h[1-6][^>]*>)/g, '$1');\n html = html.replace(/(<\\/h[1-6]>)<\\/p>/g, '$1');\n html = html.replace(/<p>(<blockquote[^>]*>)/g, '$1');\n html = html.replace(/(<\\/blockquote>)<\\/p>/g, '$1');\n html = html.replace(/<p>(<ul[^>]*>|<ol[^>]*>)/g, '$1');\n html = html.replace(/(<\\/ul>|<\\/ol>)<\\/p>/g, '$1');\n html = html.replace(/<p>(<hr[^>]*>)<\\/p>/g, '$1');\n html = html.replace(/<p>(<table[^>]*>)/g, '$1');\n html = html.replace(/(<\\/table>)<\\/p>/g, '$1');\n html = html.replace(/<p>(<pre[^>]*>)/g, '$1');\n html = html.replace(/(<\\/pre>)<\\/p>/g, '$1');\n // Also unwrap code block placeholders\n html = html.replace(/<p>(%%%CODEBLOCK\\d+%%%)<\\/p>/g, '$1');\n \n // Phase 4: Restore code blocks and inline code\n \n // Restore code blocks\n codeBlocks.forEach((block, i) => {\n let replacement;\n \n if (block.custom && fence_plugin) {\n // Use custom fence plugin\n replacement = fence_plugin(block.code, block.lang);\n // If plugin returns undefined, fall back to default rendering\n if (replacement === undefined) {\n const langClass = !inline_styles && block.lang ? ` class=\"language-${block.lang}\"` : '';\n const codeAttr = inline_styles ? getAttr('code') : langClass;\n replacement = `<pre${getAttr('pre')}><code${codeAttr}>${escapeHtml(block.code)}</code></pre>`;\n }\n } else {\n // Default rendering\n const langClass = !inline_styles && block.lang ? ` class=\"language-${block.lang}\"` : '';\n const codeAttr = inline_styles ? getAttr('code') : langClass;\n replacement = `<pre${getAttr('pre')}><code${codeAttr}>${block.code}</code></pre>`;\n }\n \n const placeholder = `%%%CODEBLOCK${i}%%%`;\n html = html.replace(placeholder, replacement);\n });\n \n // Restore inline code\n inlineCodes.forEach((code, i) => {\n const placeholder = `%%%INLINECODE${i}%%%`;\n html = html.replace(placeholder, `<code${getAttr('code')}>${code}</code>`);\n });\n \n return html.trim();\n}\n\n/**\n * Process inline markdown formatting\n */\nfunction processInlineMarkdown(text, inline_styles, styles) {\n // Helper to get attributes\n function getAttr(tag, additionalStyle = '') {\n if (inline_styles) {\n const style = styles[tag] || '';\n const fullStyle = additionalStyle ? `${style}; ${additionalStyle}` : style;\n return fullStyle ? ` style=\"${fullStyle}\"` : '';\n } else {\n return ` class=\"quikdown-${tag}\"`;\n }\n }\n \n // Process bold\n text = text.replace(/\\*\\*(.+?)\\*\\*/g, `<strong${getAttr('strong')}>$1</strong>`);\n text = text.replace(/__(.+?)__/g, `<strong${getAttr('strong')}>$1</strong>`);\n \n // Process italic (must not match bold markers)\n text = text.replace(/(?<!\\*)\\*(?!\\*)(.+?)(?<!\\*)\\*(?!\\*)/g, `<em${getAttr('em')}>$1</em>`);\n text = text.replace(/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g, `<em${getAttr('em')}>$1</em>`);\n \n // Process strikethrough\n text = text.replace(/~~(.+?)~~/g, `<del${getAttr('del')}>$1</del>`);\n \n // Process inline code\n text = text.replace(/`([^`]+)`/g, `<code${getAttr('code')}>$1</code>`);\n \n return text;\n}\n\n/**\n * Process markdown tables\n */\nfunction processTable(text, inline_styles, styles) {\n const lines = text.split('\\n');\n const result = [];\n let inTable = false;\n let tableLines = [];\n \n for (let i = 0; i < lines.length; i++) {\n const line = lines[i].trim();\n \n // Check if this line looks like a table row (with or without trailing |)\n if (line.includes('|') && (line.startsWith('|') || /[^\\\\|]/.test(line))) {\n if (!inTable) {\n inTable = true;\n tableLines = [];\n }\n tableLines.push(line);\n } else {\n // Not a table line\n if (inTable) {\n // Process the accumulated table\n const tableHtml = buildTable(tableLines, inline_styles, styles);\n if (tableHtml) {\n result.push(tableHtml);\n } else {\n // Not a valid table, restore original lines\n result.push(...tableLines);\n }\n inTable = false;\n tableLines = [];\n }\n result.push(lines[i]);\n }\n }\n \n // Handle table at end of text\n if (inTable && tableLines.length > 0) {\n const tableHtml = buildTable(tableLines, inline_styles, styles);\n if (tableHtml) {\n result.push(tableHtml);\n } else {\n result.push(...tableLines);\n }\n }\n \n return result.join('\\n');\n}\n\n/**\n * Build an HTML table from markdown table lines\n */\nfunction buildTable(lines, inline_styles, styles) {\n // Helper to get attributes\n function getAttr(tag, additionalStyle = '') {\n if (inline_styles) {\n const style = styles[tag] || '';\n const fullStyle = additionalStyle ? `${style}; ${additionalStyle}` : style;\n return fullStyle ? ` style=\"${fullStyle}\"` : '';\n } else {\n return ` class=\"quikdown-${tag}\"`;\n }\n }\n \n if (lines.length < 2) return null;\n \n // Check for separator line (second line should be the separator)\n let separatorIndex = -1;\n for (let i = 1; i < lines.length; i++) {\n // Support separator with or without leading/trailing pipes\n if (/^\\|?[\\s\\-:|]+\\|?$/.test(lines[i]) && lines[i].includes('-')) {\n separatorIndex = i;\n break;\n }\n }\n \n if (separatorIndex === -1) return null;\n \n const headerLines = lines.slice(0, separatorIndex);\n const bodyLines = lines.slice(separatorIndex + 1);\n \n // Parse alignment from separator\n const separator = lines[separatorIndex];\n // Handle pipes at start/end or not\n const separatorCells = separator.trim().replace(/^\\|/, '').replace(/\\|$/, '').split('|');\n const alignments = separatorCells.map(cell => {\n const trimmed = cell.trim();\n if (trimmed.startsWith(':') && trimmed.endsWith(':')) return 'center';\n if (trimmed.endsWith(':')) return 'right';\n return 'left';\n });\n \n let html = `<table${getAttr('table')}>\\n`;\n \n // Build header\n if (headerLines.length > 0) {\n html += `<thead${getAttr('thead')}>\\n`;\n headerLines.forEach(line => {\n html += `<tr${getAttr('tr')}>\\n`;\n // Handle pipes at start/end or not\n const cells = line.trim().replace(/^\\|/, '').replace(/\\|$/, '').split('|');\n cells.forEach((cell, i) => {\n const alignStyle = alignments[i] && alignments[i] !== 'left' ? `text-align: ${alignments[i]}` : '';\n const processedCell = processInlineMarkdown(cell.trim(), inline_styles, styles);\n html += `<th${getAttr('th', alignStyle)}>${processedCell}</th>\\n`;\n });\n html += '</tr>\\n';\n });\n html += '</thead>\\n';\n }\n \n // Build body\n if (bodyLines.length > 0) {\n html += `<tbody${getAttr('tbody')}>\\n`;\n bodyLines.forEach(line => {\n html += `<tr${getAttr('tr')}>\\n`;\n // Handle pipes at start/end or not\n const cells = line.trim().replace(/^\\|/, '').replace(/\\|$/, '').split('|');\n cells.forEach((cell, i) => {\n const alignStyle = alignments[i] && alignments[i] !== 'left' ? `text-align: ${alignments[i]}` : '';\n const processedCell = processInlineMarkdown(cell.trim(), inline_styles, styles);\n html += `<td${getAttr('td', alignStyle)}>${processedCell}</td>\\n`;\n });\n html += '</tr>\\n';\n });\n html += '</tbody>\\n';\n }\n \n html += '</table>';\n return html;\n}\n\n/**\n * Process markdown lists (ordered and unordered)\n */\nfunction processLists(text, inline_styles, styles) {\n // Helper to get attributes\n function getAttr(tag, additionalStyle = '') {\n if (inline_styles) {\n const style = styles[tag] || '';\n const fullStyle = additionalStyle ? `${style}; ${additionalStyle}` : style;\n return fullStyle ? ` style=\"${fullStyle}\"` : '';\n } else {\n return ` class=\"quikdown-${tag}\"`;\n }\n }\n \n const lines = text.split('\\n');\n const result = [];\n let listStack = []; // Track nested lists\n \n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const match = line.match(/^(\\s*)([*\\-+]|\\d+\\.)\\s+(.+)$/);\n \n if (match) {\n const [, indent, marker, content] = match;\n const level = Math.floor(indent.length / 2);\n const isOrdered = /^\\d+\\./.test(marker);\n const listType = isOrdered ? 'ol' : 'ul';\n \n // Check for task list items\n let listItemContent = content;\n let taskListClass = '';\n const taskMatch = content.match(/^\\[([x ])\\]\\s+(.*)$/i);\n if (taskMatch && !isOrdered) {\n const [, checked, taskContent] = taskMatch;\n const isChecked = checked.toLowerCase() === 'x';\n const checkboxAttr = inline_styles \n ? ' style=\"margin-right: 0.5em\"' \n : ' class=\"quikdown-task-checkbox\"';\n listItemContent = `<input type=\"checkbox\"${checkboxAttr}${isChecked ? ' checked' : ''} disabled> ${taskContent}`;\n taskListClass = inline_styles ? ' style=\"list-style: none\"' : ' class=\"quikdown-task-item\"';\n }\n \n // Close deeper levels\n while (listStack.length > level + 1) {\n const list = listStack.pop();\n result.push(`</${list.type}>`);\n }\n \n // Open new level if needed\n if (listStack.length === level) {\n // Need to open a new list\n listStack.push({ type: listType, level });\n result.push(`<${listType}${getAttr(listType)}>`);\n } else if (listStack.length === level + 1) {\n // Check if we need to switch list type\n const currentList = listStack[listStack.length - 1];\n if (currentList.type !== listType) {\n result.push(`</${currentList.type}>`);\n listStack.pop();\n listStack.push({ type: listType, level });\n result.push(`<${listType}${getAttr(listType)}>`);\n }\n }\n \n const liAttr = taskListClass || getAttr('li');\n result.push(`<li${liAttr}>${listItemContent}</li>`);\n } else {\n // Not a list item, close all lists\n while (listStack.length > 0) {\n const list = listStack.pop();\n result.push(`</${list.type}>`);\n }\n result.push(line);\n }\n }\n \n // Close any remaining lists\n while (listStack.length > 0) {\n const list = listStack.pop();\n result.push(`</${list.type}>`);\n }\n \n return result.join('\\n');\n}\n\n/**\n * Emit CSS styles for quikdown elements\n * @returns {string} CSS string with quikdown styles\n */\nquikdown.emitStyles = function() {\n const styles = {\n h1: 'font-size: 2em; font-weight: 600; margin: 0.67em 0; text-align: left',\n h2: 'font-size: 1.5em; font-weight: 600; margin: 0.83em 0',\n h3: 'font-size: 1.25em; font-weight: 600; margin: 1em 0',\n h4: 'font-size: 1em; font-weight: 600; margin: 1.33em 0',\n h5: 'font-size: 0.875em; font-weight: 600; margin: 1.67em 0',\n h6: 'font-size: 0.85em; font-weight: 600; margin: 2em 0',\n pre: 'background: #f4f4f4; padding: 10px; border-radius: 4px; overflow-x: auto; margin: 1em 0',\n code: 'background: #f0f0f0; padding: 2px 4px; border-radius: 3px; font-family: monospace',\n blockquote: 'border-left: 4px solid #ddd; margin-left: 0; padding-left: 1em',\n table: 'border-collapse: collapse; width: 100%; margin: 1em 0',\n th: 'border: 1px solid #ddd; padding: 8px; background-color: #f2f2f2; font-weight: bold; text-align: left',\n td: 'border: 1px solid #ddd; padding: 8px; text-align: left',\n hr: 'border: none; border-top: 1px solid #ddd; margin: 1em 0',\n img: 'max-width: 100%; height: auto',\n a: 'color: #0066cc; text-decoration: underline',\n strong: 'font-weight: bold',\n em: 'font-style: italic',\n del: 'text-decoration: line-through',\n ul: 'margin: 0.5em 0; padding-left: 2em',\n ol: 'margin: 0.5em 0; padding-left: 2em',\n li: 'margin: 0.25em 0',\n 'task-item': 'list-style: none',\n 'task-checkbox': 'margin-right: 0.5em'\n };\n \n let css = '';\n for (const [tag, style] of Object.entries(styles)) {\n if (style) {\n css += `.quikdown-${tag} { ${style} }\\n`;\n }\n }\n \n return css;\n};\n\n/**\n * Configure quikdown with options and return a function\n * @param {Object} options - Configuration options\n * @returns {Function} Configured quikdown function\n */\nquikdown.configure = function(options) {\n return function(markdown) {\n return quikdown(markdown, options);\n };\n};\n\n/**\n * Version information\n */\nquikdown.version = quikdownVersion;\n\n// Export for both CommonJS and ES6\nif (typeof module !== 'undefined' && module.exports) {\n module.exports = quikdown;\n}\n\n// For browser global\nif (typeof window !== 'undefined') {\n window.quikdown = quikdown;\n}\n\nexport default quikdown;","// Auto-generated version file - DO NOT EDIT MANUALLY\n// This file is automatically updated by tools/updateVersion.js\n\nexport const quikdownVersion = \"1.0.2\";\n\nexport default quikdownVersion;"],"names":["quikdown","markdown","options","fence_plugin","inline_styles","styles","h1","h2","h3","h4","h5","h6","pre","code","blockquote","table","thead","tbody","tr","th","td","hr","img","a","strong","em","del","ul","ol","li","br","getAttr","tag","additionalStyle","style","fullStyle","escapeHtml","text","map","replace","m","sanitizeUrl","url","allowUnsafe","trimmedUrl","trim","lowerUrl","toLowerCase","dangerousProtocols","protocol","startsWith","html","codeBlocks","inlineCodes","match","fence","lang","placeholder","length","langTrimmed","push","trimEnd","custom","lines","split","result","inTable","tableLines","i","line","includes","test","tableHtml","buildTable","join","processTable","hashes","content","level","listStack","indent","marker","Math","floor","isOrdered","listType","listItemContent","taskListClass","taskMatch","checked","taskContent","isChecked","list","pop","type","currentList","liAttr","processLists","alt","src","sanitizedSrc","allow_unsafe_urls","href","sanitizedHref","rel","prefix","sanitizedUrl","forEach","block","replacement","undefined","langClass","codeAttr","processInlineMarkdown","separatorIndex","headerLines","slice","bodyLines","alignments","cell","trimmed","endsWith","alignStyle","processedCell","emitStyles","css","Object","entries","configure","version","module","exports","window"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"quikdown.esm.min.js","sources":["../src/quikdown.js"],"sourcesContent":["/**\n * quikdown - A minimal markdown parser optimized for chat/LLM output\n * Supports tables, code blocks, lists, and common formatting\n * @param {string} markdown - The markdown source text\n * @param {Object} options - Optional configuration object\n * @param {Function} options.fence_plugin - Custom renderer for fenced code blocks\n * (content, fence_string) => html string\n * @param {boolean} options.inline_styles - If true, uses inline styles instead of classes\n * @returns {string} - The rendered HTML\n */\n\n// Version will be injected at build time \nconst quikdownVersion = '__QUIKDOWN_VERSION__';\n\n// Constants for reuse\nconst CLASS_PREFIX = 'quikdown-';\nconst PLACEHOLDER_CB = '§CB';\nconst PLACEHOLDER_IC = '§IC';\n\n// Escape map at module level\nconst ESC_MAP = {'&':'&','<':'<','>':'>','\"':'"',\"'\":'''};\n\n// Single source of truth for all style definitions - optimized\nconst QUIKDOWN_STYLES = {\n h1: 'font-size:2em;font-weight:600;margin:.67em 0;text-align:left',\n h2: 'font-size:1.5em;font-weight:600;margin:.83em 0',\n h3: 'font-size:1.25em;font-weight:600;margin:1em 0',\n h4: 'font-size:1em;font-weight:600;margin:1.33em 0',\n h5: 'font-size:.875em;font-weight:600;margin:1.67em 0',\n h6: 'font-size:.85em;font-weight:600;margin:2em 0',\n pre: 'background:#f4f4f4;padding:10px;border-radius:4px;overflow-x:auto;margin:1em 0',\n code: 'background:#f0f0f0;padding:2px 4px;border-radius:3px;font-family:monospace',\n blockquote: 'border-left:4px solid #ddd;margin-left:0;padding-left:1em',\n table: 'border-collapse:collapse;width:100%;margin:1em 0',\n th: 'border:1px solid #ddd;padding:8px;background-color:#f2f2f2;font-weight:bold;text-align:left',\n td: 'border:1px solid #ddd;padding:8px;text-align:left',\n hr: 'border:none;border-top:1px solid #ddd;margin:1em 0',\n img: 'max-width:100%;height:auto',\n a: 'color:#06c;text-decoration:underline',\n strong: 'font-weight:bold',\n em: 'font-style:italic',\n del: 'text-decoration:line-through',\n ul: 'margin:.5em 0;padding-left:2em',\n ol: 'margin:.5em 0;padding-left:2em',\n li: 'margin:.25em 0',\n // Task list specific styles\n 'task-item': 'list-style:none',\n 'task-checkbox': 'margin-right:.5em'\n};\n\n// Factory function to create getAttr for a given context\nfunction createGetAttr(inline_styles, styles) {\n return function(tag, additionalStyle = '') {\n if (inline_styles) {\n const style = styles[tag];\n if (!style && !additionalStyle) return '';\n const fullStyle = additionalStyle ? (style ? `${style};${additionalStyle}` : additionalStyle) : style;\n return ` style=\"${fullStyle}\"`;\n } else {\n return ` class=\"${CLASS_PREFIX}${tag}\"`;\n }\n };\n}\n\nfunction quikdown(markdown, options = {}) {\n if (!markdown || typeof markdown !== 'string') {\n return '';\n }\n \n const { fence_plugin, inline_styles = false } = options;\n const styles = QUIKDOWN_STYLES; // Use module-level styles\n const getAttr = createGetAttr(inline_styles, styles); // Create getAttr once\n\n // Escape HTML entities to prevent XSS\n function escapeHtml(text) {\n return text.replace(/[&<>\"']/g, m => ESC_MAP[m]);\n }\n \n // Sanitize URLs to prevent XSS attacks\n function sanitizeUrl(url, allowUnsafe = false) {\n if (!url) return '';\n \n // If unsafe URLs are explicitly allowed, return as-is\n if (allowUnsafe) return url;\n \n const trimmedUrl = url.trim();\n const lowerUrl = trimmedUrl.toLowerCase();\n \n // Block dangerous protocols\n const dangerousProtocols = ['javascript:', 'vbscript:', 'data:'];\n \n for (const protocol of dangerousProtocols) {\n if (lowerUrl.startsWith(protocol)) {\n // Exception: Allow data:image/* for images\n if (protocol === 'data:' && lowerUrl.startsWith('data:image/')) {\n return trimmedUrl;\n }\n // Return safe empty link for dangerous protocols\n return '#';\n }\n }\n \n return trimmedUrl;\n }\n\n // Process the markdown in phases\n let html = markdown;\n \n // Phase 1: Extract and protect code blocks and inline code\n const codeBlocks = [];\n const inlineCodes = [];\n \n // Extract fenced code blocks first (supports both ``` and ~~~)\n // Match paired fences - ``` with ``` and ~~~ with ~~~\n // Fence must be at start of line\n html = html.replace(/^(```|~~~)([^\\n]*)\\n([\\s\\S]*?)^\\1$/gm, (match, fence, lang, code) => {\n const placeholder = `${PLACEHOLDER_CB}${codeBlocks.length}§`;\n \n // Trim the language specification\n const langTrimmed = lang ? lang.trim() : '';\n \n // If custom fence plugin is provided, use it\n if (fence_plugin && typeof fence_plugin === 'function') {\n codeBlocks.push({\n lang: langTrimmed,\n code: code.trimEnd(),\n custom: true\n });\n } else {\n codeBlocks.push({\n lang: langTrimmed,\n code: escapeHtml(code.trimEnd()),\n custom: false\n });\n }\n return placeholder;\n });\n \n // Extract inline code\n html = html.replace(/`([^`]+)`/g, (match, code) => {\n const placeholder = `${PLACEHOLDER_IC}${inlineCodes.length}§`;\n inlineCodes.push(escapeHtml(code));\n return placeholder;\n });\n \n // Now escape HTML in the rest of the content\n html = escapeHtml(html);\n \n // Phase 2: Process block elements\n \n // Process tables\n html = processTable(html, getAttr);\n \n // Process headings (supports optional trailing #'s)\n html = html.replace(/^(#{1,6})\\s+(.+?)\\s*#*$/gm, (match, hashes, content) => {\n const level = hashes.length;\n return `<h${level}${getAttr('h' + level)}>${content}</h${level}>`;\n });\n \n // Process blockquotes (must handle escaped > since we already escaped HTML)\n html = html.replace(/^>\\s+(.+)$/gm, `<blockquote${getAttr('blockquote')}>$1</blockquote>`);\n // Merge consecutive blockquotes\n html = html.replace(/<\\/blockquote>\\n<blockquote>/g, '\\n');\n \n // Process horizontal rules\n html = html.replace(/^---+$/gm, `<hr${getAttr('hr')}>`);\n \n // Process lists\n html = processLists(html, getAttr, inline_styles);\n \n // Phase 3: Process inline elements\n \n // Images (must come before links, with URL sanitization)\n html = html.replace(/!\\[([^\\]]*)\\]\\(([^)]+)\\)/g, (match, alt, src) => {\n const sanitizedSrc = sanitizeUrl(src, options.allow_unsafe_urls);\n return `<img${getAttr('img')} src=\"${sanitizedSrc}\" alt=\"${alt}\">`;\n });\n \n // Links (with URL sanitization)\n html = html.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, text, href) => {\n // Sanitize URL to prevent XSS\n const sanitizedHref = sanitizeUrl(href, options.allow_unsafe_urls);\n const isExternal = /^https?:\\/\\//i.test(sanitizedHref);\n const rel = isExternal ? ' rel=\"noopener noreferrer\"' : '';\n return `<a${getAttr('a')} href=\"${sanitizedHref}\"${rel}>${text}</a>`;\n });\n \n // Autolinks - convert bare URLs to clickable links\n html = html.replace(/(^|\\s)(https?:\\/\\/[^\\s<]+)/g, (match, prefix, url) => {\n const sanitizedUrl = sanitizeUrl(url, options.allow_unsafe_urls);\n return `${prefix}<a${getAttr('a')} href=\"${sanitizedUrl}\" rel=\"noopener noreferrer\">${url}</a>`;\n });\n \n // Process inline formatting (bold, italic, strikethrough)\n const inlinePatterns = [\n [/\\*\\*(.+?)\\*\\*/g, 'strong'],\n [/__(.+?)__/g, 'strong'],\n [/(?<!\\*)\\*(?!\\*)(.+?)(?<!\\*)\\*(?!\\*)/g, 'em'],\n [/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g, 'em'],\n [/~~(.+?)~~/g, 'del']\n ];\n \n inlinePatterns.forEach(([pattern, tag]) => {\n html = html.replace(pattern, `<${tag}${getAttr(tag)}>$1</${tag}>`);\n });\n \n // Line breaks (two spaces at end of line)\n html = html.replace(/ $/gm, `<br${getAttr('br')}>`);\n \n // Paragraphs (double newlines)\n html = html.replace(/\\n\\n+/g, '</p><p>');\n html = '<p>' + html + '</p>';\n \n // Clean up empty paragraphs and unwrap block elements\n const cleanupPatterns = [\n [/<p><\\/p>/g, ''],\n [/<p>(<h[1-6][^>]*>)/g, '$1'],\n [/(<\\/h[1-6]>)<\\/p>/g, '$1'],\n [/<p>(<blockquote[^>]*>)/g, '$1'],\n [/(<\\/blockquote>)<\\/p>/g, '$1'],\n [/<p>(<ul[^>]*>|<ol[^>]*>)/g, '$1'],\n [/(<\\/ul>|<\\/ol>)<\\/p>/g, '$1'],\n [/<p>(<hr[^>]*>)<\\/p>/g, '$1'],\n [/<p>(<table[^>]*>)/g, '$1'],\n [/(<\\/table>)<\\/p>/g, '$1'],\n [/<p>(<pre[^>]*>)/g, '$1'],\n [/(<\\/pre>)<\\/p>/g, '$1'],\n [new RegExp(`<p>(${PLACEHOLDER_CB}\\\\d+§)<\\/p>`, 'g'), '$1']\n ];\n \n cleanupPatterns.forEach(([pattern, replacement]) => {\n html = html.replace(pattern, replacement);\n });\n \n // Phase 4: Restore code blocks and inline code\n \n // Restore code blocks\n codeBlocks.forEach((block, i) => {\n let replacement;\n \n if (block.custom && fence_plugin) {\n // Use custom fence plugin\n replacement = fence_plugin(block.code, block.lang);\n // If plugin returns undefined, fall back to default rendering\n if (replacement === undefined) {\n const langClass = !inline_styles && block.lang ? ` class=\"language-${block.lang}\"` : '';\n const codeAttr = inline_styles ? getAttr('code') : langClass;\n replacement = `<pre${getAttr('pre')}><code${codeAttr}>${escapeHtml(block.code)}</code></pre>`;\n }\n } else {\n // Default rendering\n const langClass = !inline_styles && block.lang ? ` class=\"language-${block.lang}\"` : '';\n const codeAttr = inline_styles ? getAttr('code') : langClass;\n replacement = `<pre${getAttr('pre')}><code${codeAttr}>${block.code}</code></pre>`;\n }\n \n const placeholder = `${PLACEHOLDER_CB}${i}§`;\n html = html.replace(placeholder, replacement);\n });\n \n // Restore inline code\n inlineCodes.forEach((code, i) => {\n const placeholder = `${PLACEHOLDER_IC}${i}§`;\n html = html.replace(placeholder, `<code${getAttr('code')}>${code}</code>`);\n });\n \n return html.trim();\n}\n\n/**\n * Process inline markdown formatting\n */\nfunction processInlineMarkdown(text, getAttr) {\n \n // Process inline formatting patterns\n const patterns = [\n [/\\*\\*(.+?)\\*\\*/g, 'strong'],\n [/__(.+?)__/g, 'strong'],\n [/(?<!\\*)\\*(?!\\*)(.+?)(?<!\\*)\\*(?!\\*)/g, 'em'],\n [/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/g, 'em'],\n [/~~(.+?)~~/g, 'del'],\n [/`([^`]+)`/g, 'code']\n ];\n \n patterns.forEach(([pattern, tag]) => {\n text = text.replace(pattern, `<${tag}${getAttr(tag)}>$1</${tag}>`);\n });\n \n return text;\n}\n\n/**\n * Process markdown tables\n */\nfunction processTable(text, getAttr) {\n const lines = text.split('\\n');\n const result = [];\n let inTable = false;\n let tableLines = [];\n \n for (let i = 0; i < lines.length; i++) {\n const line = lines[i].trim();\n \n // Check if this line looks like a table row (with or without trailing |)\n if (line.includes('|') && (line.startsWith('|') || /[^\\\\|]/.test(line))) {\n if (!inTable) {\n inTable = true;\n tableLines = [];\n }\n tableLines.push(line);\n } else {\n // Not a table line\n if (inTable) {\n // Process the accumulated table\n const tableHtml = buildTable(tableLines, getAttr);\n if (tableHtml) {\n result.push(tableHtml);\n } else {\n // Not a valid table, restore original lines\n result.push(...tableLines);\n }\n inTable = false;\n tableLines = [];\n }\n result.push(lines[i]);\n }\n }\n \n // Handle table at end of text\n if (inTable && tableLines.length > 0) {\n const tableHtml = buildTable(tableLines, getAttr);\n if (tableHtml) {\n result.push(tableHtml);\n } else {\n result.push(...tableLines);\n }\n }\n \n return result.join('\\n');\n}\n\n/**\n * Build an HTML table from markdown table lines\n */\nfunction buildTable(lines, getAttr) {\n \n if (lines.length < 2) return null;\n \n // Check for separator line (second line should be the separator)\n let separatorIndex = -1;\n for (let i = 1; i < lines.length; i++) {\n // Support separator with or without leading/trailing pipes\n if (/^\\|?[\\s\\-:|]+\\|?$/.test(lines[i]) && lines[i].includes('-')) {\n separatorIndex = i;\n break;\n }\n }\n \n if (separatorIndex === -1) return null;\n \n const headerLines = lines.slice(0, separatorIndex);\n const bodyLines = lines.slice(separatorIndex + 1);\n \n // Parse alignment from separator\n const separator = lines[separatorIndex];\n // Handle pipes at start/end or not\n const separatorCells = separator.trim().replace(/^\\|/, '').replace(/\\|$/, '').split('|');\n const alignments = separatorCells.map(cell => {\n const trimmed = cell.trim();\n if (trimmed.startsWith(':') && trimmed.endsWith(':')) return 'center';\n if (trimmed.endsWith(':')) return 'right';\n return 'left';\n });\n \n let html = `<table${getAttr('table')}>\\n`;\n \n // Build header\n if (headerLines.length > 0) {\n html += `<thead${getAttr('thead')}>\\n`;\n headerLines.forEach(line => {\n html += `<tr${getAttr('tr')}>\\n`;\n // Handle pipes at start/end or not\n const cells = line.trim().replace(/^\\|/, '').replace(/\\|$/, '').split('|');\n cells.forEach((cell, i) => {\n const alignStyle = alignments[i] && alignments[i] !== 'left' ? `text-align:${alignments[i]}` : '';\n const processedCell = processInlineMarkdown(cell.trim(), getAttr);\n html += `<th${getAttr('th', alignStyle)}>${processedCell}</th>\\n`;\n });\n html += '</tr>\\n';\n });\n html += '</thead>\\n';\n }\n \n // Build body\n if (bodyLines.length > 0) {\n html += `<tbody${getAttr('tbody')}>\\n`;\n bodyLines.forEach(line => {\n html += `<tr${getAttr('tr')}>\\n`;\n // Handle pipes at start/end or not\n const cells = line.trim().replace(/^\\|/, '').replace(/\\|$/, '').split('|');\n cells.forEach((cell, i) => {\n const alignStyle = alignments[i] && alignments[i] !== 'left' ? `text-align:${alignments[i]}` : '';\n const processedCell = processInlineMarkdown(cell.trim(), getAttr);\n html += `<td${getAttr('td', alignStyle)}>${processedCell}</td>\\n`;\n });\n html += '</tr>\\n';\n });\n html += '</tbody>\\n';\n }\n \n html += '</table>';\n return html;\n}\n\n/**\n * Process markdown lists (ordered and unordered)\n */\nfunction processLists(text, getAttr, inline_styles) {\n \n const lines = text.split('\\n');\n const result = [];\n let listStack = []; // Track nested lists\n \n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n const match = line.match(/^(\\s*)([*\\-+]|\\d+\\.)\\s+(.+)$/);\n \n if (match) {\n const [, indent, marker, content] = match;\n const level = Math.floor(indent.length / 2);\n const isOrdered = /^\\d+\\./.test(marker);\n const listType = isOrdered ? 'ol' : 'ul';\n \n // Check for task list items\n let listItemContent = content;\n let taskListClass = '';\n const taskMatch = content.match(/^\\[([x ])\\]\\s+(.*)$/i);\n if (taskMatch && !isOrdered) {\n const [, checked, taskContent] = taskMatch;\n const isChecked = checked.toLowerCase() === 'x';\n const checkboxAttr = inline_styles \n ? ' style=\"margin-right:.5em\"' \n : ` class=\"${CLASS_PREFIX}task-checkbox\"`;\n listItemContent = `<input type=\"checkbox\"${checkboxAttr}${isChecked ? ' checked' : ''} disabled> ${taskContent}`;\n taskListClass = inline_styles ? ' style=\"list-style:none\"' : ` class=\"${CLASS_PREFIX}task-item\"`;\n }\n \n // Close deeper levels\n while (listStack.length > level + 1) {\n const list = listStack.pop();\n result.push(`</${list.type}>`);\n }\n \n // Open new level if needed\n if (listStack.length === level) {\n // Need to open a new list\n listStack.push({ type: listType, level });\n result.push(`<${listType}${getAttr(listType)}>`);\n } else if (listStack.length === level + 1) {\n // Check if we need to switch list type\n const currentList = listStack[listStack.length - 1];\n if (currentList.type !== listType) {\n result.push(`</${currentList.type}>`);\n listStack.pop();\n listStack.push({ type: listType, level });\n result.push(`<${listType}${getAttr(listType)}>`);\n }\n }\n \n const liAttr = taskListClass || getAttr('li');\n result.push(`<li${liAttr}>${listItemContent}</li>`);\n } else {\n // Not a list item, close all lists\n while (listStack.length > 0) {\n const list = listStack.pop();\n result.push(`</${list.type}>`);\n }\n result.push(line);\n }\n }\n \n // Close any remaining lists\n while (listStack.length > 0) {\n const list = listStack.pop();\n result.push(`</${list.type}>`);\n }\n \n return result.join('\\n');\n}\n\n/**\n * Emit CSS styles for quikdown elements\n * @param {string} prefix - Optional class prefix (default: 'quikdown-')\n * @param {string} theme - Optional theme: 'light' (default) or 'dark'\n * @returns {string} CSS string with quikdown styles\n */\nquikdown.emitStyles = function(prefix = 'quikdown-', theme = 'light') {\n const styles = QUIKDOWN_STYLES;\n \n // Define theme color overrides\n const themeOverrides = {\n dark: {\n '#f4f4f4': '#2a2a2a', // pre background\n '#f0f0f0': '#2a2a2a', // code background\n '#f2f2f2': '#2a2a2a', // th background\n '#ddd': '#3a3a3a', // borders\n '#06c': '#6db3f2', // links\n _textColor: '#e0e0e0'\n },\n light: {\n _textColor: '#333' // Explicit text color for light theme\n }\n };\n \n let css = '';\n for (const [tag, style] of Object.entries(styles)) {\n if (style) {\n let themedStyle = style;\n \n // Apply theme overrides if dark theme\n if (theme === 'dark' && themeOverrides.dark) {\n // Replace colors\n for (const [oldColor, newColor] of Object.entries(themeOverrides.dark)) {\n if (!oldColor.startsWith('_')) {\n themedStyle = themedStyle.replace(new RegExp(oldColor, 'g'), newColor);\n }\n }\n \n // Add text color for certain elements in dark theme\n const needsTextColor = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'td', 'li', 'blockquote'];\n if (needsTextColor.includes(tag)) {\n themedStyle += `;color:${themeOverrides.dark._textColor}`;\n }\n } else if (theme === 'light' && themeOverrides.light) {\n // Add explicit text color for light theme elements too\n const needsTextColor = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'td', 'li', 'blockquote'];\n if (needsTextColor.includes(tag)) {\n themedStyle += `;color:${themeOverrides.light._textColor}`;\n }\n }\n \n css += `.${prefix}${tag} { ${themedStyle} }\\n`;\n }\n }\n \n return css;\n};\n\n/**\n * Configure quikdown with options and return a function\n * @param {Object} options - Configuration options\n * @returns {Function} Configured quikdown function\n */\nquikdown.configure = function(options) {\n return function(markdown) {\n return quikdown(markdown, options);\n };\n};\n\n/**\n * Version information\n */\nquikdown.version = quikdownVersion;\n\n// Export for both CommonJS and ES6\nif (typeof module !== 'undefined' && module.exports) {\n module.exports = quikdown;\n}\n\n// For browser global\nif (typeof window !== 'undefined') {\n window.quikdown = quikdown;\n}\n\nexport default quikdown;"],"names":["CLASS_PREFIX","PLACEHOLDER_CB","ESC_MAP","QUIKDOWN_STYLES","h1","h2","h3","h4","h5","h6","pre","code","blockquote","table","th","td","hr","img","a","strong","em","del","ul","ol","li","quikdown","markdown","options","fence_plugin","inline_styles","getAttr","styles","tag","additionalStyle","style","createGetAttr","escapeHtml","text","replace","m","sanitizeUrl","url","allowUnsafe","trimmedUrl","trim","lowerUrl","toLowerCase","dangerousProtocols","protocol","startsWith","html","codeBlocks","inlineCodes","match","fence","lang","placeholder","length","langTrimmed","push","trimEnd","custom","lines","split","result","inTable","tableLines","i","line","includes","test","tableHtml","buildTable","join","processTable","hashes","content","level","listStack","indent","marker","Math","floor","isOrdered","listType","listItemContent","taskListClass","taskMatch","checked","taskContent","isChecked","list","pop","type","currentList","liAttr","processLists","alt","src","sanitizedSrc","allow_unsafe_urls","href","sanitizedHref","rel","prefix","sanitizedUrl","forEach","pattern","RegExp","replacement","block","undefined","langClass","codeAttr","processInlineMarkdown","separatorIndex","headerLines","slice","bodyLines","alignments","map","cell","trimmed","endsWith","alignStyle","processedCell","emitStyles","theme","themeOverrides","_textColor","css","Object","entries","themedStyle","oldColor","newColor","configure","version","module","exports","window"],"mappings":"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"}
|
package/dist/quikdown.light.css
CHANGED
|
@@ -1,48 +1,69 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* QuikDown Light Theme CSS
|
|
3
|
+
* Generated from quikdown.emitStyles('quikdown-', 'light')
|
|
4
|
+
*
|
|
5
|
+
* Theme with container-based scoping.
|
|
6
|
+
* Usage: <div class="quikdown-light">...content...</div>
|
|
7
|
+
*
|
|
8
|
+
* @generated 2025-08-17T11:14:25.790Z
|
|
9
|
+
* @source tools/generateThemeCSS.js
|
|
4
10
|
*/
|
|
5
11
|
|
|
6
|
-
/*
|
|
7
|
-
|
|
12
|
+
/* ============================================
|
|
13
|
+
QuikDown Light Theme Styles
|
|
14
|
+
All selectors scoped to .quikdown-light container
|
|
15
|
+
============================================ */
|
|
16
|
+
|
|
17
|
+
/* Primary heading */
|
|
18
|
+
.quikdown-light .quikdown-h1 {
|
|
8
19
|
font-size: 2em;
|
|
9
20
|
font-weight: 600;
|
|
10
21
|
margin: 0.67em 0;
|
|
11
22
|
text-align: left;
|
|
23
|
+
color: #333;
|
|
12
24
|
}
|
|
13
25
|
|
|
14
|
-
|
|
26
|
+
/* Secondary heading */
|
|
27
|
+
.quikdown-light .quikdown-h2 {
|
|
15
28
|
font-size: 1.5em;
|
|
16
29
|
font-weight: 600;
|
|
17
30
|
margin: 0.83em 0;
|
|
31
|
+
color: #333;
|
|
18
32
|
}
|
|
19
33
|
|
|
20
|
-
|
|
34
|
+
/* Tertiary heading */
|
|
35
|
+
.quikdown-light .quikdown-h3 {
|
|
21
36
|
font-size: 1.25em;
|
|
22
37
|
font-weight: 600;
|
|
23
38
|
margin: 1em 0;
|
|
39
|
+
color: #333;
|
|
24
40
|
}
|
|
25
41
|
|
|
26
|
-
|
|
42
|
+
/* Fourth level heading */
|
|
43
|
+
.quikdown-light .quikdown-h4 {
|
|
27
44
|
font-size: 1em;
|
|
28
45
|
font-weight: 600;
|
|
29
46
|
margin: 1.33em 0;
|
|
47
|
+
color: #333;
|
|
30
48
|
}
|
|
31
49
|
|
|
32
|
-
|
|
33
|
-
|
|
50
|
+
/* Fifth level heading */
|
|
51
|
+
.quikdown-light .quikdown-h5 {
|
|
52
|
+
font-size: .875em;
|
|
34
53
|
font-weight: 600;
|
|
35
54
|
margin: 1.67em 0;
|
|
55
|
+
color: #333;
|
|
36
56
|
}
|
|
37
57
|
|
|
38
|
-
|
|
39
|
-
|
|
58
|
+
/* Sixth level heading */
|
|
59
|
+
.quikdown-light .quikdown-h6 {
|
|
60
|
+
font-size: .85em;
|
|
40
61
|
font-weight: 600;
|
|
41
62
|
margin: 2em 0;
|
|
63
|
+
color: #333;
|
|
42
64
|
}
|
|
43
65
|
|
|
44
|
-
|
|
45
|
-
.quikdown-pre {
|
|
66
|
+
.quikdown-light .quikdown-pre {
|
|
46
67
|
background: #f4f4f4;
|
|
47
68
|
padding: 10px;
|
|
48
69
|
border-radius: 4px;
|
|
@@ -50,28 +71,27 @@
|
|
|
50
71
|
margin: 1em 0;
|
|
51
72
|
}
|
|
52
73
|
|
|
53
|
-
.quikdown-code {
|
|
74
|
+
.quikdown-light .quikdown-code {
|
|
54
75
|
background: #f0f0f0;
|
|
55
76
|
padding: 2px 4px;
|
|
56
77
|
border-radius: 3px;
|
|
57
78
|
font-family: monospace;
|
|
58
79
|
}
|
|
59
80
|
|
|
60
|
-
|
|
61
|
-
.quikdown-blockquote {
|
|
81
|
+
.quikdown-light .quikdown-blockquote {
|
|
62
82
|
border-left: 4px solid #ddd;
|
|
63
83
|
margin-left: 0;
|
|
64
84
|
padding-left: 1em;
|
|
85
|
+
color: #333;
|
|
65
86
|
}
|
|
66
87
|
|
|
67
|
-
|
|
68
|
-
.quikdown-table {
|
|
88
|
+
.quikdown-light .quikdown-table {
|
|
69
89
|
border-collapse: collapse;
|
|
70
90
|
width: 100%;
|
|
71
91
|
margin: 1em 0;
|
|
72
92
|
}
|
|
73
93
|
|
|
74
|
-
.quikdown-th {
|
|
94
|
+
.quikdown-light .quikdown-th {
|
|
75
95
|
border: 1px solid #ddd;
|
|
76
96
|
padding: 8px;
|
|
77
97
|
background-color: #f2f2f2;
|
|
@@ -79,60 +99,72 @@
|
|
|
79
99
|
text-align: left;
|
|
80
100
|
}
|
|
81
101
|
|
|
82
|
-
.quikdown-td {
|
|
102
|
+
.quikdown-light .quikdown-td {
|
|
83
103
|
border: 1px solid #ddd;
|
|
84
104
|
padding: 8px;
|
|
85
105
|
text-align: left;
|
|
106
|
+
color: #333;
|
|
86
107
|
}
|
|
87
108
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
margin:
|
|
92
|
-
padding-left: 2em;
|
|
109
|
+
.quikdown-light .quikdown-hr {
|
|
110
|
+
border: none;
|
|
111
|
+
border-top: 1px solid #ddd;
|
|
112
|
+
margin: 1em 0;
|
|
93
113
|
}
|
|
94
114
|
|
|
95
|
-
.quikdown-
|
|
96
|
-
|
|
115
|
+
.quikdown-light .quikdown-img {
|
|
116
|
+
max-width: 100%;
|
|
117
|
+
height: auto;
|
|
97
118
|
}
|
|
98
119
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
120
|
+
.quikdown-light .quikdown-a {
|
|
121
|
+
color: #06c;
|
|
122
|
+
text-decoration: underline;
|
|
102
123
|
}
|
|
103
124
|
|
|
104
|
-
.quikdown-
|
|
105
|
-
|
|
125
|
+
.quikdown-light .quikdown-strong {
|
|
126
|
+
font-weight: bold;
|
|
106
127
|
}
|
|
107
128
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
color: #0066cc;
|
|
111
|
-
text-decoration: underline;
|
|
129
|
+
.quikdown-light .quikdown-em {
|
|
130
|
+
font-style: italic;
|
|
112
131
|
}
|
|
113
132
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
max-width: 100%;
|
|
117
|
-
height: auto;
|
|
133
|
+
.quikdown-light .quikdown-del {
|
|
134
|
+
text-decoration: line-through;
|
|
118
135
|
}
|
|
119
136
|
|
|
120
|
-
|
|
121
|
-
.
|
|
122
|
-
|
|
123
|
-
border-top: 1px solid #ddd;
|
|
124
|
-
margin: 1em 0;
|
|
137
|
+
.quikdown-light .quikdown-ul {
|
|
138
|
+
margin: 0.5em 0;
|
|
139
|
+
padding-left: 2em;
|
|
125
140
|
}
|
|
126
141
|
|
|
127
|
-
|
|
128
|
-
.
|
|
129
|
-
|
|
142
|
+
.quikdown-light .quikdown-ol {
|
|
143
|
+
margin: 0.5em 0;
|
|
144
|
+
padding-left: 2em;
|
|
130
145
|
}
|
|
131
146
|
|
|
132
|
-
.quikdown-
|
|
133
|
-
|
|
147
|
+
.quikdown-light .quikdown-li {
|
|
148
|
+
margin: 0.25em 0;
|
|
149
|
+
color: #333;
|
|
134
150
|
}
|
|
135
151
|
|
|
136
|
-
.quikdown-
|
|
137
|
-
|
|
152
|
+
.quikdown-light .quikdown-task-item {
|
|
153
|
+
list-style: none;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.quikdown-light .quikdown-task-checkbox {
|
|
157
|
+
margin-right: .5em;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/* ============================================
|
|
161
|
+
Container Styling
|
|
162
|
+
============================================ */
|
|
163
|
+
|
|
164
|
+
.quikdown-light {
|
|
165
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
|
166
|
+
line-height: 1.6;
|
|
167
|
+
color: #333;
|
|
168
|
+
background: #fff;
|
|
169
|
+
padding: 1rem;
|
|
138
170
|
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/* QuikDown Theme CSS (minified) */
|
|
2
|
+
.quikdown-light .quikdown-h1{font-size:2em;font-weight:600;margin:.67em 0;text-align:left;color:#333}.quikdown-light .quikdown-h2{font-size:1.5em;font-weight:600;margin:.83em 0;color:#333}.quikdown-light .quikdown-h3{font-size:1.25em;font-weight:600;margin:1em 0;color:#333}.quikdown-light .quikdown-h4{font-size:1em;font-weight:600;margin:1.33em 0;color:#333}.quikdown-light .quikdown-h5{font-size:.875em;font-weight:600;margin:1.67em 0;color:#333}.quikdown-light .quikdown-h6{font-size:.85em;font-weight:600;margin:2em 0;color:#333}.quikdown-light .quikdown-pre{background:#f4f4f4;padding:10px;border-radius:4px;overflow-x:auto;margin:1em 0}.quikdown-light .quikdown-code{background:#f0f0f0;padding:2px 4px;border-radius:3px;font-family:monospace}.quikdown-light .quikdown-blockquote{border-left:4px solid #ddd;margin-left:0;padding-left:1em;color:#333}.quikdown-light .quikdown-table{border-collapse:collapse;width:100%;margin:1em 0}.quikdown-light .quikdown-th{border:1px solid #ddd;padding:8px;background-color:#f2f2f2;font-weight:700;text-align:left}.quikdown-light .quikdown-td{border:1px solid #ddd;padding:8px;text-align:left;color:#333}.quikdown-light .quikdown-hr{border:none;border-top:1px solid #ddd;margin:1em 0}.quikdown-light .quikdown-img{max-width:100%;height:auto}.quikdown-light .quikdown-a{color:#06c;text-decoration:underline}.quikdown-light .quikdown-strong{font-weight:700}.quikdown-light .quikdown-em{font-style:italic}.quikdown-light .quikdown-del{text-decoration:line-through}.quikdown-light .quikdown-ol,.quikdown-light .quikdown-ul{margin:.5em 0;padding-left:2em}.quikdown-light .quikdown-li{margin:.25em 0;color:#333}.quikdown-light .quikdown-task-item{list-style:none}.quikdown-light .quikdown-task-checkbox{margin-right:.5em}.quikdown-light{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,sans-serif;line-height:1.6;color:#333;background:#fff;padding:1rem}
|