import sys import re def get_balanced_div(html, start_idx): i = start_idx tag_count = 0 while i < len(html): next_open = html.find('', i) if next_open == -1 and next_close == -1: break if next_open != -1 and (next_open < next_close or next_close == -1): tag_count += 1 i = next_open + 4 else: tag_count -= 1 i = next_close + 6 if tag_count == 0: return start_idx, i return start_idx, -1 def get_balanced_ul(html, start_idx): i = start_idx tag_count = 0 while i < len(html): next_open = html.find('', i) if next_open == -1 and next_close == -1: break if next_open != -1 and (next_open < next_close or next_close == -1): tag_count += 1 i = next_open + 3 else: tag_count -= 1 i = next_close + 5 if tag_count == 0: return start_idx, i return start_idx, -1 html = open('app/modules/sag/templates/detail.html.bak').read() def extract_widget(html, data_module_name): matches = list(re.finditer(rf']*data-module="{data_module_name}"[^>]*>', html)) if not matches: return "", html start, end = get_balanced_div(html, matches[0].start()) widget = html[start:end] html = html[:start] + html[end:] return widget, html def extract_by_comment(html, comment_str): c_start = html.find(comment_str) if c_start == -1: return "", html div_start = html.find('', 0, start) if c_start != -1 and (start - c_start < 100): actual_start = c_start else: actual_start = start _, end = get_balanced_ul(html, start) widget = html[actual_start:end] html = html[:actual_start] + html[end:] return widget, html # Extraction process quick_info, html = extract_by_comment(html, '') assignment, html = extract_by_comment(html, '') customers, html = extract_widget(html, "customers") contacts, html = extract_widget(html, "contacts") hardware, html = extract_widget(html, "hardware") locations, html = extract_widget(html, "locations") todo, html = extract_widget(html, "todo-steps") wiki, html = extract_widget(html, "wiki") reminders_tab_pane, html = extract_widget(html, "reminders") # update the reminders tab pane wrapping to match right column styling reminders_content = reminders_tab_pane.replace('class="tab-pane fade"', 'class="card right-module-card pt-1"').replace('id="reminders" role="tabpanel" tabindex="0"', '') # Also remove reminders from the nav tab! html = re.sub(r'', '', html, flags=re.DOTALL) sagsbeskrivelse, html = extract_by_comment(html, '') nav_tabs, html = extract_ul_nav(html) tab_content_start = html.find('
') if tab_content_start != -1: tc_start, tc_end = get_balanced_div(html, tab_content_start) tab_content = html[tab_content_start:tc_end] html = html[:tab_content_start] + html[tc_end:] else: tab_content = "" # Strip old #details column wrapping tab_content = tab_content.replace('
\n
', '') left_col_str = '
' idx_l = tab_content.find(left_col_str) if idx_l != -1: tab_content = tab_content[:idx_l] + tab_content[idx_l+len(left_col_str):] idx_row = tab_content.rfind('
', 0, idx_l) if idx_row != -1: tab_content = tab_content[:idx_row] + tab_content[idx_row+len('
'):] right_col_str = '
' idx_r = tab_content.find(right_col_str) if idx_r != -1: r_start, r_end = get_balanced_div(tab_content, idx_r) tab_content = tab_content[:idx_r] + tab_content[r_end:] # Since we removed 2 open divs (
last_div = dt_content.rfind('
') if last_div != -1: dt_content = dt_content[:last_div] + dt_content[last_div+6:] last_div = dt_content.rfind('
') if last_div != -1: dt_content = dt_content[:last_div] + dt_content[last_div+6:] tab_content = tab_content[:details_div_start] + dt_content + tab_content[details_div_end:] new_grid = f""" {quick_info}
Kontekst & Stamdata
{customers} {contacts} {hardware} {locations} {wiki}
{sagsbeskrivelse}
{nav_tabs}
{tab_content}
Opsummering & Opgaver
{assignment} {todo} {reminders_content}
""" top_bar_start = html.find('