unknown commited on
Commit
8dbfbab
·
1 Parent(s): de7fe63
Files changed (1) hide show
  1. utils/markdown_sanitizer.py +42 -6
utils/markdown_sanitizer.py CHANGED
@@ -1,12 +1,17 @@
1
- # utils/markdown_sanitizer.py
2
  import re
3
 
 
4
  _WS_WEIRD = re.compile(r"[\u00A0\u2000-\u200B\u2060\u3000]")
5
 
 
6
  ROW_RE = re.compile(r"^\s*\|.*\|\s*$")
7
  SEP_RE = re.compile(r"^\s*\|?\s*:?-{2,}\s*(\|\s*:?-{2,}\s*)+\|?\s*$")
8
  FENCE_RE = re.compile(r"^\s*(```|~~~)")
9
 
 
 
 
 
10
  def _split_cells(line: str) -> list[str]:
11
  return [c.strip() for c in line.strip().strip("|").split("|")]
12
 
@@ -31,6 +36,10 @@ def _balance_columns(block: list[str]) -> list[str]:
31
  fixed.append(_join_cells(cells))
32
  return fixed
33
 
 
 
 
 
34
  def _unindent_headings(line: str) -> str:
35
  m = re.match(r"^(\s{4,})(#{1,6}\s+.*)$", line)
36
  if m:
@@ -52,8 +61,12 @@ def _escape_leading_pipe(line: str) -> str:
52
  return line[:i] + r"\|" + line[i+1:]
53
  return line
54
 
 
 
 
 
55
  def _normalize_math_brackets(lines: list[str]) -> list[str]:
56
- """Chuyển [ ... ] → $$ … $$ ; và $$…$$-trên-1-dòng → khối $$ trên dòng riêng."""
57
  out = []
58
  i, n = 0, len(lines)
59
  in_fence = False
@@ -68,7 +81,7 @@ def _normalize_math_brackets(lines: list[str]) -> list[str]:
68
  if not in_fence:
69
  t = ln.strip()
70
 
71
- # $$ ... $$ trên một dòng → khối
72
  m = re.match(r"^\s*\$\$(.+)\$\$\s*$", ln)
73
  if m:
74
  content = m.group(1).strip()
@@ -100,15 +113,20 @@ def _normalize_math_brackets(lines: list[str]) -> list[str]:
100
 
101
  return out
102
 
 
 
 
 
103
  def normalize_markdown_for_pandoc(md: str) -> str:
 
104
  md = md.replace("\r\n", "\n").replace("\r", "\n")
105
  md = _WS_WEIRD.sub(" ", md)
106
 
107
- # Pass 1: chuẩn hoá khối toán học
108
  lines = md.split("\n")
109
  lines = _normalize_math_brackets(lines)
110
 
111
- # Pass 2: bảng + escape pipes
112
  out = []
113
  i, n = 0, len(lines)
114
  in_fence = False
@@ -149,4 +167,22 @@ def normalize_markdown_for_pandoc(md: str) -> str:
149
 
150
  out.append(ln); i += 1
151
 
152
- return "\n".join(out)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import re
2
 
3
+ # Xử lý ký tự khoảng trắng đặc biệt
4
  _WS_WEIRD = re.compile(r"[\u00A0\u2000-\u200B\u2060\u3000]")
5
 
6
+ # Nhận diện bảng, code block, toán học
7
  ROW_RE = re.compile(r"^\s*\|.*\|\s*$")
8
  SEP_RE = re.compile(r"^\s*\|?\s*:?-{2,}\s*(\|\s*:?-{2,}\s*)+\|?\s*$")
9
  FENCE_RE = re.compile(r"^\s*(```|~~~)")
10
 
11
+ # ------------------------- #
12
+ # HÀM HỖ TRỢ XỬ LÝ BẢNG #
13
+ # ------------------------- #
14
+
15
  def _split_cells(line: str) -> list[str]:
16
  return [c.strip() for c in line.strip().strip("|").split("|")]
17
 
 
36
  fixed.append(_join_cells(cells))
37
  return fixed
38
 
39
+ # ------------------------- #
40
+ # HỖ TRỢ XỬ LÝ KHÁC #
41
+ # ------------------------- #
42
+
43
  def _unindent_headings(line: str) -> str:
44
  m = re.match(r"^(\s{4,})(#{1,6}\s+.*)$", line)
45
  if m:
 
61
  return line[:i] + r"\|" + line[i+1:]
62
  return line
63
 
64
+ # ------------------------- #
65
+ # XỬ LÝ CÔNG THỨC TOÁN #
66
+ # ------------------------- #
67
+
68
  def _normalize_math_brackets(lines: list[str]) -> list[str]:
69
+ """Chuyển [ ... ] → $$ … $$ ; và $$…$$-trên-1-dòng → khối $$ riêng."""
70
  out = []
71
  i, n = 0, len(lines)
72
  in_fence = False
 
81
  if not in_fence:
82
  t = ln.strip()
83
 
84
+ # $$ ... $$ trên 1 dòng → khối riêng
85
  m = re.match(r"^\s*\$\$(.+)\$\$\s*$", ln)
86
  if m:
87
  content = m.group(1).strip()
 
113
 
114
  return out
115
 
116
+ # ------------------------- #
117
+ # CHUẨN HÓA TOÀN BỘ MARKDOWN #
118
+ # ------------------------- #
119
+
120
  def normalize_markdown_for_pandoc(md: str) -> str:
121
+ """Chuẩn hóa Markdown trước khi đưa vào Pandoc."""
122
  md = md.replace("\r\n", "\n").replace("\r", "\n")
123
  md = _WS_WEIRD.sub(" ", md)
124
 
125
+ # Pass 1: Chuẩn hóa toán học
126
  lines = md.split("\n")
127
  lines = _normalize_math_brackets(lines)
128
 
129
+ # Pass 2: Bảng + escape ký tự
130
  out = []
131
  i, n = 0, len(lines)
132
  in_fence = False
 
167
 
168
  out.append(ln); i += 1
169
 
170
+ # Pass 3: Ép xuống dòng hợp lý (fix Word export)
171
+ final_lines = []
172
+ for j, ln in enumerate(out):
173
+ final_lines.append(ln)
174
+ # Nếu dòng hiện tại và dòng kế tiếp đều không trống và không thuộc bảng / code / heading
175
+ if (
176
+ j + 1 < len(out)
177
+ and out[j].strip() != ""
178
+ and out[j + 1].strip() != ""
179
+ and not ROW_RE.match(out[j])
180
+ and not FENCE_RE.match(out[j])
181
+ and not out[j].strip().startswith("|")
182
+ and not out[j + 1].strip().startswith("|")
183
+ and not out[j].strip().startswith("#")
184
+ and not out[j + 1].strip().startswith("#")
185
+ ):
186
+ final_lines[-1] = final_lines[-1].rstrip() + " " # ép xuống dòng Markdown
187
+
188
+ return "\n".join(final_lines)