diff --git a/.vscode/settings.json b/.vscode/settings.json index 96daaa5..a9347ec 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -21,6 +21,7 @@ "blockquote", "levelname", "mmdc", - "scandir" + "scandir", + "webui" ] } diff --git a/README.md b/README.md index 3008abb..2bc62b9 100644 --- a/README.md +++ b/README.md @@ -125,9 +125,10 @@ Use the `--help` switch to get a full list of supported command-line options: ```console $ python3 -m md2conf --help -usage: md2conf [-h] [-d DOMAIN] [-p PATH] [-u USERNAME] [-a APIKEY] [-s SPACE] [-l {debug,info,warning,error,critical}] [-r ROOT_PAGE] - [--generated-by GENERATED_BY] [--no-generated-by] [--render-mermaid] [--no-render-mermaid] - [--render-mermaid-format {png,svg}] [--heading-anchors] [--ignore-invalid-url] [--local] +usage: md2conf [-h] [--version] [-d DOMAIN] [-p PATH] [-u USERNAME] [-a APIKEY] [-s SPACE] + [-l {debug,info,warning,error,critical}] [-r ROOT_PAGE] [--generated-by GENERATED_BY] [--no-generated-by] + [--render-mermaid] [--no-render-mermaid] [--render-mermaid-format {png,svg}] [--heading-anchors] + [--ignore-invalid-url] [--local] [--headers [KEY=VALUE ...]] [--webui-links] mdpath positional arguments: @@ -135,6 +136,7 @@ positional arguments: options: -h, --help show this help message and exit + --version show program's version number and exit -d DOMAIN, --domain DOMAIN Confluence organization domain. -p PATH, --path PATH Base path for Confluence (default: '/wiki/'). @@ -157,6 +159,9 @@ options: --heading-anchors Place an anchor at each section heading with GitHub-style same-page identifiers. --ignore-invalid-url Emit a warning but otherwise ignore relative URLs that point to ill-specified locations. --local Write XHTML-based Confluence Storage Format files locally without invoking Confluence API. + --headers [KEY=VALUE ...] + Apply custom headers to all Confluence API requests. + --webui-links Enable Confluence Web UI links. ``` ### Using the docker container diff --git a/md2conf/__main__.py b/md2conf/__main__.py index ab6d221..364dd88 100644 --- a/md2conf/__main__.py +++ b/md2conf/__main__.py @@ -4,7 +4,7 @@ import sys import typing from pathlib import Path -from typing import Any, Optional, Sequence, Union +from typing import Any, Literal, Optional, Sequence, Union import requests @@ -26,7 +26,11 @@ class Arguments(argparse.Namespace): loglevel: str ignore_invalid_url: bool heading_anchors: bool + root_page: Optional[str] generated_by: Optional[str] + render_mermaid: bool + diagram_output_format: Literal["png", "svg"] + webui_links: bool class KwargsAppendAction(argparse.Action): @@ -176,7 +180,7 @@ def main() -> None: root_page_id=args.root_page, render_mermaid=args.render_mermaid, diagram_output_format=args.diagram_output_format, - web_links=args.webui_links, + webui_links=args.webui_links, ) properties = ConfluenceProperties( args.domain, args.path, args.username, args.apikey, args.space, args.headers diff --git a/md2conf/application.py b/md2conf/application.py index adcebf6..6979d42 100644 --- a/md2conf/application.py +++ b/md2conf/application.py @@ -3,7 +3,7 @@ from pathlib import Path from typing import Dict, List, Optional -from .api import ConfluenceSession +from .api import ConfluencePage, ConfluenceSession from .converter import ( ConfluenceDocument, ConfluenceDocumentOptions, @@ -144,18 +144,8 @@ def _get_or_create_page( "expected: Confluence page ID to act as parent for Markdown files with no linked Confluence page" ) - # use file name without extension if no title is supplied - if title is None: - title = absolute_path.stem - - confluence_page = self.api.get_or_create_page( - title, parent_id.page_id, space_key=parent_id.space_key - ) - self._update_markdown( - absolute_path, - document, - confluence_page.id, - confluence_page.space_key, + confluence_page = self._create_page( + absolute_path, document, title, parent_id ) return ConfluencePageMetadata( @@ -166,7 +156,32 @@ def _get_or_create_page( title=confluence_page.title or "", ) + def _create_page( + self, + absolute_path: Path, + document: str, + title: Optional[str], + parent_id: ConfluenceQualifiedID, + ) -> ConfluencePage: + "Creates a new Confluence page when Markdown file doesn't have an embedded page ID yet." + + # use file name without extension if no title is supplied + if title is None: + title = absolute_path.stem + + confluence_page = self.api.get_or_create_page( + title, parent_id.page_id, space_key=parent_id.space_key + ) + self._update_markdown( + absolute_path, + document, + confluence_page.id, + confluence_page.space_key, + ) + return confluence_page + def _update_document(self, document: ConfluenceDocument, base_path: Path) -> None: + "Saves a new version of a Confluence document." for image in document.images: self.api.upload_attachment( diff --git a/md2conf/converter.py b/md2conf/converter.py index 8873011..10b1bc0 100644 --- a/md2conf/converter.py +++ b/md2conf/converter.py @@ -256,7 +256,7 @@ class ConfluenceConverterOptions: heading_anchors: bool = False render_mermaid: bool = False diagram_output_format: Literal["png", "svg"] = "png" - web_links: bool = False + webui_links: bool = False class ConfluenceStorageFormatConverter(NodeVisitor): @@ -358,7 +358,7 @@ def _transform_link(self, anchor: ET._Element) -> None: ) self.links.append(url) - if self.options.web_links: + if self.options.webui_links: page_url = f"{link_metadata.base_path}pages/viewpage.action?pageId={link_metadata.page_id}" else: page_url = f"{link_metadata.base_path}spaces/{link_metadata.space_key}/pages/{link_metadata.page_id}/{link_metadata.title}" @@ -841,7 +841,7 @@ class ConfluenceDocumentOptions: :param show_generated: Whether to display a prompt "This page has been generated with a tool." :param render_mermaid: Whether to pre-render Mermaid diagrams into PNG/SVG images. :param diagram_output_format: Target image format for diagrams. - :param web_links: When true, convert relative URLs to Confluence Web UI links. + :param webui_links: When true, convert relative URLs to Confluence Web UI links. """ ignore_invalid_url: bool = False @@ -850,7 +850,7 @@ class ConfluenceDocumentOptions: root_page_id: Optional[str] = None render_mermaid: bool = False diagram_output_format: Literal["png", "svg"] = "png" - web_links: bool = False + webui_links: bool = False class ConfluenceDocument: @@ -919,7 +919,7 @@ def __init__( heading_anchors=self.options.heading_anchors, render_mermaid=self.options.render_mermaid, diagram_output_format=self.options.diagram_output_format, - web_links=self.options.web_links, + webui_links=self.options.webui_links, ), path, page_metadata,