Showing
1 changed file
with
117 additions
and
0 deletions
| @@ -686,6 +686,123 @@ class ChapterGenerationNode(BaseNode): | @@ -686,6 +686,123 @@ class ChapterGenerationNode(BaseNode): | ||
| 686 | block_type = block.get("type") | 686 | block_type = block.get("type") |
| 687 | if block_type == "paragraph": | 687 | if block_type == "paragraph": |
| 688 | self._normalize_paragraph_block(block) | 688 | self._normalize_paragraph_block(block) |
| 689 | + elif block_type == "table": | ||
| 690 | + self._sanitize_table_block(block) | ||
| 691 | + | ||
| 692 | + def _sanitize_table_block(self, block: Dict[str, Any]): | ||
| 693 | + """保证表格的rows/cells结构合法且每个单元格包含至少一个block""" | ||
| 694 | + rows = self._normalize_table_rows(block.get("rows")) | ||
| 695 | + block["rows"] = rows | ||
| 696 | + | ||
| 697 | + def _normalize_table_rows(self, rows: Any) -> List[Dict[str, Any]]: | ||
| 698 | + """确保rows始终是由row对象组成的列表""" | ||
| 699 | + if rows is None: | ||
| 700 | + rows_iterable: List[Any] = [] | ||
| 701 | + elif isinstance(rows, list): | ||
| 702 | + rows_iterable = rows | ||
| 703 | + else: | ||
| 704 | + rows_iterable = [rows] | ||
| 705 | + | ||
| 706 | + normalized_rows: List[Dict[str, Any]] = [] | ||
| 707 | + for row in rows_iterable: | ||
| 708 | + sanitized_row = self._normalize_table_row(row) | ||
| 709 | + if sanitized_row: | ||
| 710 | + normalized_rows.append(sanitized_row) | ||
| 711 | + | ||
| 712 | + if not normalized_rows: | ||
| 713 | + normalized_rows.append({"cells": [self._build_default_table_cell()]}) | ||
| 714 | + return normalized_rows | ||
| 715 | + | ||
| 716 | + def _normalize_table_row(self, row: Any) -> Dict[str, Any] | None: | ||
| 717 | + """将各种行表达统一成{'cells': [...]}结构""" | ||
| 718 | + if row is None: | ||
| 719 | + return None | ||
| 720 | + if isinstance(row, dict): | ||
| 721 | + result = dict(row) | ||
| 722 | + cells_value = result.get("cells") | ||
| 723 | + else: | ||
| 724 | + result = {} | ||
| 725 | + cells_value = row | ||
| 726 | + | ||
| 727 | + cells = self._normalize_table_cells(cells_value) | ||
| 728 | + if not cells: | ||
| 729 | + cells = [self._build_default_table_cell()] | ||
| 730 | + result["cells"] = cells | ||
| 731 | + return result | ||
| 732 | + | ||
| 733 | + def _normalize_table_cells(self, cells: Any) -> List[Dict[str, Any]]: | ||
| 734 | + """清洗单元格,保证每个cell下都有非空blocks""" | ||
| 735 | + if cells is None: | ||
| 736 | + cell_entries: List[Any] = [] | ||
| 737 | + elif isinstance(cells, list): | ||
| 738 | + cell_entries = cells | ||
| 739 | + else: | ||
| 740 | + cell_entries = [cells] | ||
| 741 | + | ||
| 742 | + normalized_cells: List[Dict[str, Any]] = [] | ||
| 743 | + for cell in cell_entries: | ||
| 744 | + sanitized = self._normalize_table_cell(cell) | ||
| 745 | + if sanitized: | ||
| 746 | + normalized_cells.append(sanitized) | ||
| 747 | + | ||
| 748 | + return normalized_cells | ||
| 749 | + | ||
| 750 | + def _normalize_table_cell(self, cell: Any) -> Dict[str, Any] | None: | ||
| 751 | + """把各种单元格写法规整为schema认可的形式""" | ||
| 752 | + if cell is None: | ||
| 753 | + return {"blocks": [self._as_paragraph_block("")]} | ||
| 754 | + | ||
| 755 | + if isinstance(cell, dict): | ||
| 756 | + normalized = dict(cell) | ||
| 757 | + blocks = self._coerce_cell_blocks(normalized.get("blocks"), normalized) | ||
| 758 | + elif isinstance(cell, list): | ||
| 759 | + normalized = {} | ||
| 760 | + blocks = self._coerce_cell_blocks(cell, None) | ||
| 761 | + elif isinstance(cell, (str, int, float)): | ||
| 762 | + normalized = {} | ||
| 763 | + blocks = [self._as_paragraph_block(str(cell))] | ||
| 764 | + else: | ||
| 765 | + normalized = {} | ||
| 766 | + blocks = [self._as_paragraph_block(str(cell))] | ||
| 767 | + | ||
| 768 | + normalized["blocks"] = blocks or [self._as_paragraph_block("")] | ||
| 769 | + return normalized | ||
| 770 | + | ||
| 771 | + def _coerce_cell_blocks( | ||
| 772 | + self, blocks: Any, source: Dict[str, Any] | None | ||
| 773 | + ) -> List[Dict[str, Any]]: | ||
| 774 | + """将cell.blocks字段强制转换为合法的block数组""" | ||
| 775 | + if isinstance(blocks, list): | ||
| 776 | + entries = blocks | ||
| 777 | + elif blocks is None: | ||
| 778 | + entries = [] | ||
| 779 | + else: | ||
| 780 | + entries = [blocks] | ||
| 781 | + | ||
| 782 | + normalized_blocks: List[Dict[str, Any]] = [] | ||
| 783 | + for entry in entries: | ||
| 784 | + if isinstance(entry, dict): | ||
| 785 | + normalized_blocks.append(entry) | ||
| 786 | + elif isinstance(entry, list): | ||
| 787 | + normalized_blocks.extend(self._coerce_cell_blocks(entry, None)) | ||
| 788 | + elif isinstance(entry, (str, int, float)): | ||
| 789 | + normalized_blocks.append(self._as_paragraph_block(str(entry))) | ||
| 790 | + elif entry is None: | ||
| 791 | + continue | ||
| 792 | + else: | ||
| 793 | + normalized_blocks.append(self._as_paragraph_block(str(entry))) | ||
| 794 | + | ||
| 795 | + if normalized_blocks: | ||
| 796 | + return normalized_blocks | ||
| 797 | + | ||
| 798 | + text_hint = "" | ||
| 799 | + if isinstance(source, dict): | ||
| 800 | + text_hint = self._extract_block_text(source).strip() | ||
| 801 | + return [self._as_paragraph_block(text_hint or "--")] | ||
| 802 | + | ||
| 803 | + def _build_default_table_cell(self) -> Dict[str, Any]: | ||
| 804 | + """生成一个最小可渲染的空白单元格""" | ||
| 805 | + return {"blocks": [self._as_paragraph_block("--")]} | ||
| 689 | 806 | ||
| 690 | def _normalize_paragraph_block(self, block: Dict[str, Any]): | 807 | def _normalize_paragraph_block(self, block: Dict[str, Any]): |
| 691 | """将paragraph的inlines统一规整,剔除非法marks""" | 808 | """将paragraph的inlines统一规整,剔除非法marks""" |
-
Please register or login to post a comment