zenivan commited on
Commit
ec62fc6
·
1 Parent(s): b4f8673
Files changed (1) hide show
  1. app/test_gradio_test.py +71 -39
app/test_gradio_test.py CHANGED
@@ -58,60 +58,92 @@ def upload_to_catbox(file_bytes: bytes, filename: str = "image.png", expire: str
58
 
59
  import re
60
 
 
 
 
61
  from bs4 import BeautifulSoup
62
  from docx import Document
63
  from docx.enum.section import WD_ORIENT
64
- from html_for_docx import HTML2DOCX # класс из html‑for‑docx
65
- import tempfile, os
66
- from datetime import datetime
67
 
68
  def generate_docx(html: str) -> str:
 
69
  soup = BeautifulSoup(html, "html.parser")
70
 
71
- # Убираем все цвета, border, float; оставляем только font-size, padding
72
  for tag in soup.find_all(True):
73
- style = tag.get("style","")
74
- safe=[]
75
- for part in style.split(";"):
76
- if part.strip().startswith(("font-size","padding","vertical-align")):
77
- # конвертируем em/px→pt
78
- prop,val=part.split(":")
79
- if val.endswith("em"):
80
- val=f"{int(float(val[:-2])*12)}pt"
81
- elif val.endswith("px"):
82
- val=f"{round(int(val[:-2])*72/96)}pt"
83
- safe.append(f"{prop}:{val}")
84
- if safe: tag["style"]=";".join(safe)
85
- else: tag.attrs.pop("style",None)
86
-
87
- # Преобразуем два <div> в section.output-block → таблицу 1×2
88
- for section in soup.select("section.output-block"):
89
- divs=section.find_all("div",recursive=False)
90
- if len(divs)==2:
91
- table=soup.new_tag("table", style="width:100%;border-collapse:collapse")
92
- tr=soup.new_tag("tr")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  for div in divs:
94
- td=soup.new_tag("td", style="vertical-align:top;padding:0.5em;font-size:11pt;")
95
- td.extend(div.contents)
 
 
96
  tr.append(td)
97
  table.append(tr)
98
- section.clear(); section.append(table)
 
99
 
100
- clean_html=str(soup)
101
 
102
- # Создаём документ и ландшафт
103
- doc=Document()
104
- sec=doc.sections[-1]
105
- sec.orientation=WD_ORIENT.LANDSCAPE
106
- sec.page_width,sec.page_height=sec.page_height,sec.page_width
107
 
108
- # Конвертируем через html-for-docx, задаём видимые границы
109
- converter=HTML2DOCX()
110
- converter.table_style="TableGrid"
111
- converter.add_html_to_document(clean_html,doc)
112
 
113
- fn=f"lesson_{datetime.now():%Y%m%d%H%M%S}.docx"
114
- path=os.path.join(tempfile.gettempdir(),fn)
 
115
  doc.save(path)
116
  return path
117
 
 
58
 
59
  import re
60
 
61
+ import os, tempfile
62
+ from datetime import datetime
63
+
64
  from bs4 import BeautifulSoup
65
  from docx import Document
66
  from docx.enum.section import WD_ORIENT
67
+ from htmldocx import HtmlToDocx
 
 
68
 
69
  def generate_docx(html: str) -> str:
70
+ # 1. Парсим HTML
71
  soup = BeautifulSoup(html, "html.parser")
72
 
73
+ # 1.1 – очищаем все style, оставляем только font-size (em/px→pt), padding, vertical-align
74
  for tag in soup.find_all(True):
75
+ style = tag.get("style", "")
76
+ if style:
77
+ parts = []
78
+ for part in style.split(";"):
79
+ if ":" not in part:
80
+ continue
81
+ prop, val = part.split(":", 1)
82
+ prop, val = prop.strip(), val.strip()
83
+ if prop == "font-size":
84
+ # em→pt, px→pt
85
+ if val.endswith("em"):
86
+ pt = int(float(val[:-2]) * 12)
87
+ parts.append(f"font-size:{pt}pt")
88
+ elif val.endswith("px"):
89
+ pt = round(int(val[:-2]) * 72/96)
90
+ parts.append(f"font-size:{pt}pt")
91
+ elif prop in ("padding", "vertical-align", "margin-bottom"):
92
+ parts.append(f"{prop}:{val}")
93
+ if parts:
94
+ tag["style"] = ";".join(parts)
95
+ else:
96
+ tag.attrs.pop("style", None)
97
+
98
+ # 1.2 – шапка: cell-label и cell-value
99
+ for span in soup.select("span.cell-label"):
100
+ span["style"] = "display:block;font-size:9pt;color:#555;margin-bottom:0.2em"
101
+ for span in soup.select("span.cell-value"):
102
+ span["style"] = "display:block;font-size:12pt"
103
+
104
+ # 1.3 – заголовки h4 → p.bold
105
+ for h4 in soup.find_all("h4"):
106
+ p = soup.new_tag("p")
107
+ p.string = h4.get_text()
108
+ p["style"] = "font-size:12pt;font-weight:bold;margin-bottom:0.2em"
109
+ h4.replace_with(p)
110
+
111
+ # 1.4 – Teaching Reference Sheet (только секция без header‑block)
112
+ for section in soup.find_all("section", class_="output-block"):
113
+ classes = section.get("class", [])
114
+ if "header-block" in classes or section.find("table"):
115
+ continue
116
+ divs = section.find_all("div", recursive=False)
117
+ if len(divs) == 2:
118
+ table = soup.new_tag("table")
119
+ table["style"] = "width:100%;border-collapse:collapse"
120
+ tr = soup.new_tag("tr")
121
  for div in divs:
122
+ td = soup.new_tag("td")
123
+ td["style"] = "vertical-align:top;padding:0.5em;font-size:11pt"
124
+ for ch in div.contents:
125
+ td.append(ch)
126
  tr.append(td)
127
  table.append(tr)
128
+ section.clear()
129
+ section.append(table)
130
 
131
+ clean_html = str(soup)
132
 
133
+ # 2. Создаём DOCX и делаем landscape
134
+ doc = Document()
135
+ sec = doc.sections[-1]
136
+ sec.orientation = WD_ORIENT.LANDSCAPE # альбом :contentReference[oaicite:4]{index=4}
137
+ sec.page_width, sec.page_height = sec.page_height, sec.page_width
138
 
139
+ # 3. Конвертируем HTML → DOCX с видимыми границами
140
+ parser = HtmlToDocx()
141
+ parser.table_style = "TableGrid" # TableGrid для всех таблиц :contentReference[oaicite:5]{index=5}
142
+ parser.add_html_to_document(clean_html, doc)
143
 
144
+ # 4. Сохраняем во временный файл
145
+ fname = f"lesson_plan_{datetime.now():%Y%m%d%H%M%S}.docx"
146
+ path = os.path.join(tempfile.gettempdir(), fname)
147
  doc.save(path)
148
  return path
149