From 9450eeb817c0b6a74a43803bd728fda3aca68263 Mon Sep 17 00:00:00 2001 From: Nathan Schneider Date: Wed, 7 May 2025 15:00:20 -0600 Subject: [PATCH] Added Markdown support --- static/css/main.css | 101 ++++++++++++++++++ static/js/builder.js | 45 +++++++- .../layouts/_default/builder.html | 13 +++ .../layouts/partials/head.html | 3 +- 4 files changed, 158 insertions(+), 4 deletions(-) diff --git a/static/css/main.css b/static/css/main.css index b23a7cc..012a04f 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -1356,4 +1356,105 @@ textarea { box-shadow: none; margin-top: 5px; } +} + +/* Markdown styles for preview content */ +.preview-content { + line-height: 1.5; + word-wrap: break-word; +} + +.preview-content a { + color: #0066cc; + text-decoration: underline; +} + +.preview-content strong, .preview-content b { + font-weight: bold; +} + +.preview-content em, .preview-content i { + font-style: italic; +} + +.preview-content ul, .preview-content ol { + margin: 0.5em 0; + padding-left: 2em; +} + +.preview-content ul li { + list-style-type: disc; +} + +.preview-content ol li { + list-style-type: decimal; +} + +.preview-content h1, +.preview-content h2, +.preview-content h3, +.preview-content h4, +.preview-content h5, +.preview-content h6 { + margin: 0.5em 0; + line-height: 1.2; +} + +.preview-content h1 { font-size: 1.5em; } +.preview-content h2 { font-size: 1.3em; } +.preview-content h3 { font-size: 1.2em; } +.preview-content h4 { font-size: 1.1em; } +.preview-content h5, .preview-content h6 { font-size: 1em; } + +.preview-content blockquote { + margin: 0.5em 0; + padding-left: 1em; + border-left: 3px solid #ccc; + color: #555; +} + +.preview-content code { + font-family: monospace; + background-color: #f0f0f0; + padding: 2px 4px; + border-radius: 3px; +} + +.preview-content pre { + background-color: #f0f0f0; + padding: 0.5em; + border-radius: 3px; + overflow-x: auto; + margin: 0.5em 0; +} + +.preview-content pre code { + background-color: transparent; + padding: 0; +} + +.preview-content p { + margin: 0.5em 0; +} + +/* Markdown help section styles */ +.markdown-help { + font-size: 0.85rem; + line-height: 1.6; + border: 1px solid #ddd; + border-radius: 4px; + padding: 10px; + background-color: #f8f8f8; +} + +.markdown-help p { + margin: 0.5em 0; +} + +.markdown-help code { + font-family: monospace; + background-color: #eee; + padding: 2px 4px; + border-radius: 3px; + font-size: 0.9em; } \ No newline at end of file diff --git a/static/js/builder.js b/static/js/builder.js index 3f58c3d..75969a1 100644 --- a/static/js/builder.js +++ b/static/js/builder.js @@ -803,8 +803,39 @@ document.addEventListener('DOMContentLoaded', function() { // Format field content with larger font size (12) doc.setFontSize(12); + // Process markdown to plaintext for PDF + let processedContent = fieldValue; + try { + // Strip HTML tags from rendered markdown to get clean text + const temp = document.createElement('div'); + temp.innerHTML = marked.parse(fieldValue); + + // Convert links to format: text (url) + const links = temp.querySelectorAll('a'); + links.forEach(link => { + const linkText = link.textContent; + const href = link.getAttribute('href'); + // Only modify if href is different from text + if (href && href !== linkText) { + const replacement = `${linkText} (${href})`; + link.textContent = replacement; + } + }); + + // Bold text handling + const boldElements = temp.querySelectorAll('strong, b'); + boldElements.forEach(el => { + el.textContent = `*${el.textContent}*`; // Surround with asterisks + }); + + // Get plain text content + processedContent = temp.textContent; + } catch (error) { + console.error('Error processing Markdown for PDF:', error); + } + // Use consistent width for all text - const textLines = doc.splitTextToSize(fieldValue, margins.width); + const textLines = doc.splitTextToSize(processedContent, margins.width); doc.text(textLines, margins.left, yPos); yPos += textLines.length * 6 + 8; // Slightly increase spacing for larger font } @@ -933,7 +964,7 @@ document.addEventListener('DOMContentLoaded', function() { }); }); - // Function to update preview content + // Function to update preview content with Markdown support function updatePreviewContent() { // First, clear any existing preview divs document.querySelectorAll('.preview-content').forEach(div => { @@ -951,7 +982,15 @@ document.addEventListener('DOMContentLoaded', function() { // Create a div to replace the textarea for preview const previewDiv = document.createElement('div'); previewDiv.className = 'preview-content'; - previewDiv.textContent = textarea.value; + + // Parse Markdown and set as HTML content + try { + previewDiv.innerHTML = marked.parse(textarea.value); + } catch (error) { + console.error('Error parsing Markdown:', error); + previewDiv.textContent = textarea.value; + } + previewDiv.dataset.forTextarea = textarea.id; // Hide the textarea and insert the div diff --git a/themes/dispute-protocol-theme/layouts/_default/builder.html b/themes/dispute-protocol-theme/layouts/_default/builder.html index f88efac..11e824d 100644 --- a/themes/dispute-protocol-theme/layouts/_default/builder.html +++ b/themes/dispute-protocol-theme/layouts/_default/builder.html @@ -106,6 +106,7 @@ @@ -119,6 +120,18 @@ + + diff --git a/themes/dispute-protocol-theme/layouts/partials/head.html b/themes/dispute-protocol-theme/layouts/partials/head.html index 44fc252..64f1761 100644 --- a/themes/dispute-protocol-theme/layouts/partials/head.html +++ b/themes/dispute-protocol-theme/layouts/partials/head.html @@ -8,9 +8,10 @@ - + + {{ if eq .Layout "builder" }}