coords.py 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. """坐标与引用。
  2. WikiPali 的最小可引用单位是 (book, paragraph),句子再细分到 word_start/word_end。
  3. 一切给用户看的内容都必须带得回坐标——这是研究型产出可信度的地基。
  4. 坐标的书写形式统一为 `book:paragraph`,例如 `216:35`。
  5. """
  6. import re
  7. from errors import WpError
  8. COORD_RE = re.compile(r'^\s*(\d+)\s*[:\-_]\s*(\d+)\s*$')
  9. def parse_coord(text):
  10. """把 '216:35' 解析成 (216, 35)。也接受 216-35 / 216_35。"""
  11. m = COORD_RE.match(str(text))
  12. if not m:
  13. raise WpError(f"坐标格式不对:{text}(应为 book:paragraph,如 216:35)")
  14. return int(m.group(1)), int(m.group(2))
  15. def parse_coords(items):
  16. """解析一串坐标,按 book 分组,返回 {book: [paragraph, ...]}(去重、保序)。"""
  17. grouped = {}
  18. for item in items:
  19. for part in str(item).split(','):
  20. if not part.strip():
  21. continue
  22. book, para = parse_coord(part)
  23. paras = grouped.setdefault(book, [])
  24. if para not in paras:
  25. paras.append(para)
  26. return grouped
  27. def fmt_coord(book, paragraph):
  28. return f"{book}:{paragraph}"
  29. def fmt_path(path, sep=' › ', max_items=4):
  30. """把检索结果的 path 数组压成一行章节路径。"""
  31. if not path:
  32. return ''
  33. titles = [p.get('title', '') for p in path if isinstance(p, dict) and p.get('title')]
  34. if len(titles) > max_items:
  35. titles = [titles[0], '…'] + titles[-(max_items - 2):]
  36. return sep.join(titles)
  37. def text_layer(tags):
  38. """按 tags 判断文献层次:本文 / 义注 / 复注。引用时必须标明,混用是学术错误。"""
  39. names = {t.get('name') for t in (tags or []) if isinstance(t, dict)}
  40. if 'ṭīkā' in names:
  41. return 'ṭīkā'
  42. if 'aṭṭhakathā' in names:
  43. return 'aṭṭhakathā'
  44. if 'mūla' in names:
  45. return 'mūla'
  46. return ''