Commit 08434c27 authored by Miguel Angel Reina Ortega's avatar Miguel Angel Reina Ortega
Browse files

Support for several lists in the same cell

parent a55b507e
Loading
Loading
Loading
Loading
Loading
+25 −13
Original line number Diff line number Diff line
@@ -187,10 +187,9 @@ def parseGridTableWithSpans(gridTable:str) -> tuple[GridTableRowList, GridTableR
				_c = re.sub(r'\\\s*$', '\n', _c)
				cell.content += _c + _nextListElementMark  # Add list element end mark to know when the list element ends
			elif cell.listFlag and len(_c) > 0:  # any other content when handling list is concatenated to the last list element
				_c = re.sub(r'\\\s*$', '\n', _c)
				# cell.content = cell.content.strip(nextListElementMark) #remove list element end mark
				cell.content = cell.content.removesuffix(_nextListElementMark) #remove list element end mark

				_c = re.sub(r'\\\s*$', '\n', _c)
				cell.content += ' ' + _c + _nextListElementMark #add list element end mark
			elif len(_c) == 0:  # separation between list and other paragraph
				if cell.listFlag:
@@ -668,8 +667,11 @@ def generateHtmlTableWithSpans(gridTable:str) -> str:
		Returns:
			The HTML table in string format.
	"""
	regex1 = r'\s*([-*+]|\s*\d+\.)\s+((?:(?!' + re.escape(_nextListElementMark) + r').)+)' + re.escape(_nextListElementMark)
	regex1 = r'\s*([-*+]|\s*\d+\.)\s+([^' + re.escape(_nextListElementMark) + r']+)' + re.escape(_nextListElementMark)
	regex2 = r'(\s*([-*+]|\s*\d+\.)\s+(?:(?!∆).)+' + re.escape(_nextListElementMark) + r')+'
	regexLists = r'(?:(?:^|\s*<br\s*\/?>)\s*(?:(?:[-*+]|\d+\.)\s+[^' + re.escape(_nextListElementMark) + r']+' + re.escape(_nextListElementMark) + r')+(?:(\s*<br\s*\/?>\s*<br\s*\/?>|$)))'
	#regexLists = r'(?:(?:(?:[-*+]|\d+\.)\s+[^' + re.escape(_nextListElementMark) + r']+' + re.escape(_nextListElementMark) + r')+)\s*<br\s*/?>\s*<br\s*/?>'
	#regexLists = r'(?:^\s*(?:(?:[-*+]|\d+\.)\s+[^' + re.escape(_nextListElementMark) + r']+' + re.escape(_nextListElementMark) + r')+)'
	
	try:
		gridHeader, gridBody = parseGridTableWithSpans(gridTable)
@@ -721,13 +723,23 @@ def generateHtmlTableWithSpans(gridTable:str) -> str:
				continue
			else:
				#Prepare content, in case there's a list
				if cell.content is not None and (matches := re.findall(regex1, cell.content)):  # Update cell in new row
					list = '<ul>'
				if cell.content is not None:
					def replace_list(match_obj):
						"""Callback function to replace each list match."""
						list_text = match_obj.group(0)  # Get full match
						if matches := re.findall(regex1, list_text):
							sub_list = '<ul>'
							# Build list the matches
							for match in matches:
						list += f'<li>{match[1]}</li>'
					list += '</ul>'
					cell.content = re.sub(regex2, list, cell.content)
								sub_list += f'<li>{match[1]}</li>'
							sub_list += '</ul><br />'
							return sub_list
						return match_obj.group(0)  # Return original if no matches
					
					# Replace all list matches using callback
					new_content = re.sub(regexLists, replace_list, cell.content)
					if new_content != cell.content:
						cell.content = new_content
						# Enforce left alignment if cell contains a list
						cell.alignment = _alignLeft

+30 −23
Original line number Diff line number Diff line
@@ -134,28 +134,29 @@ module Banzai
            modified_content = modified_content.gsub(/\\\s*$/, '\n')
            cell.content = "#{modified_content}#{NEXT_ELEMENT_LIST_MARK}" # add the list element end mark
          elsif modified_content.empty?
            cell.content = "\n"
            cell.content = '\n'
          else
            cell.content = modified_content.gsub(/\\\s*$/, "\n")
            cell.content = modified_content.gsub(/\\\s*$/, '\n')
          end
        elsif modified_content.start_with?("- ")
          cell.content += "\n" unless cell.list_flag
          cell.content += '\n' unless cell.list_flag
          cell.list_flag = true
          modified_content = modified_content.gsub(/\\\s*$/, '\n')
          cell.content += "#{modified_content}#{NEXT_ELEMENT_LIST_MARK}"
        elsif cell.list_flag && !modified_content.empty?
          cell.content = cell.content.strip.chomp(NEXT_ELEMENT_LIST_MARK.to_s)
          modified_content = modified_content.gsub(/\\\s*$/, '\n')
          # cell.content = cell.content.strip(nextListElementMark) #remove list element end mark
          cell.content = cell.content.strip.chomp(NEXT_ELEMENT_LIST_MARK.to_s)
          cell.content += " #{modified_content}#{NEXT_ELEMENT_LIST_MARK}"
        elsif modified_content.empty?
          if cell.list_flag
            cell.list_flag = false
            cell.content += "\n\n"
            cell.content += '\n\n'
          end

          cell.content += cell.content.end_with?("\n") ? "" : "\n"
          cell.content += cell.content.end_with?('\n') ? "" : '\n'
        else
          modified_content = modified_content.gsub(/\\\s*$/, "\n")
          modified_content = modified_content.gsub(/\\\s*$/, '\n')
          cell.content += " #{modified_content}"
        end

@@ -511,7 +512,7 @@ module Banzai
              #cell.content = cell.content.gsub(/(?<espace>^|\s)(?<italic>\*|_)(?<text>.+?)\g<italic>(?!\w)/,
              #  "\\k<espace><i>\\k<text></i>")
              # Convert newlines to HTML breaks
              cell.content = cell.content&.gsub("\n", "<br />")
              cell.content = cell.content&.gsub('\n', "<br />")
            end
          end

@@ -594,7 +595,7 @@ module Banzai

                rowspan = cell.rowspan > 1 ? %( rowspan="#{cell.rowspan}") : ""
                colspan = cell.colspan > 1 ? %( colspan="#{cell.colspan}") : ""
                html += %(<th#{rowspan}#{colspan} markdown="1" style="text-align: #{cell.alignment}"><br /><br />#{cell.content}<br /><br /></th>)
                html += %(<th#{rowspan}#{colspan} markdown="1" style="text-align: #{cell.alignment}">\n\n#{cell.content}\n\n</th>)
              end
              html += '</tr>'
            end
@@ -607,19 +608,25 @@ module Banzai
            row.each do |cell|
              next if cell.rowspan == 0 || cell.colspan == 0

              matches = cell.content&.scan(
                /\s*([-*+]|\d+\.)\s+([^#{NEXT_ELEMENT_LIST_MARK}]+?)#{NEXT_ELEMENT_LIST_MARK}\n?/o)
              lists = cell.content&.scan(
                /(?:(?:^|\s*<br\s*\/?>)\s*(?:(?:[-*+]|\d+\.)\s+[^#{NEXT_ELEMENT_LIST_MARK}]+#{NEXT_ELEMENT_LIST_MARK})+(?:\s*<br\s*\/?>\s*<br\s*\/?>|$))/o)

              if lists
                lists.each do |list|
                  matches = list&.scan(
                  /\s*([-*+]|\d+\.)\s+([^#{NEXT_ELEMENT_LIST_MARK}]+?)#{NEXT_ELEMENT_LIST_MARK}/o)
                  if matches
                list = "<ul>"
                    sub_list = "<ul>"
                    matches.each do |match|
                  list += "<li>#{match[1]}</li>"
                      sub_list += "<li>#{match[1]}</li>"
                    end
                cell.content = cell.content.gsub(
                  /(\s*([-*+]|\d+\.)\s+([^#{NEXT_ELEMENT_LIST_MARK}]+#{NEXT_ELEMENT_LIST_MARK}\n?))+/o, list)
                # Enforce left alignment if cell contains a list
                    sub_list += "</ul><br />"
                    cell.content = cell.content.gsub(list.to_s, sub_list.to_s)
                    # Enforce left alignment when cell contains a list
                    cell.alignment = 'left'
                  end
                end
              end

              rowspan = cell.rowspan > 1 ? %( rowspan="#{cell.rowspan}") : ""
              colspan = cell.colspan > 1 ? %( colspan="#{cell.colspan}") : ""