From c3806f01c3c739d53d0426cc9e5d876bcd9db49e Mon Sep 17 00:00:00 2001 From: ben Date: Fri, 26 Sep 2025 19:13:21 -0300 Subject: [PATCH] fix: resolve markdown list processing and TinyMCE timing issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rewrite markdown conversion to handle lists before other formatting - Fix conflict between * for lists and * for italic text formatting - Improve list detection with proper "* " pattern matching - Add WordPress tinymce-editor-init event listener for proper initialization - Store editor reference globally for reliable content insertion - Enhanced TinyMCE readiness detection with fallback mechanisms 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- assets/js/hvac-ai-assist.js | 83 +++++++++++++--------- includes/class-hvac-event-form-builder.php | 22 ++++-- 2 files changed, 67 insertions(+), 38 deletions(-) diff --git a/assets/js/hvac-ai-assist.js b/assets/js/hvac-ai-assist.js index 7912e330..c618bef8 100644 --- a/assets/js/hvac-ai-assist.js +++ b/assets/js/hvac-ai-assist.js @@ -576,8 +576,12 @@ jQuery(document).ready(function($) { // Wait for TinyMCE to be fully initialized const applyToTinyMCE = () => { - if (typeof tinyMCE !== 'undefined' && tinyMCE.get('event_description') && window.hvacTinyMCEReady) { - console.log('Setting TinyMCE content'); + if (window.hvacTinyMCEReady && window.hvacTinyMCEEditor) { + console.log('Setting TinyMCE content using stored editor reference'); + window.hvacTinyMCEEditor.setContent(htmlContent); + return true; + } else if (typeof tinyMCE !== 'undefined' && tinyMCE.get('event_description')) { + console.log('Setting TinyMCE content using direct reference'); tinyMCE.get('event_description').setContent(htmlContent); return true; } @@ -742,36 +746,23 @@ jQuery(document).ready(function($) { * Convert markdown to HTML for rich text editor */ markdownToHtml: function(markdown) { - // Test the function with sample input if (window.hvacDebugMarkdown) { console.log('Testing markdown conversion:'); console.log('Input:', markdown); } - let html = markdown; - // Convert headers (#### -> h4, ### -> h3, ## -> h2, # -> h1) - html = html.replace(/^#### (.+)$/gm, '

$1

'); - html = html.replace(/^### (.+)$/gm, '

$1

'); - html = html.replace(/^## (.+)$/gm, '

$1

'); - html = html.replace(/^# (.+)$/gm, '

$1

'); - - // Convert bold text (**text** -> text) - html = html.replace(/\*\*([^*]+)\*\*/g, '$1'); - - // Convert italic text (*text* -> text) - html = html.replace(/\*([^*]+)\*/g, '$1'); - - // Process lines for better list handling - const lines = html.split('\n'); + // First, handle lists BEFORE processing other markdown + // This prevents conflicts between * for lists and * for italic + const lines = markdown.split('\n'); const processedLines = []; let inList = false; for (let i = 0; i < lines.length; i++) { let line = lines[i].trim(); - // Handle bullet list items - if (line.match(/^\* (.+)$/)) { - const listItemContent = line.replace(/^\* (.+)$/, '$1'); + // Handle bullet list items (must start with * and space) + if (line.match(/^\* /)) { + const listItemContent = line.substring(2); // Remove "* " if (!inList) { processedLines.push(''); inList = false; } @@ -793,11 +784,7 @@ jQuery(document).ready(function($) { } // Add regular line - if (line !== '') { - processedLines.push(line); - } else { - processedLines.push(''); // Preserve empty lines for paragraph breaks - } + processedLines.push(lines[i]); // Keep original spacing } } @@ -806,13 +793,41 @@ jQuery(document).ready(function($) { processedLines.push(''); } + // Rejoin the processed content + let html = processedLines.join('\n'); + + // Now process other markdown elements + // Convert headers (#### -> h4, ### -> h3, ## -> h2, # -> h1) + html = html.replace(/^#### (.+)$/gm, '

$1

'); + html = html.replace(/^### (.+)$/gm, '

$1

'); + html = html.replace(/^## (.+)$/gm, '

$1

'); + html = html.replace(/^# (.+)$/gm, '

$1

'); + + // Convert bold text (**text** -> text) + html = html.replace(/\*\*([^*]+?)\*\*/g, '$1'); + + // Convert italic text (*text* -> text) + // Process line by line to avoid conflicts with list items + const italicLines = html.split('\n').map(line => { + // Skip processing if this line contains list markup + if (line.includes('
  • ') || line.includes('
      ') || line.includes('
    ')) { + return line; + } + // Apply italic formatting to non-list lines + return line.replace(/\*([^*\n]+?)\*/g, '$1'); + }); + html = italicLines.join('\n'); + // Convert to paragraphs + const finalLines = html.split('\n'); const paragraphs = []; let currentParagraph = ''; - for (let line of processedLines) { + for (let line of finalLines) { + const trimmedLine = line.trim(); + // Skip empty lines - if (line === '') { + if (trimmedLine === '') { if (currentParagraph) { paragraphs.push(currentParagraph); currentParagraph = ''; @@ -821,18 +836,18 @@ jQuery(document).ready(function($) { } // If line is already wrapped in HTML tags, add it as is - if (line.match(/^<(h[1-6]|ul|\/ul|li|strong|em)/)) { + if (trimmedLine.match(/^<(h[1-6]|ul|\/ul|li)/)) { if (currentParagraph) { paragraphs.push(currentParagraph); currentParagraph = ''; } - paragraphs.push(line); + paragraphs.push(trimmedLine); } else { // Regular text line if (currentParagraph) { - currentParagraph += ' ' + line; + currentParagraph += ' ' + trimmedLine; } else { - currentParagraph = line; + currentParagraph = trimmedLine; } } } diff --git a/includes/class-hvac-event-form-builder.php b/includes/class-hvac-event-form-builder.php index c407339d..2ce851cb 100644 --- a/includes/class-hvac-event-form-builder.php +++ b/includes/class-hvac-event-form-builder.php @@ -1678,18 +1678,32 @@ HTML; jQuery(document).ready(function($) { // Store reference for AI Assistant window.hvacTinyMCEReady = false; + window.hvacTinyMCEEditor = null; - // Check if TinyMCE is ready + // Listen for TinyMCE init event + $(document).on('tinymce-editor-init', function(event, editor) { + if (editor.id === 'event_description') { + window.hvacTinyMCEReady = true; + window.hvacTinyMCEEditor = editor; + console.log('TinyMCE editor initialized for event_description'); + } + }); + + // Fallback check if event doesn't fire function checkTinyMCEReady() { if (typeof tinyMCE !== 'undefined' && tinyMCE.get('event_description')) { - window.hvacTinyMCEReady = true; - console.log('TinyMCE ready for event_description'); + if (!window.hvacTinyMCEReady) { + window.hvacTinyMCEReady = true; + window.hvacTinyMCEEditor = tinyMCE.get('event_description'); + console.log('TinyMCE ready for event_description (fallback detection)'); + } } else { setTimeout(checkTinyMCEReady, 100); } } - checkTinyMCEReady(); + // Start fallback check + setTimeout(checkTinyMCEReady, 500); });