dhammawatthumpra commited on
Commit
bf53ae4
·
1 Parent(s): cfd4523

fix: extract end markers from raw <B> tags instead of sections (works per-page, not proximity guess)

Browse files
webapp/tipitaka-api/app/schemas.py CHANGED
@@ -18,6 +18,7 @@ class PageResponse(BaseModel):
18
  content_html_formatted: str = ""
19
  title: Optional[str] = None
20
  sections: List[SectionInfo] = Field(default_factory=list)
 
21
  requested_page: Optional[int] = None
22
  is_blank: Optional[bool] = False
23
  skipped_from: Optional[int] = None
 
18
  content_html_formatted: str = ""
19
  title: Optional[str] = None
20
  sections: List[SectionInfo] = Field(default_factory=list)
21
+ end_markers: List[str] = Field(default_factory=list)
22
  requested_page: Optional[int] = None
23
  is_blank: Optional[bool] = False
24
  skipped_from: Optional[int] = None
webapp/tipitaka-api/app/services/page_service.py CHANGED
@@ -95,6 +95,16 @@ class PageService:
95
  sections.sort(key=lambda s: s["level"])
96
  cleaned = self.search_service.clean_text(row["content_text"])
97
  is_blank = self._is_blank_page(cleaned)
 
 
 
 
 
 
 
 
 
 
98
  return {
99
  "id": row["id"],
100
  "volume_id": row["volume_id"],
@@ -102,10 +112,11 @@ class PageService:
102
  "page_number": row["page_number"],
103
  "total_pages": row["total_pages"] or 0,
104
  "content_text": "" if is_blank else cleaned,
105
- "content_html": "" if is_blank else (row["content_html"] or ""),
106
- "content_html_formatted": "" if is_blank else self.format_content_html(row["content_html"] or ""),
107
  "title": row["title"],
108
  "sections": sections,
 
109
  "is_blank": is_blank,
110
  }
111
 
 
95
  sections.sort(key=lambda s: s["level"])
96
  cleaned = self.search_service.clean_text(row["content_text"])
97
  is_blank = self._is_blank_page(cleaned)
98
+
99
+ # Extract end markers from raw content_html: <B> tags containing "จบ"
100
+ raw_html = row["content_html"] or ""
101
+ end_markers = []
102
+ if not is_blank and raw_html:
103
+ for m in re.finditer(r'<B>(.*?จบ.*?)</B>', raw_html, re.IGNORECASE):
104
+ tm = m.group(1).strip()
105
+ if tm and tm not in end_markers:
106
+ end_markers.append(tm)
107
+
108
  return {
109
  "id": row["id"],
110
  "volume_id": row["volume_id"],
 
112
  "page_number": row["page_number"],
113
  "total_pages": row["total_pages"] or 0,
114
  "content_text": "" if is_blank else cleaned,
115
+ "content_html": "" if is_blank else raw_html,
116
+ "content_html_formatted": "" if is_blank else self.format_content_html(raw_html),
117
  "title": row["title"],
118
  "sections": sections,
119
+ "end_markers": end_markers,
120
  "is_blank": is_blank,
121
  }
122
 
webapp/tipitaka-web/src/components/layout/ReaderPanel.tsx CHANGED
@@ -17,21 +17,7 @@ const SHELL_STYLES: Record<string, string> = {
17
  classic: 'bg-[#f5edd8]',
18
  };
19
 
20
- const renderContent = (html: string, fontSize: number, sections: {title: string; level: number; page_number?: number}[], currentPage?: number) => {
21
- // Sections with "จบ" → end marker below content
22
- // Only if section's page_number is close to current page (within 5 pages)
23
- const endMarkers = sections.filter(s => {
24
- const title = s.title.trim();
25
- if (!(title.endsWith('จบ') || title.includes('จบ'))) return false;
26
- // Skip if this end marker belongs to a faraway page
27
- if (s.page_number !== undefined && currentPage !== undefined) {
28
- if (currentPage - s.page_number > 5) return false;
29
- }
30
- // Skip if already rendered as <h4> inside content body (from <B> tag)
31
- if (html && html.includes(title)) return false;
32
- return true;
33
- });
34
-
35
  return (
36
  <div
37
  style={{ fontSize: `${fontSize}px`, lineHeight: '2.1' }}
@@ -45,12 +31,12 @@ const renderContent = (html: string, fontSize: number, sections: {title: string;
45
  ) : (
46
  <p className="text-[#888] italic text-center py-10">ไม่มีข้อความในหน้านี้</p>
47
  )}
48
- {/* End markers sections containing "จบ" at bottom */}
49
  {endMarkers.length > 0 && (
50
  <div className="space-y-1 pt-2">
51
- {endMarkers.map((s, i) => (
52
  <p key={i} className="text-xs text-[#888] tracking-widest">
53
- --------- {s.title} ---------
54
  </p>
55
  ))}
56
  </div>
@@ -198,7 +184,7 @@ const ReaderPanel: React.FC = () => {
198
  ))}
199
  </header>
200
  <div className="border-b border-[#c8860a]/15 mb-5" />
201
- {renderContent(content.content_html_formatted || content.content_html || '', fontSize, content.sections || [], content.page_number)}
202
  </>
203
  )}
204
 
 
17
  classic: 'bg-[#f5edd8]',
18
  };
19
 
20
+ const renderContent = (html: string, fontSize: number, endMarkers: string[]) => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  return (
22
  <div
23
  style={{ fontSize: `${fontSize}px`, lineHeight: '2.1' }}
 
31
  ) : (
32
  <p className="text-[#888] italic text-center py-10">ไม่มีข้อความในหน้านี้</p>
33
  )}
34
+ {/* End markers from raw <B> tags containing "จบ" */}
35
  {endMarkers.length > 0 && (
36
  <div className="space-y-1 pt-2">
37
+ {endMarkers.map((title, i) => (
38
  <p key={i} className="text-xs text-[#888] tracking-widest">
39
+ --------- {title} ---------
40
  </p>
41
  ))}
42
  </div>
 
184
  ))}
185
  </header>
186
  <div className="border-b border-[#c8860a]/15 mb-5" />
187
+ {renderContent(content.content_html_formatted || content.content_html || '', fontSize, content.end_markers || [])}
188
  </>
189
  )}
190