""" * View/Slide Statistics: 1. Read MD file to gather the statistics of the view. a) Statistics includes: Original Markdown file name: md_file_name. Slide title characters count: slide_title_char_count. Slide title CJK characters count: slide_title_cjk_char_count. Slide title Western characters count: slide_title_western_char_count. Normalized slide title length: slide_title_normalized_len. Bullet line count: bullet_line_count. Max level in bullet: bullet_line_max_level. Level 0 bullet lines: bullet_line_l0_count. Level 1 bullet lines: bullet_line_l1_count. Level 2 bullet lines: bullet_line_l2_count. Level 3 bullet lines: bullet_line_l3_count. Level 4 bullet lines: bullet_line_l4_count. Normalized max bullet line character count: bullet_line_max_normalized_char_count. Normalized max bullet line happens at bullet level: bullet_line_max_normalized_char_level. Normalized max bullet line happens at line number: bullet_line_max_normalized_char_order. Code area lines: codearea1_line_count. Shortest code line in code area: codearea1_line_length_min. Maximum code line in code area: codearea1_line_length_max. Table count: table_count. Table row count: table_row_count. URL link count: url_link_count. Image count: image_count. Image count (smart): image_count_on_smart. Image count (left): image_count_on_left. Image count (right): image_count_on_right. Image count (center): image_count_on_center. Image count (background): image_count_on_background. Speaker note lines: speaker_note_line_count. Knowledge keywords: knowledge_keyword_count. 2. Advice a suggested presentation layout in the master template based on the statistics. 3. Dynamically to code area based on the statistics. """ import pingcap.pe.flash.util as util import pingcap.pe.flash.ai_editor as editor from PIL import Image import random, re, time def _normalized_len(line: str) -> int: n_len = 0 for c in line.strip("\n").replace("`", "").replace("**", ""): if util.is_char_cjk(c): n_len += 2 else: n_len += 1 return n_len def analyze_view(view: tuple) -> dict: """ :param view: The parsed_markdown result. ( list:[ (slide_line_type, slide_line_content),... ], list:[str:note_line,...], str:markdown_basename, list:[str:table_line,...], ) :returns: The analyzed statistics for the slide. """ md_file_name = view[2] slide_title_char_count = 0 slide_title_cjk_char_count = 0 slide_title_western_char_count = 0 bullet_line_count = 0 bullet_line_max_level = 0 bullet_line_l0_count = 0 bullet_line_l1_count = 0 bullet_line_l2_count = 0 bullet_line_l3_count = 0 bullet_line_l4_count = 0 bullet_line_max_level = 0 bullet_line_max_normalized_char_level = 0 bullet_line_max_normalized_char_count = 0 bullet_line_max_normalized_char_order = 0 codearea_count = 0 codearea1_line_count = 0 codearea1_line_length_min = 9999 codearea1_line_length_max = 0 codearea2_line_count = 0 codearea2_line_length_min = 9999 codearea2_line_length_max = 0 url_link_count = 0 table_count = 0 table_row_count = 0 table_column_count = 0 table_column_max_length = [] table_column_header_length = [] table_column_avg_length = [] image_count = 0 image_count_on_smart = 0 image_count_on_left = 0 image_count_on_center = 0 image_count_on_right = 0 image_count_on_background = 0 speaker_note_line_count = len(view[1]) knowledge_keyword_count = 0 parameter_view = False parameter_name = 0 version_view = False version_number = 0 # Table. if len(view) > 3: for table_line in view[3]: if table_column_count == 0: table_column_count = len(table_line[1]) table_column_max_length = [ (0, False) for _ in range(0, table_column_count) ] table_column_header_length = [0 for _ in range(0, table_column_count)] table_column_avg_length = [0 for _ in range(0, table_column_count)] if table_line[0] == "table:header": table_count += 1 for c in range(0, table_column_count): table_column_header_length[c] = _normalized_len( table_line[1][c].replace("`", "").strip("\n").strip(" ") ) elif table_line[0] == "table:row": table_row_count += 1 for c in range(0, table_column_count): c_len = _normalized_len( table_line[1][c].replace("`", "").strip("\n").strip(" ") ) table_column_avg_length[c] += c_len if c_len > table_column_max_length[c][0]: table_column_max_length[c] = (c_len, False) for c in range(0, len(table_column_max_length)): if table_column_max_length[c][0] == table_column_header_length[c]: table_column_max_length[c] = (table_column_header_length[c], True) if table_row_count > 0: table_column_avg_length = [ sum / table_row_count for sum in table_column_avg_length ] else: table_column_avg_length = table_column_header_length # Titles. for slide_line in view[0]: if slide_line[0] in ["title:slide", "chapter_title:main"]: if "`PARAMETER::" in slide_line[1].strip("\n"): parameter_view = True parameter_name = re.findall("PARAMETER::([^`]*)` ", slide_line[1]) if len(parameter_name) > 0: parameter_name = parameter_name[0] print(parameter_name) title_payload = slide_line[1].strip("\n") if "`VERSION::" in slide_line[1].strip("\n"): version_view = True version_number = re.findall("VERSION::([^`]*)` ", slide_line[1]) if len(version_number) > 0: version_number = version_number[0] print(version_number) title_payload = slide_line[1].strip("\n") if parameter_view: title_payload = re.sub("`PARAMETER::[^ ]*` ", "", title_payload) if version_view: title_payload = re.sub("`VERSION::[^ ]*` ", "", title_payload) title_payload = title_payload.replace("`", "") slide_title_char_count = len(title_payload) slide_title_normalized_len = _normalized_len(title_payload) for c in title_payload: if util.is_char_cjk(c): slide_title_cjk_char_count += 1 else: slide_title_western_char_count += 1 if slide_line[0].startswith("bulletin:"): bullet_line_count += 1 if slide_line[0] == "bulletin:0": bullet_line_l0_count += 1 if _normalized_len(slide_line[1]) > 100: bullet_line_count += 1 if ( _normalized_len(slide_line[1]) >= bullet_line_max_normalized_char_count ): bullet_line_max_normalized_char_count = _normalized_len( slide_line[1] ) bullet_line_max_normalized_char_order = bullet_line_count bullet_line_max_normalized_char_level = 0 elif slide_line[0] == "bulletin:1": bullet_line_l1_count += 1 if _normalized_len(slide_line[1]) > 100: bullet_line_count += 1 if ( (_normalized_len(slide_line[1]) + 5) ) >= bullet_line_max_normalized_char_count: bullet_line_max_normalized_char_count = ( _normalized_len(slide_line[1]) + 5 ) bullet_line_max_normalized_char_order = bullet_line_count bullet_line_max_normalized_char_level = 1 elif slide_line[0] == "bulletin:2": bullet_line_l2_count += 1 if _normalized_len(slide_line[1]) > 90: bullet_line_count += 1 if ( (_normalized_len(slide_line[1]) + 9) ) >= bullet_line_max_normalized_char_count: bullet_line_max_normalized_char_count = ( _normalized_len(slide_line[1]) + 9 ) bullet_line_max_normalized_char_order = bullet_line_count bullet_line_max_normalized_char_level = 2 elif slide_line[0] == "bulletin:3": bullet_line_l3_count += 1 if _normalized_len(slide_line[1]) > 90: bullet_line_count += 1 if ( _normalized_len(slide_line[1]) + 13 ) >= bullet_line_max_normalized_char_count: bullet_line_max_normalized_char_count = ( _normalized_len(slide_line[1]) + 13 ) bullet_line_max_normalized_char_order = bullet_line_count bullet_line_max_normalized_char_level = 3 elif slide_line[0] == "bulletin:4": bullet_line_l4_count += 1 if _normalized_len(slide_line[1]) > 90: bullet_line_count += 1 if ( _normalized_len(slide_line[1]) + 17 ) >= bullet_line_max_normalized_char_count: bullet_line_max_normalized_char_count = ( _normalized_len(slide_line[1]) + 17 ) bullet_line_max_normalized_char_order = bullet_line_count bullet_line_max_normalized_char_level = 4 if slide_line[0] == "code_area:begin": # Codearea header. codearea_count += 1 if slide_line[0] == "code_area:body": # No CJK characters allowed in code area. if codearea_count == 1: codearea1_line_count += 1 if len(slide_line[1].strip("\n")) > codearea1_line_length_max: codearea1_line_length_max = len(slide_line[1].strip("\n")) if len(slide_line[1].strip("\n")) < codearea1_line_length_min: codearea1_line_length_min = len(slide_line[1].strip("\n")) elif codearea_count == 2: codearea2_line_count += 1 if len(slide_line[1].strip("\n")) > codearea2_line_length_max: codearea2_line_length_max = len(slide_line[1].strip("\n")) if len(slide_line[1].strip("\n")) < codearea2_line_length_min: codearea2_line_length_min = len(slide_line[1].strip("\n")) if slide_line[0] == "link:url": url_link_count += 1 bullet_line_count += 1 if slide_line[0].startswith("picture:"): image_count += 1 if slide_line[0] == "picture:smart": image_count_on_smart += 1 if slide_line[0] == "picture:left": image_count_on_left += 1 elif slide_line[1] == "picture:center": image_count_on_center += 1 elif slide_line[1] == "picture:right": image_count_on_right += 1 elif slide_line[1] == "picture:background": image_count_on_background += 1 if slide_line[0] == "knowledge_point:keyword": knowledge_keyword_count += 1 if codearea1_line_length_min == 9999: codearea1_line_length_min = 0 if bullet_line_count > 0: if bullet_line_l4_count > 0: bullet_line_max_level = 4 elif bullet_line_l3_count > 0: bullet_line_max_level = 3 elif bullet_line_l2_count > 0: bullet_line_max_level = 2 elif bullet_line_l1_count > 0: bullet_line_max_level = 1 ret = { "md_file_name": md_file_name, "slide_title_char_count": slide_title_char_count, "slide_title_western_char_count": slide_title_western_char_count, "slide_title_cjk_char_count": slide_title_cjk_char_count, "slide_title_normalized_len": slide_title_normalized_len, "bullet_line_count": bullet_line_count, "bullet_line_max_normalized_char_count": bullet_line_max_normalized_char_count, "bullet_line_max_normalized_char_level": bullet_line_max_normalized_char_level, "bullet_line_max_normalized_char_order": bullet_line_max_normalized_char_order, "bullet_line_l0_count": bullet_line_l0_count, "bullet_line_l1_count": bullet_line_l1_count, "bullet_line_l2_count": bullet_line_l2_count, "bullet_line_l3_count": bullet_line_l3_count, "bullet_line_l4_count": bullet_line_l4_count, "codearea_count": codearea_count, "codearea1_line_count": codearea1_line_count, "codearea1_line_length_max": codearea1_line_length_max, "codearea1_line_length_min": codearea1_line_length_min, "codearea2_line_count": codearea2_line_count, "codearea2_line_length_max": codearea2_line_length_max, "codearea2_line_length_min": codearea2_line_length_min, "table_count": table_count, "table_row_count": table_row_count, "table_column_count": table_column_count, "table_column_max_length": table_column_max_length, "url_link_count": url_link_count, "image_count": image_count, "image_count_on_smart": image_count_on_smart, "image_count_on_left": image_count_on_left, "image_count_on_center": image_count_on_center, "image_count_on_right": image_count_on_right, "image_count_on_background": image_count_on_background, "knowledge_keyword_count": knowledge_keyword_count, "speaker_note_line_count": speaker_note_line_count, "parameter_view": parameter_view, "version_view": version_view, "info": { "MD": md_file_name, "BH": bullet_line_count, "BW": bullet_line_max_normalized_char_count, "BO": bullet_line_max_normalized_char_order, "BML": bullet_line_max_level, "BMCL": bullet_line_max_normalized_char_level, "CC": codearea_count, "CH": codearea1_line_count, "CW": codearea1_line_length_max, "CH2": codearea2_line_count, "CW2": codearea2_line_length_max, "TCML": table_column_max_length, "TR": table_row_count, "TCAL": table_column_avg_length, "SPECIAL_VIEW": (parameter_view, version_view), "PN": parameter_name, "VN": version_number, }, } return ret def advise_slide_layout_idx(slide_statistics: dict) -> int: """ :param slide_statistics analyzed by analyze_view(). :returns: The prs.slide_layouts[idx] number for the PPTX template. 1. prs.slide_layouts[0]: Not in-use, ignored by Flash. 2. prs.slide_layouts[1]: Not in-use, ignored by Flash. 3. prs.slide_layouts[2]: Chapter title, or for section title, if [6][7][8] are not there. 4. prs.slide_layouts[3]: For slides contain one title, [bulletins | one codearea | pictures]. 5. prs.slide_layouts[4]: For slides contain one title and one picture. 6. prs.slide_layouts[5]: For auto ending Thanks. 7. prs.slide_layouts[6]: For random section title. 8. prs.slide_layouts[7]: For random section title. 9. prs.slide_layouts[8]: For random section title. 10. prs.slide_layouts[9]: For normal slide, with a full picture as the background. 11. prs.slide_layouts[10]: For title only slide, with a full picture as the background. 12. prs.slide_layouts[12]: For objectives only slide. Not in-use. 13. prs.slide_layours[13]: For summary only slide. 14. prs.slide_layouts[14]: Not in-use, ingored by Flash. 15. prs.slide_layouts[15]: For slides contain one title, [bulletins | one codearea | pictures] with too many title characters. 16. prs.slide_layouts[16]: For slide to explain single parameter. Advice: a) For normalized_slide_title_char_count < 73 ? idx:3 : idx:15 """ advised_idx = 3 if slide_statistics["info"]["MD"] == "01title.md": # The chapter/unit title. advised_idx = 2 elif slide_statistics["parameter_view"] and slide_statistics["version_view"]: advised_idx = 18 elif slide_statistics["version_view"]: advised_idx = 17 elif slide_statistics["parameter_view"]: advised_idx = 16 elif ( # The section title. slide_statistics["info"]["BH"] + slide_statistics["info"]["CH"] + slide_statistics["table_count"] + slide_statistics["url_link_count"] + slide_statistics["image_count"] == 0 ): advised_idx = random.randint(6, 8) elif ( # We have payload, futher information needed. slide_statistics["info"]["BH"] + slide_statistics["info"]["CH"] + slide_statistics["table_count"] + slide_statistics["url_link_count"] + slide_statistics["image_count"] > 0 and slide_statistics["image_count_on_background"] == 0 ): slide_title_normalized_len = slide_statistics["slide_title_normalized_len"] if slide_title_normalized_len < 73: # Title font size 18, otherwise 14. advised_idx = 3 else: advised_idx = 15 elif slide_statistics["image_count_on_background"] == 1: advised_idx = 10 return advised_idx def advise_table_attributes( stats, component_left_margin, slide_base_top_margin, bullet_normalized_unit_height, table_order, ) -> tuple: """ :param stats view statistics. Return the positioning attribuets for table. Assume single table in single slide. :returns: (left, top, width, height) """ if stats["table_count"] == 1 and table_order == 1: left = component_left_margin - 28 top = ( slide_base_top_margin + bullet_normalized_unit_height * stats["info"]["BH"] ) w = 700 - left h = 405 - top # Limit control if w > 540: w = 540 if h > 290: h = 290 return (left, top, w, h) def advise_picture_attributes( stats, pos_hint, component_left_margin, slide_base_top_margin, bullet_normalized_unit_height, img: Image, ) -> tuple: """ Return the positioning attribuets for picture. :returns: (left, top, width, height) """ left = component_left_margin - 20 top = slide_base_top_margin w = 0 h = 0 if pos_hint == "right": left = 360 # if stats["image_count_on_left"] == 1 or stats["image_count_on_smart"] > 1: # top = top + bullet_normalized_unit_height * stats["info"]["BH"] elif pos_hint == "left": top = top + bullet_normalized_unit_height * stats["info"]["BH"] elif pos_hint == "centr": top = top + bullet_normalized_unit_height * stats["info"]["BH"] elif pos_hint == "smart": if stats["image_count_on_left"] == 0 and ( stats["info"]["BH"] + stats["info"]["CH"] <= 8 and stats["info"]["CH"] < 3 ): if ( stats["image_count_on_right"] == 0 and stats["info"]["BW"] < 60 and stats["info"]["CW"] < 65 and stats["info"]["BH"] > 3 ): left = 400 stats["image_count_on_right"] += 1 else: top = top + bullet_normalized_unit_height * stats["info"]["BH"] stats["image_count_on_left"] += 1 elif stats["image_count_on_center"] == 0 and ( stats["info"]["BH"] + stats["info"]["CH"] <= 20 and stats["info"]["BH"] < 8 ): left = 360 top = top + bullet_normalized_unit_height * stats["info"]["BH"] stats["image_count_on_center"] += 1 elif ( stats["image_count_on_right"] == 0 and stats["info"]["BW"] < 60 and stats["info"]["CW"] < 65 ): left = 400 stats["image_count_on_right"] += 1 elif ( stats["image_count_on_right"] == 0 and stats["info"]["BW"] < 90 and stats["info"]["CW"] < 110 ): left = 450 # if stats["image_count_on_left"] == 1 or stats["image_count_on_smart"] > 1: # top = top + bullet_normalized_unit_height * stats["info"]["BH"] stats["image_count_on_right"] += 1 elif ( stats["image_count_on_right"] == 0 and stats["info"]["BW"] < 100 and stats["info"]["CW"] < 130 ): left = 500 # if stats["image_count_on_left"] == 1 or stats["image_count_on_smart"] > 1: # top = top + bullet_normalized_unit_height * stats["info"]["BH"] stats["image_count_on_right"] += 1 else: print("\t Picture on default position !!!") img_container_width = 720 - left img_container_height = 405 - top img_container_wh_ratio = img_container_width / img_container_height iw = img.width ih = img.height img_wh_ratio = iw / ih if iw <= img_container_width and ih <= img_container_height: w = iw elif iw <= img_container_width and ih >= img_container_height: h = img_container_height - 30 elif iw >= img_container_width and ih <= img_container_height: w = img_container_width - 30 elif ( iw >= img_container_width and ih >= img_container_height and img_wh_ratio > img_container_wh_ratio ): w = img_container_width - 30 elif ( iw >= img_container_width and ih >= img_container_height and img_wh_ratio <= img_container_wh_ratio ): h = img_container_height - 30 # Limit control if w > 560: w = 560 if h > 300: h = 300 return (left, top, w, h) def apply_text_format_rules(input_run_text: str, hints="zh") -> str: """ Do we have any rules for run text? Please apply here if any. """ cw_mask = "" text = re.sub(" {1,}", " ", input_run_text).strip() for c in text: if c in [ ",", ",", ".", "。", ":", ":", ";", ";", "~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "~", "·", "`", "'", '"', "[", "]", "{", "}", "‘", "【", "】", "\\", "|", "、", "|", "<", ">", "《", "》", "-", "-", "_", "——", "=", "+", "=", "+", ]: cw_mask += "P" elif c in [" "]: cw_mask += "S" elif c in [" "]: cw_mask += "S" elif util.is_char_cjk(c): cw_mask += "C" else: cw_mask += "W" violate_pattern = "(CW|WC)" if len(re.findall(violate_pattern, cw_mask)) > 0: space_mask = ( re.sub(violate_pattern, "BE", cw_mask) .replace("C", "_") .replace("W", "_") .replace("P", "_") .replace("BE", "_S_") ) output_text = [] text_idx = 0 for p in space_mask: if p == "_": output_text += text[text_idx] text_idx += 1 else: if text[text_idx] in [" ", " "]: text_idx += 1 output_text += " " return "".join(output_text) else: return text def pretty_format_title(title_line: str, en_1gram_terms_list: list, md2md=False) -> str: """Make the input string line as a pretty slide title.""" # Apply rule title_line = apply_text_format_rules(title_line, None) # Compress the white space compress_space = re.sub(" {1,}", " ", title_line).strip() # Replaces `element1 element2...` as XX_XX_XX_PH1_XX_XX_XX keep_patterns = re.findall("`[^`]+`", compress_space) g = 1 for p in keep_patterns: compress_space = compress_space.replace(p, "XX_XX_PH" + str(g) + "_XX_XX") g += 1 cap = util.capitalize_all_first_letters(compress_space) compress_space = re.sub(" {1,}", " ", cap) # Search for EN 1gram abbrevs match, and convert token to terms pattern. tokens = compress_space.split(" ") target_tokens = [] for t in tokens: term_switch = False for ect in en_1gram_terms_list: if t.upper() == ect.upper(): if re.match("[A-Z]", ect): target_tokens += [ect] else: target_tokens += [t.title()] term_switch = True break if term_switch: continue else: target_tokens += [t] compress_space = " ".join(target_tokens) stop_word_lowered = ( compress_space.replace(" MacOS ", " macOS ") .replace(" At ", " at ") .replace(" On ", " on ") .replace(" In ", " in ") .replace(" To ", " to ") .replace(" Of ", " of ") .replace(" For ", " for ") .replace(" As ", " as ") .replace(" The ", " the ") .replace(" And ", " and ") .replace(" After ", " after ") .replace(" Before ", " before ") .replace(" Am ", " am ") .replace(" I'M ", " I'm ") .replace(" An ", " an ") .replace(" A ", " a ") .replace(" By ", " by ") .replace(" Is ", " is ") .replace(" Are ", " are ") .replace(" Or ", " or ") ) # Give the keep_patterns back g = 1 for p in keep_patterns: stop_word_lowered = stop_word_lowered.replace("XX_XX_PH" + str(g) + "_XX_XX", p) g += 1 result_title = stop_word_lowered.strip() if not md2md: result_title = result_title.replace("`", "") return result_title.replace("*", "") def pretty_format_bulletin( bulletin_line: str, en_1gram_terms_list: list, md2md=False, mode="silent" ) -> str: if mode != "silent": print(util.speak_result("pretty_format_bulletin: " + bulletin_line)) # Remove additional white spaces compress_space = re.sub(" {1,}", " ", bulletin_line).strip() # Remove prefixed "It is" and "それは、" and "它被" if compress_space.startswith("It is "): compress_space = re.sub("^It is ", "", compress_space) if compress_space.startswith("それは、"): compress_space = re.sub("^それは、", "", compress_space) if compress_space.startswith("它被"): compress_space = re.sub("^它被", "", compress_space) # Replaces `element1 element2...` as XX_XX_XX_PH1_XX_XX_XX keep_patterns = re.findall("`[^`]+`", compress_space) g = 1 for p in keep_patterns: compress_space = compress_space.replace(p, "XX_XX_PH" + str(g) + "_XX_XX") g += 1 if mode != "silent": print(util.speak_result("pretty_format_bulletin: " + compress_space)) # Search for EN Terms, and convert token to terms pattern. tokens = compress_space.split(" ") target_tokens = [] for t in tokens: term_switch = False for ect in en_1gram_terms_list: if t.upper() == ect.upper() and t.lower() != ect: target_tokens += [ect] term_switch = True break if term_switch: continue else: target_tokens += [t] compress_space = " ".join(target_tokens) if mode != "silent": print(util.speak_result("pretty_format_bulletin: " + compress_space)) # Give the keep_patterns back g = 1 for p in keep_patterns: compress_space = compress_space.replace("XX_XX_PH" + str(g) + "_XX_XX", p) g += 1 if compress_space.startswith("http") or compress_space.startswith("e.g:"): result_bulletin = compress_space else: result_bulletin = compress_space if mode != "silent": print(util.speak_result("pretty_format_bulletin: " + result_bulletin)) return result_bulletin def refine_en_md_with_openai(line: str, en_1gram_list: list, md2md=True) -> str: time.sleep(3) # 1. Do nothing: Shortcut. if ( re.match("^ *$", line) or re.match("^\|[\-\:\| ]+$", line) or re.match("^-+$", line) or re.match("^\++$", line) or re.match("^\*+$", line) or re.match("^=+$", line) or re.match("^\!\[.*$", line) or re.match("^$", line) ): return line # 2. Preserve the prefixed whitespaces compress_space_raw = line prefix_white_space = re.findall("^ +", compress_space_raw) # 3.1 Hash title prefix marker hash_title_pattern = re.findall("^ *#+ ", compress_space_raw) hash_title_count = len(hash_title_pattern) if hash_title_count == 1: compress_space_raw = compress_space_raw.replace( hash_title_pattern[0], "" ).strip() # 3.2 Plus prefix marker plus_prefix_pattern = re.findall("^ *\++ ", compress_space_raw) plus_prefix_count = len(plus_prefix_pattern) if plus_prefix_count == 1: compress_space_raw = compress_space_raw.replace( plus_prefix_pattern[0], "" ).strip() # 3.3 Minus prefix marker minus_prefix_pattern = re.findall("^ *\-+ ", compress_space_raw) minus_prefix_count = len(minus_prefix_pattern) if minus_prefix_count == 1: compress_space_raw = compress_space_raw.replace( minus_prefix_pattern[0], "" ).strip() # 3.4 Star prefix marker star_prefix_pattern = re.findall("^ *\*+ ", compress_space_raw) star_prefix_count = len(star_prefix_pattern) if star_prefix_count == 1: compress_space_raw = compress_space_raw.replace( star_prefix_pattern[0], "" ).strip() # 3.5 Number prefix marker number_prefix_pattern = re.findall("^ *[0-9]+\. ", compress_space_raw) number_prefix_count = len(number_prefix_pattern) if number_prefix_count == 1: compress_space_raw = compress_space_raw.replace( number_prefix_pattern[0], "" ).strip() # 4. Inline code marker keep_inline_code_patterns = re.findall("`[^`]+`", compress_space_raw) inline_code_count_suffix = [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", ] inline_code_count = 0 for p in keep_inline_code_patterns: compress_space_raw = compress_space_raw.replace( p, "PD1X" + inline_code_count_suffix[inline_code_count] ) inline_code_count += 1 refined_line = editor.refine_en_sentence_by_openai(compress_space_raw.strip()) compress_space_raw = refined_line.strip() # Inline code handling inline_code_count = 0 for p in keep_inline_code_patterns: compress_space_raw = re.sub( "PD1X" + inline_code_count_suffix[inline_code_count], p, compress_space_raw, flags=re.IGNORECASE, ).strip() inline_code_count += 1 compress_space_raw = compress_space_raw.strip() # Adding Hash title prefix back if hash_title_count == 1: if len(hash_title_pattern[0].strip()) < 3: compress_space_raw = hash_title_pattern[0] + pretty_format_title( compress_space_raw, en_1gram_list, md2md ) else: compress_space_raw = hash_title_pattern[0] + pretty_format_bulletin( compress_space_raw, en_1gram_list, md2md ) # Adding plus prefix back elif plus_prefix_count == 1: compress_space_raw = plus_prefix_pattern[0] + compress_space_raw # Adding minus prefix back elif minus_prefix_count == 1: compress_space_raw = minus_prefix_pattern[0] + compress_space_raw # Adding star prefix back elif star_prefix_count == 1: compress_space_raw = star_prefix_pattern[0] + compress_space_raw # Adding number prefix back elif number_prefix_count == 1: compress_space_raw = number_prefix_pattern[0] + compress_space_raw elif len(prefix_white_space) > 0: compress_space_raw = prefix_white_space[0] + compress_space_raw return compress_space_raw