Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -128,5 +128,9 @@ dmypy.json
# Pyre type checker
.pyre/

# branch feature_ha_append_page_metadata
tmp
appTest.py

# End of https://www.gitignore.io/api/code,python

48 changes: 41 additions & 7 deletions confluence_markdown_exporter/confluence.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
from typing import TypeAlias
from typing import cast

import json
from datetime import datetime, timedelta

import jmespath
import yaml
from atlassian.errors import ApiError
Expand Down Expand Up @@ -324,6 +327,30 @@ class Page(Document):
editor2: str
labels: list["Label"]
attachments: list["Attachment"]
page_metadata: str

@staticmethod
def get_custom_metadata(response: dict | None) -> dict:
if response is None:
return {}
custom_metadata = {
'id' : response.get('id',''),
'title' : response.get('title',''),
'type' : response.get('type',''),
'created' : response.get('history', {}).get('createdDate',''),
'author' : response.get('history', {}).get('createdBy', {}).get('displayName',''),
'version' : response.get('version', {}).get('number','1'),
'lastModified' : response.get('version', {}).get('when',''),
'lastModifiedBy' : response.get('version', {}).get('by', {}).get('displayName',''),
'lastModifiedWithin365Days': response.get('version', {}).get('when','')[10] >= (datetime.now()-timedelta(days=365)).strftime('%Y-%m-%d') if response.get('version', {}).get('when','') else False,
'pageURL' : f"""{response.get('_links', {}).get('base','')}/{response.get('_links', {}).get('webui','')}""",
# 'pageURL' : f"""{response.get('_links', {}).get('base','')}/pages/viewpage.action?pageId={response.get('id','')}""",
}
custom_metadata_html = "<table>\n"
custom_metadata_html += "".join(f"<tr><td>{key}</td><td>{value}</td></tr>\n" for key, value in custom_metadata.items())
custom_metadata_html += "</table>\n"
response['page_metadata'] = custom_metadata_html
return response

@property
def descendants(self) -> list[int]:
Expand Down Expand Up @@ -382,9 +409,12 @@ def export_path(self) -> Path:

@property
def html(self) -> str:
body = self.body
if settings.export.include_document_title:
return f"<h1>{self.title}</h1>{self.body}"
return self.body
body = f"<h1>{self.title}</h1>{self.body}"
if settings.export.include_document_metadata:
body = f"{body}<br><br><br><h3>Metadata:</h3><br>{self.page_metadata}"
return body

@property
def markdown(self) -> str:
Expand Down Expand Up @@ -486,20 +516,23 @@ def from_json(cls, data: JsonResponse) -> "Page":
],
attachments=Attachment.from_page_id(data.get("id", 0)),
ancestors=[ancestor.get("id") for ancestor in data.get("ancestors", [])][1:],
page_metadata=data.get("page_metadata", ""),
)

@classmethod
@functools.lru_cache(maxsize=1000)
def from_id(cls, page_id: int) -> "Page":
try:
response = confluence.get_page_by_id(
page_id,
expand="body.view,body.export_view,body.editor2,metadata.labels,"
"metadata.properties,ancestors,history,version",
)
response = cls.get_custom_metadata(response)
return cls.from_json(
cast(
JsonResponse,
confluence.get_page_by_id(
page_id,
expand="body.view,body.export_view,body.editor2,metadata.labels,"
"metadata.properties,ancestors",
),
response,
)
)
except (ApiError, HTTPError) as e:
Expand All @@ -515,6 +548,7 @@ def from_id(cls, page_id: int) -> "Page":
labels=[],
attachments=[],
ancestors=[],
page_metadata="",
)

@classmethod
Expand Down
8 changes: 8 additions & 0 deletions confluence_markdown_exporter/utils/app_data_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,14 @@ class ExportConfig(BaseModel):
"If enabled, the title will be added as a top-level heading."
),
)
include_document_metadata: bool = Field(
default=False,
title="Include Document Metadata",
description=(
"Whether to include document metadata (like author, last modified date) "
"at the bottom of the exported markdown file."
),
)


class ConfigModel(BaseModel):
Expand Down