(target_path, pages)
| 518 | # ============================================================ |
| 519 | |
| 520 | def get_backlinks(target_path, pages): |
| 521 | target_path = target_path.replace("\\", "/").lstrip("./") |
| 522 | target_stem = Path(target_path).stem |
| 523 | |
| 524 | out = [] |
| 525 | for p in pages: |
| 526 | # self-link 不算反向链接(与 web/lib/kb-service.ts.getBacklinks 一致) |
| 527 | if p.path == target_path: |
| 528 | continue |
| 529 | # 在掩码后的内容上扫描(剥离代码块/行内代码里的示例链接); |
| 530 | # mask_code_spans 保留字符偏移与行号,故 context / line 仍取自原文。 |
| 531 | scan_text = mask_code_spans(p.raw_content) |
| 532 | for m in WIKILINK_RE.finditer(scan_text): |
| 533 | link_target = m.group(1) |
| 534 | link_target_norm = normalize_link_target(link_target) |
| 535 | link_stem = Path(link_target_norm).stem |
| 536 | |
| 537 | hit = (link_target_norm == target_path) or (link_stem == target_stem) |
| 538 | if not hit: |
| 539 | continue |
| 540 | |
| 541 | start = max(0, m.start() - 60) |
| 542 | end = min(len(p.raw_content), m.end() + 60) |
| 543 | context = p.raw_content[start:end].replace("\n", " ").strip() |
| 544 | line = p.raw_content[: m.start()].count("\n") + 1 |
| 545 | |
| 546 | alias, relation = split_alias_or_relation(m.group(3)) |
| 547 | out.append({ |
| 548 | "from_path": p.path, |
| 549 | "from_title": p.title, |
| 550 | "anchor": m.group(2), |
| 551 | "alias": alias, |
| 552 | "relation": relation, |
| 553 | "context": context, |
| 554 | "line": line, |
| 555 | }) |
| 556 | return out |
| 557 | |
| 558 | |
| 559 | def get_outlinks(source_path, pages): |
no test coverage detected