# -*- coding: utf-8 -*-"""Confluence Page Data ModelProvides the Page class for representing Confluence pages with hierarchymetadata and serialization to XML/Markdown for AI knowledge base export."""importtypingasTimportjsonimportdataclassesfromfunctoolsimportcached_propertyimportatlas_doc_parser.apiasatlas_doc_parserfromsanhe_confluence_sdk.apiimportConfluencefromsanhe_confluence_sdk.methods.page.get_pagesimport(GetPagesResponseResult,)from.constantsimportTAB,ConfluencePageFieldEnum,DescendantTypeEnumfrom.crawlerimportEntity,crawl_descendants,filter_entities
[docs]@dataclasses.dataclassclassPage:""" Confluence page with hierarchy metadata and serialization capabilities. Combines crawled entity data (hierarchy info) with fetched page content (from Confluence API) to provide a complete page representation for export. :param site_url: Base URL of the Confluence site (e.g., "https://example.atlassian.net") :param entity: Crawled entity containing hierarchy metadata (breadcrumb paths, etc.) :param result: Page content from Confluence get_pages API response The page body is expected in `Atlas Doc Format <https://developer.atlassian.com/cloud/jira/platform/apis/document/structure/>`_ which is converted to Markdown for export. """site_url:str=dataclasses.field()entity:Entity=dataclasses.field()result:GetPagesResponseResult=dataclasses.field()@cached_propertydef_formatted_site_url(self)->str:"""Site URL without trailing slash."""ifself.site_url.endswith("/"):returnself.site_url[:-1]else:returnself.site_url@cached_propertydefatlas_doc(self)->dict[str,T.Any]:"""Parsed Atlas Doc Format content as dictionary."""returnjson.loads(self.result.body.atlas_doc_format.value)@cached_propertydefwebui_url(self)->str:"""Full URL to view this page in Confluence web UI."""returnf"{self._formatted_site_url}/wiki{self.result.links.webui}"
[docs]defto_markdown(self,ignore_error:bool=True)->str:""" Convert page content to Markdown format. :param ignore_error: Skip unsupported content types instead of raising errors :returns: Markdown string with page title as H1 header """node_doc=atlas_doc_parser.NodeDoc.from_dict(dct=self.atlas_doc,)md=node_doc.to_markdown(ignore_error=ignore_error)lines=[f"# {self.result.title}","",]lines.extend(md.splitlines())md="\n".join(lines)returnmd.rstrip()
[docs]defto_xml(self,wanted_fields:T.Optional[T.Set[ConfluencePageFieldEnum]]=None,to_markdown_ignore_error:bool=True,)->str:""" Serialize page to XML format for AI knowledge base ingestion. :param wanted_fields: Fields to include; None means all fields :param to_markdown_ignore_error: Skip errors during markdown conversion :returns: XML string with document structure """ifwanted_fieldsisNone:wanted_fields={field.valueforfieldinConfluencePageFieldEnum}else:wanted_fields={field.valueforfieldinwanted_fields}lines=list()lines.append("<document>")field=ConfluencePageFieldEnum.source_type.valueiffieldinwanted_fields:lines.append(f"{TAB}<{field}>Confluence Page</{field}>")field=ConfluencePageFieldEnum.confluence_url.valueiffieldinwanted_fields:lines.append(f"{TAB}<{field}>{self.webui_url}</{field}>")field=ConfluencePageFieldEnum.title.valueiffieldinwanted_fields:lines.append(f"{TAB}<{field}>{self.result.title}</{field}>")field=ConfluencePageFieldEnum.markdown_content.valueiffieldinwanted_fields:lines.append(f"{TAB}<{field}>")lines.append(self.to_markdown(ignore_error=to_markdown_ignore_error))lines.append(f"{TAB}</{field}>")lines.append("</document>")return"\n".join(lines)
[docs]defto_json(self,wanted_fields:T.Optional[T.Set[ConfluencePageFieldEnum]]=None,to_markdown_ignore_error:bool=True,)->str:"""Serialize page to JSON format. Not yet implemented."""raiseNotImplementedError
[docs]defto_yaml(self,wanted_fields:T.Optional[T.Set[ConfluencePageFieldEnum]]=None,to_markdown_ignore_error:bool=True,)->str:"""Serialize page to YAML format. Not yet implemented."""raiseNotImplementedError