""" GB 7714 《文后参考文献著录规则》顺序编码制 — 参考文献解析与格式化。 将 Markdown 中 ``[N] ... [TYPE] ...`` 格式的参考文献逐条解析, 按文献类型(书 M、期刊 J、会议 C、学位论文 D、标准 S、电子资源 EB/OL 等) 重新编排为符合 GB 7714 规范的格式,并输出为独立段落。 """ import re from typing import Optional # 单行匹配: [N] 开头 _RE_LINE = re.compile(r"^\[(\d+)\]\s*(.*)$") # 文献类型标记: [M] [J] [C] [D] [S] [EB/OL] [P] [N] _RE_TYPE = re.compile(r"\[(\w+(?:/\w+)?)\]") # GB 7714 中各文献类型的标准格式模板(仅用于说明,实际格式化直接拼接) TYPE_LABELS: dict[str, str] = { "M": "专著", "J": "期刊文章", "C": "会议论文", "D": "学位论文", "S": "标准", "EB/OL": "电子资源", "P": "专利", "N": "报纸文章", } def parse_reference_line(line: str) -> Optional[dict]: """解析单行参考文献,提取序号、作者+标题、文献类型、来源信息。 期望格式:: [N] Authors. Title[TYPE]. Source info. """ line = line.strip() m = _RE_LINE.match(line) if not m: return None number = int(m.group(1)) rest = m.group(2).strip() # 定位文献类型标记 [TYPE] tm = _RE_TYPE.search(rest) if not tm: return None before_type = rest[: tm.start()].strip().rstrip(".") doc_type = tm.group(1) after_type = rest[tm.end() :].strip().lstrip(".").strip() return { "number": number, "before_type": before_type, # "Authors. Title" "doc_type": doc_type, # "M", "J", "EB/OL", … "after_type": after_type, # 来源信息 } def _normalize_period(text: str) -> str: """确保文本以英文句点结尾(GB 7714 要求)。""" text = text.rstrip() if text and not text.endswith("."): text += "." return text def format_gb7714(ref: dict) -> str: """按 GB 7714 重新编排一条参考文献(不含序号前缀,由 Word 样式自动编号)。 格式:: Authors. Title[TYPE]. Source. """ bt = ref["before_type"] dt = ref["doc_type"] at = ref["after_type"] formatted = f"{bt}[{dt}]. {at}" return _normalize_period(formatted) def references_to_paragraphs( ref_text: str, ref_style: str = "列出段落1", ) -> list[dict]: """将参考文献原始文本转换为格式化段落列表。 返回的每个元素:: {"text": str, "level": 0, "style": ref_style} 每条参考文献为一个独立段落。 """ if not ref_text or ref_text == "": return [{"text": "", "level": 0, "style": ref_style}] lines = [l.strip() for l in ref_text.strip().split("\n") if l.strip()] paragraphs: list[dict] = [] for line in lines: ref = parse_reference_line(line) if ref: formatted = format_gb7714(ref) ref_id = ref["number"] else: # 无法解析时,至少去掉 [N] 前缀 fallback = re.sub(r"^\[\d+\]\s*", "", line) formatted = _normalize_period(fallback) ref_id = None paragraphs.append( {"text": formatted, "level": 0, "style": ref_style, "ref_id": ref_id} ) return paragraphs