SYMBOL INDEX (845 symbols across 39 files) FILE: confluence_markdown_exporter/api_clients.py function parse_gateway_url (line 34) | def parse_gateway_url(url: str) -> tuple[str, str] | None: function build_gateway_url (line 39) | def build_gateway_url(service: str, cloud_id: str) -> str: function ensure_service_gateway_url (line 43) | def ensure_service_gateway_url(url: str, service: str | None = None) -> ... function _is_standard_atlassian_cloud_url (line 56) | def _is_standard_atlassian_cloud_url(url: str) -> bool: function _try_fetch_cloud_id (line 65) | def _try_fetch_cloud_id(base_url: str) -> str | None: function _get_confluence_sdk_url (line 79) | def _get_confluence_sdk_url(base_url: str, auth: ApiDetails) -> str: function _get_jira_sdk_url (line 86) | def _get_jira_sdk_url(base_url: str, auth: ApiDetails) -> str: function _decode_url_part (line 93) | def _decode_url_part(v: str | None) -> None | str: class ConfluenceRef (line 99) | class ConfluenceRef(BaseModel): function parse_confluence_path (line 121) | def parse_confluence_path(path: str) -> ConfluenceRef | None: class AuthNotConfiguredError (line 140) | class AuthNotConfiguredError(BaseException): method __init__ (line 147) | def __init__(self, url: str, service: str = "Confluence") -> None: class JiraAuthenticationError (line 153) | class JiraAuthenticationError(Exception): function _jira_auth_failure_hook (line 157) | def _jira_auth_failure_hook( function response_hook (line 167) | def response_hook( class ApiClientFactory (line 181) | class ApiClientFactory: method __init__ (line 184) | def __init__(self, connection_config: AtlassianSdkConnectionConfig) ->... method create_confluence (line 191) | def create_confluence(self, url: str, auth: ApiDetails) -> ConfluenceA... method create_jira (line 206) | def create_jira(self, url: str, auth: ApiDetails) -> JiraApiSdk: function get_confluence_instance (line 222) | def get_confluence_instance(url: str) -> ConfluenceApiSdk: function get_thread_confluence (line 272) | def get_thread_confluence(base_url: str) -> ConfluenceApiSdk: function get_jira_instance (line 288) | def get_jira_instance(url: str) -> JiraApiSdk: function invalidate_confluence_client (line 348) | def invalidate_confluence_client(url: str) -> None: function invalidate_jira_client (line 354) | def invalidate_jira_client(url: str) -> None: function handle_jira_auth_failure (line 360) | def handle_jira_auth_failure(url: str) -> None: FILE: confluence_markdown_exporter/config.py function callback (line 90) | def callback(ctx: typer.Context) -> None: function reset (line 113) | def reset( function path (line 151) | def path() -> None: function list_config (line 172) | def list_config( function get (line 214) | def get( function set_config (line 263) | def set_config( function edit (line 307) | def edit( function _parse_value (line 325) | def _parse_value(value_str: str) -> object: FILE: confluence_markdown_exporter/confluence.py function _rgb_to_hex (line 88) | def _rgb_to_hex(r: int, g: int, b: int) -> str: function _extract_cell_highlight_hex (line 92) | def _extract_cell_highlight_hex(el: Tag) -> str | None: function _require_dict (line 119) | def _require_dict(response: object, context: str) -> JsonResponse: function _extract_base_url (line 140) | def _extract_base_url(url: str) -> str: function _join_confluence_link (line 191) | def _join_confluence_link(data: JsonResponse, key: str) -> str: function _get_web_url (line 202) | def _get_web_url(data: JsonResponse) -> str: function _get_tiny_url (line 206) | def _get_tiny_url(data: JsonResponse) -> str: function _extract_jira_base_url (line 353) | def _extract_jira_base_url(url: str) -> str | None: class JiraIssue (line 386) | class JiraIssue(BaseModel): method from_json (line 393) | def from_json(cls, data: JsonResponse) -> "JiraIssue": method from_key (line 403) | def from_key(cls, issue_key: str, jira_url: str) -> "JiraIssue | None": method _fetch_cached (line 417) | def _fetch_cached(cls, issue_key: str, jira_url: str) -> "JiraIssue": class User (line 423) | class User(BaseModel): method from_json (line 431) | def from_json(cls, data: JsonResponse) -> "User": method from_username (line 442) | def from_username(cls, username: str, base_url: str = "") -> "User": method from_userkey (line 452) | def from_userkey(cls, userkey: str, base_url: str = "") -> "User": method from_accountid (line 462) | def from_accountid(cls, accountid: str, base_url: str = "") -> "User": class Version (line 471) | class Version(BaseModel): method from_json (line 478) | def from_json(cls, data: JsonResponse) -> "Version": class History (line 487) | class History(BaseModel): method from_json (line 492) | def from_json(cls, data: JsonResponse) -> "History": class Organization (line 499) | class Organization(BaseModel): method pages (line 504) | def pages(self) -> list["Page | Descendant"]: method export (line 507) | def export(self) -> None: method from_json (line 523) | def from_json(cls, data: JsonResponse, base_url: str) -> "Organization": method from_url (line 531) | def from_url(cls, base_url: str) -> "Organization": class Space (line 549) | class Space(BaseModel): method pages (line 557) | def pages(self) -> list["Page | Descendant"]: method export (line 567) | def export(self) -> None: method from_json (line 578) | def from_json(cls, data: JsonResponse, base_url: str) -> "Space": method from_key (line 589) | def from_key(cls, space_key: str, base_url: str) -> "Space": method from_url (line 599) | def from_url(cls, space_url: str) -> "Space": class Label (line 628) | class Label(BaseModel): method from_json (line 634) | def from_json(cls, data: JsonResponse) -> "Label": class Document (line 642) | class Document(BaseModel): method _template_vars (line 650) | def _template_vars(self) -> dict[str, str]: class Attachment (line 669) | class Attachment(Document): method extension (line 680) | def extension(self) -> str: method filename (line 689) | def filename(self) -> str: method _template_vars (line 693) | def _template_vars(self) -> dict[str, str]: method export_path (line 710) | def export_path(self) -> Path: method from_json (line 715) | def from_json(cls, data: JsonResponse, base_url: str) -> "Attachment": method from_page_id (line 743) | def from_page_id(cls, page_id: int, base_url: str) -> list["Attachment"]: method export (line 770) | def export(self) -> None: class Ancestor (line 801) | class Ancestor(Document): method from_json (line 805) | def from_json(cls, data: JsonResponse, base_url: str) -> "Ancestor": class Descendant (line 818) | class Descendant(Document): method _template_vars (line 822) | def _template_vars(self) -> dict[str, str]: method export_path (line 830) | def export_path(self) -> Path: method from_json (line 835) | def from_json(cls, data: JsonResponse, base_url: str) -> "Descendant": function _parse_image_captions (line 850) | def _parse_image_captions(storage_xml: str) -> dict[str, str]: class Page (line 879) | class Page(Document): method descendants (line 895) | def descendants(self) -> list["Descendant"]: method _template_vars (line 930) | def _template_vars(self) -> dict[str, str]: method export_path (line 938) | def export_path(self) -> Path: method html (line 943) | def html(self) -> str: method markdown (line 949) | def markdown(self) -> str: method export (line 952) | def export(self) -> dict[str, AttachmentEntry]: method export_with_descendants (line 973) | def export_with_descendants(self) -> None: method export_body (line 980) | def export_body(self) -> None: method export_markdown (line 1002) | def export_markdown(self) -> None: method _fetch_inline_comments (line 1012) | def _fetch_inline_comments(self) -> list[dict]: method _fetch_page_comments (line 1043) | def _fetch_page_comments(self) -> list[dict]: method _fetch_comment_replies (line 1074) | def _fetch_comment_replies(self, comment_id: str) -> list[dict]: method export_comments_sidecar (line 1088) | def export_comments_sidecar(self) -> None: method _render_inline_comments (line 1123) | def _render_inline_comments(self, lines: list[str], comments: list[dic... method _render_page_comments (line 1172) | def _render_page_comments(self, lines: list[str], comments: list[dict]... method _attachments_for_export (line 1212) | def _attachments_for_export(self) -> list["Attachment"]: method export_attachments (line 1231) | def export_attachments(self) -> dict[str, AttachmentEntry]: method get_attachment_by_id (line 1271) | def get_attachment_by_id(self, attachment_id: str) -> Attachment | None: method get_attachment_by_file_id (line 1284) | def get_attachment_by_file_id(self, file_id: str) -> Attachment | None: method get_attachments_by_title (line 1290) | def get_attachments_by_title(self, title: str) -> list[Attachment]: method from_json (line 1294) | def from_json(cls, data: JsonResponse, base_url: str) -> "Page": method from_id (line 1323) | def from_id(cls, page_id: int, base_url: str) -> "Page": method from_url (line 1372) | def from_url(cls, page_url: str) -> "Page": class Converter (line 1430) | class Converter(TableConverter, MarkdownConverter): class Options (line 1433) | class Options(MarkdownConverter.DefaultOptions): # type: ignore[ass... method __init__ (line 1439) | def __init__(self, page: "Page", **options) -> None: # noqa: ANN003 method _colorid_map (line 1451) | def _colorid_map(self) -> dict[str, str]: method _storage_plantuml_macros (line 1465) | def _storage_plantuml_macros(self) -> list[Tag]: method _image_captions (line 1481) | def _image_captions(self) -> dict[str, str]: method _panel_icon_map (line 1487) | def _panel_icon_map(self) -> dict[str, str]: method _extract_panel_emoji (line 1510) | def _extract_panel_emoji(macro: Tag) -> str | None: method markdown (line 1530) | def markdown(self) -> str: method front_matter (line 1541) | def front_matter(self) -> str: method _add_confluence_url_properties (line 1555) | def _add_confluence_url_properties(self) -> None: method _add_page_metadata_properties (line 1570) | def _add_page_metadata_properties(self) -> None: method breadcrumbs (line 1598) | def breadcrumbs(self) -> str: method labels (line 1607) | def labels(self) -> list[str]: method set_page_properties (line 1610) | def set_page_properties(self, **props: list[str] | str | None) -> None: method convert_page_properties (line 1615) | def convert_page_properties( method convert_alert (line 1660) | def convert_alert(self, el: BeautifulSoup, text: str, parent_tags: l... method convert_div (line 1696) | def convert_div(self, el: BeautifulSoup, text: str, parent_tags: lis... method convert_expand_container (line 1734) | def convert_expand_container( method _span_highlight (line 1754) | def _span_highlight(self, style: str, text: str) -> str | None: method _wrap_cell_highlight (line 1761) | def _wrap_cell_highlight(self, el: BeautifulSoup, text: str) -> str: method convert_td (line 1770) | def convert_td(self, el: BeautifulSoup, text: str, parent_tags: list... method convert_th (line 1774) | def convert_th(self, el: BeautifulSoup, text: str, parent_tags: list... method _span_font_color (line 1778) | def _span_font_color(self, el: BeautifulSoup, style: str, text: str)... method _span_status_badge (line 1792) | def _span_status_badge(self, el: BeautifulSoup, text: str) -> str | ... method convert_span (line 1807) | def convert_span(self, el: BeautifulSoup, text: str, parent_tags: li... method convert_inline_comment_marker (line 1835) | def convert_inline_comment_marker( method convert_attachments (line 1844) | def convert_attachments(self, el: BeautifulSoup, text: str, parent_t... method convert_column_layout (line 1877) | def convert_column_layout( method convert_jira_table (line 1889) | def convert_jira_table(self, el: BeautifulSoup, text: str, parent_ta... method convert_toc (line 1904) | def convert_toc(self, el: BeautifulSoup, text: str, parent_tags: lis... method convert_hidden_content (line 1922) | def convert_hidden_content( method convert_jira_issue (line 1930) | def convert_jira_issue(self, el: BeautifulSoup, text: str, parent_ta... method convert_pre (line 1949) | def convert_pre(self, el: BeautifulSoup, text: str, parent_tags: lis... method convert_sub (line 1964) | def convert_sub(self, el: BeautifulSoup, text: str, parent_tags: lis... method convert_sup (line 1967) | def convert_sup(self, el: BeautifulSoup, text: str, parent_tags: lis... method convert_a (line 1973) | def convert_a(self, el: BeautifulSoup, text: str, parent_tags: list[... method convert_page_link (line 2036) | def convert_page_link(self, page_id: int) -> str: method convert_attachment_link (line 2061) | def convert_attachment_link( method convert_time (line 2087) | def convert_time(self, el: BeautifulSoup, text: str, parent_tags: li... method convert_user_mention (line 2093) | def convert_user_mention(self, el: BeautifulSoup, text: str, parent_... method convert_user (line 2102) | def convert_user(self, user: User) -> str: method convert_user_name (line 2105) | def convert_user_name(self, name: str) -> str: method convert_li (line 2108) | def convert_li(self, el: BeautifulSoup, text: str, parent_tags: list... method _convert_emoticon (line 2142) | def _convert_emoticon(self, el: BeautifulSoup) -> str | None: method convert_img (line 2162) | def convert_img(self, el: BeautifulSoup, text: str, parent_tags: lis... method _normalize_unicode_whitespace (line 2222) | def _normalize_unicode_whitespace(self, text: str) -> str: method escape (line 2254) | def escape(self, text: str, parent_tags: list[str]) -> str: method _escape_template_placeholders (line 2258) | def _escape_template_placeholders(self, text: str) -> str: method convert_em (line 2303) | def convert_em(self, el: BeautifulSoup, text: str, parent_tags: list... method convert_strong (line 2308) | def convert_strong(self, el: BeautifulSoup, text: str, parent_tags: ... method convert_code (line 2313) | def convert_code(self, el: BeautifulSoup, text: str, parent_tags: li... method convert_i (line 2318) | def convert_i(self, el: BeautifulSoup, text: str, parent_tags: list[... method convert_b (line 2323) | def convert_b(self, el: BeautifulSoup, text: str, parent_tags: list[... method _convert_drawio_embedded_mermaid (line 2328) | def _convert_drawio_embedded_mermaid(self, filename: str) -> str | N... method convert_drawio (line 2350) | def convert_drawio(self, el: BeautifulSoup, text: str, parent_tags: ... method _extract_uml_from_editor2 (line 2378) | def _extract_uml_from_editor2(self, macro_id: str) -> str | None: method _extract_uml_from_storage (line 2401) | def _extract_uml_from_storage(self) -> str | None: method convert_plantuml (line 2414) | def convert_plantuml(self, el: BeautifulSoup, text: str, parent_tags... method convert_include (line 2446) | def convert_include(self, el: BeautifulSoup, text: str, parent_tags:... method _strip_excerpt_include_panel_titles (line 2483) | def _strip_excerpt_include_panel_titles(self, html: str) -> str: method _unwrap_excerpt_include_panel (line 2496) | def _unwrap_excerpt_include_panel(self, el: Tag) -> None: method _extract_include_target_title (line 2507) | def _extract_include_target_title(self, macro_id: str) -> str | None: method _find_element_with_namespace (line 2530) | def _find_element_with_namespace(self, parent: BeautifulSoup, tag_na... method _find_structured_macro (line 2535) | def _find_structured_macro(self, el: BeautifulSoup) -> Tag | None: method _extract_plain_text_body (line 2539) | def _extract_plain_text_body(self, el: BeautifulSoup | Tag) -> str |... method _extract_markdown_parameter (line 2546) | def _extract_markdown_parameter(self, el: BeautifulSoup | Tag) -> st... method _extract_markdown_from_body (line 2555) | def _extract_markdown_from_body(self, el: BeautifulSoup) -> str | None: method _extract_markdown_from_editor2 (line 2582) | def _extract_markdown_from_editor2(self, macro_id: str) -> str | None: method convert_markdown (line 2609) | def convert_markdown(self, el: BeautifulSoup, text: str, parent_tags... method convert_table (line 2637) | def convert_table(self, el: BeautifulSoup, text: str, parent_tags: l... method convert_page_properties_report (line 2643) | def convert_page_properties_report( method _cql_to_dataview (line 2661) | def _cql_to_dataview(self, el: BeautifulSoup, cql: str) -> str | None: method _get_path_for_href (line 2712) | def _get_path_for_href( function _fetch_page_ids_v2_batch (line 2732) | def _fetch_page_ids_v2_batch(batch: list[str], base_url: str) -> set[str]: function _fetch_page_ids_cql_batch (line 2746) | def _fetch_page_ids_cql_batch(batch: list[str], base_url: str) -> set[str]: function fetch_deleted_page_ids (line 2764) | def fetch_deleted_page_ids(page_ids: list[str], base_url: str) -> set[str]: function sync_removed_pages (line 2808) | def sync_removed_pages(base_url: str) -> None: function _make_progress (line 2827) | def _make_progress() -> Progress: function _export_page_worker (line 2842) | def _export_page_worker(page: "Page | Descendant", stats: ExportStats | ... function export_pages (line 2859) | def export_pages(pages: list["Page | Descendant"]) -> None: FILE: confluence_markdown_exporter/main.py class _CmeTyper (line 31) | class _CmeTyper(typer.Typer): method __call__ (line 40) | def __call__(self, *args: object, **kwargs: object) -> None: function _init_logging (line 105) | def _init_logging() -> None: function _print_summary (line 112) | def _print_summary() -> None: function pages (line 173) | def pages( function pages_with_descendants (line 253) | def pages_with_descendants( function spaces (line 314) | def spaces( function orgs (line 373) | def orgs( function version (line 415) | def version() -> None: function _redact_url (line 424) | def _redact_url(url: str) -> str: function _redact_config (line 438) | def _redact_config(data: dict) -> dict: function bugreport (line 471) | def bugreport() -> None: FILE: confluence_markdown_exporter/utils/app_data_store.py function get_app_config_path (line 23) | def get_app_config_path() -> Path: class AtlassianSdkConnectionConfig (line 39) | class AtlassianSdkConnectionConfig(BaseModel): class ConnectionConfig (line 92) | class ConnectionConfig(AtlassianSdkConnectionConfig): class ApiDetails (line 115) | class ApiDetails(BaseModel): method _single_line (line 160) | def _single_line(cls, v: object) -> object: method dump_secret (line 167) | def dump_secret(self, v: SecretStr) -> str: class AuthConfig (line 171) | class AuthConfig(BaseModel): method _migrate (line 199) | def _migrate(cls, data: object) -> object: # noqa: C901, PLR0912 method get_instance (line 245) | def get_instance(self, url: str) -> ApiDetails | None: method get_jira_instance (line 250) | def get_jira_instance(self, url: str) -> ApiDetails | None: method default_confluence_url (line 255) | def default_confluence_url(self) -> str | None: method default_jira_url (line 259) | def default_jira_url(self) -> str | None: method _match_by_host (line 264) | def _match_by_host(instances: dict[str, ApiDetails], url: str) -> ApiD... function _looks_like_url_keyed (line 290) | def _looks_like_url_keyed(d: dict) -> bool: function normalize_instance_url (line 295) | def normalize_instance_url(url: str) -> str: class ExportConfig (line 300) | class ExportConfig(BaseModel): method _migrate_attachment_path (line 398) | def _migrate_attachment_path(cls, v: object) -> object: method _migrate_page_properties (line 504) | def _migrate_page_properties(cls, data: object) -> object: method _migrate_attachments_export (line 518) | def _migrate_attachments_export(cls, data: object) -> object: method _migrate_inline_comments (line 531) | def _migrate_inline_comments(cls, data: object) -> object: class ConfigModel (line 682) | class ConfigModel(BaseModel): class _JsonConfigSource (line 692) | class _JsonConfigSource(PydanticBaseSettingsSource): method get_field_value (line 695) | def get_field_value(self, field: Any, field_name: str) -> Any: # noqa... method field_is_complex (line 698) | def field_is_complex(self, field: Any) -> bool: # noqa: ANN401 method __call__ (line 701) | def __call__(self) -> dict[str, Any]: class AppSettings (line 711) | class AppSettings(BaseSettings): method settings_customise_sources (line 737) | def settings_customise_sources( function load_app_data (line 749) | def load_app_data() -> dict[str, dict]: function save_app_data (line 761) | def save_app_data(config_model: ConfigModel) -> None: function get_settings (line 768) | def get_settings() -> AppSettings: function _set_by_path (line 773) | def _set_by_path(obj: dict, path: str, value: object) -> None: function _set_by_keys (line 784) | def _set_by_keys(obj: dict, keys: list[str], value: object) -> None: function set_setting (line 794) | def set_setting(path: str, value: object) -> None: function set_setting_with_keys (line 805) | def set_setting_with_keys(keys: list[str], value: object) -> None: function get_default_value_by_path (line 820) | def get_default_value_by_path(path: str | None = None) -> object: function reset_to_defaults (line 840) | def reset_to_defaults(path: str | None = None) -> None: FILE: confluence_markdown_exporter/utils/config_interactive.py function _get_field_type (line 33) | def _get_field_type(model: type[BaseModel], key: str) -> type | None: function _get_submodel (line 40) | def _get_submodel(model: type[BaseModel], key: str) -> type[BaseModel] |... function _get_field_metadata (line 56) | def _get_field_metadata(model: type[BaseModel], key: str) -> dict: function _format_prompt_message (line 79) | def _format_prompt_message(key_name: str, model: type[BaseModel]) -> str: function _validate_int (line 103) | def _validate_int(val: str) -> bool | str: function _validate_pydantic (line 107) | def _validate_pydantic(val: object, model: type[BaseModel], key_name: st... function _prompt_literal (line 118) | def _prompt_literal(prompt_message: str, field_type: type, current_value... function _prompt_bool (line 128) | def _prompt_bool(prompt_message: str, current_value: object) -> object: function _prompt_path (line 134) | def _prompt_path( function _prompt_int (line 148) | def _prompt_int(prompt_message: str, current_value: object) -> object: function _prompt_list (line 163) | def _prompt_list(prompt_message: str, current_value: object) -> object: function _prompt_str (line 184) | def _prompt_str( function get_model_by_path (line 198) | def get_model_by_path(model: type[BaseModel], path: str) -> type[BaseMod... function _get_dict_value_model (line 217) | def _get_dict_value_model(model: type[BaseModel], key: str) -> type[Base... function _edit_instance_fields (line 237) | def _edit_instance_fields( # noqa: C901, PLR0912 function _maybe_sync_new_instance (line 315) | def _maybe_sync_new_instance(instance_url: str, parent_path_parts: list[... function _edit_instance_dict_loop (line 348) | def _edit_instance_dict_loop( # noqa: C901, PLR0912, PLR0915 function _main_config_menu (line 448) | def _main_config_menu(settings: dict, default: tuple[str, bool] | None =... function _prompt_for_new_value (line 491) | def _prompt_for_new_value( # noqa: PLR0911 function _maybe_sync_auth_change (line 516) | def _maybe_sync_auth_change( function _reset_and_reload (line 562) | def _reset_and_reload(parent_key: str | None, display_title: str | None ... function _get_choices (line 589) | def _get_choices(config_dict: dict, model: type[BaseModel]) -> list: function _edit_dict_config_loop (line 622) | def _edit_dict_config_loop( # noqa: C901, PLR0912, PLR0915 function _edit_dict_config (line 718) | def _edit_dict_config( function main_config_menu_loop (line 728) | def main_config_menu_loop( # noqa: C901, PLR0912 FILE: confluence_markdown_exporter/utils/drawio_converter.py function load_drawio_file (line 14) | def load_drawio_file(file_path: str | Path) -> str | None: function extract_mermaid_data (line 30) | def extract_mermaid_data(xml_content: str) -> str | None: function parse_mermaid_json (line 63) | def parse_mermaid_json(mermaid_data: str) -> str | None: function format_mermaid_markdown (line 87) | def format_mermaid_markdown(mermaid_diagram: str) -> str: function load_and_parse_drawio (line 99) | def load_and_parse_drawio(file_path: str | Path) -> str | None: FILE: confluence_markdown_exporter/utils/export.py function parse_encode_setting (line 14) | def parse_encode_setting(encode_setting: str) -> dict[str, str]: function save_file (line 52) | def save_file(file_path: Path, content: str | bytes) -> None: function sanitize_filename (line 67) | def sanitize_filename(filename: str) -> str: function sanitize_key (line 123) | def sanitize_key(s: str, connector: str = "_") -> str: function github_heading_slug (line 141) | def github_heading_slug(text: str) -> str: function escape_character_class (line 153) | def escape_character_class(s: str) -> str: FILE: confluence_markdown_exporter/utils/lockfile.py class AttachmentEntry (line 31) | class AttachmentEntry(BaseModel): class PageEntry (line 38) | class PageEntry(BaseModel): class SpaceEntry (line 47) | class SpaceEntry(BaseModel): class OrgEntry (line 53) | class OrgEntry(BaseModel): class ConfluenceLock (line 59) | class ConfluenceLock(BaseModel): method load (line 67) | def load(cls, lockfile_path: Path) -> ConfluenceLock: method all_pages (line 85) | def all_pages(self) -> dict[str, PageEntry]: method get_page (line 93) | def get_page(self, page_id: str) -> PageEntry | None: method remove_page (line 101) | def remove_page(self, page_id: str) -> None: method add_page (line 107) | def add_page( method save (line 132) | def save( # noqa: C901 class LockfileManager (line 195) | class LockfileManager: method init (line 206) | def init(cls) -> None: method get_page_attachment_entries (line 232) | def get_page_attachment_entries(cls, page_id: str) -> dict[str, Attach... method record_page (line 240) | def record_page( method mark_seen (line 256) | def mark_seen(cls, page_ids: list[int]) -> None: method should_export (line 265) | def should_export(cls, page: Page | Descendant) -> bool: method unseen_ids (line 302) | def unseen_ids(cls) -> set[str]: method remove_pages (line 309) | def remove_pages(cls, deleted_ids: set[str]) -> None: FILE: confluence_markdown_exporter/utils/measure_time.py function _format_duration (line 21) | def _format_duration(delta: relativedelta) -> str: function measure_time (line 41) | def measure_time(func: Callable[P, T]) -> Callable[P, T]: function measure (line 56) | def measure(step: str) -> Generator[None, None, None]: FILE: confluence_markdown_exporter/utils/page_registry.py class PageTitleRegistry (line 17) | class PageTitleRegistry: method reset (line 30) | def reset(cls) -> None: method register (line 36) | def register(cls, page_id: int, title: str) -> None: method is_ambiguous (line 51) | def is_ambiguous(cls, title: str) -> bool: method title_count (line 55) | def title_count(cls, title: str) -> int: FILE: confluence_markdown_exporter/utils/rich_console.py function get_rich_console (line 194) | def get_rich_console(*, stderr: bool = False) -> Console: function setup_logging (line 208) | def setup_logging(log_level: str = "INFO", log_file: Path | None = None)... class ExportStats (line 242) | class ExportStats: method inc_exported (line 256) | def inc_exported(self) -> None: method inc_skipped (line 261) | def inc_skipped(self) -> None: method inc_failed (line 266) | def inc_failed(self) -> None: method inc_removed (line 271) | def inc_removed(self) -> None: method inc_attachments_exported (line 276) | def inc_attachments_exported(self) -> None: method inc_attachments_skipped (line 281) | def inc_attachments_skipped(self) -> None: method inc_attachments_failed (line 286) | def inc_attachments_failed(self) -> None: method inc_attachments_removed (line 291) | def inc_attachments_removed(self) -> None: function reset_stats (line 301) | def reset_stats(total: int = 0) -> ExportStats: function get_stats (line 315) | def get_stats() -> ExportStats: FILE: confluence_markdown_exporter/utils/table_converter.py function _get_int_attr (line 13) | def _get_int_attr(cell: Tag, attr: str, default: str = "1") -> int: function pad (line 23) | def pad(rows: list[list[Tag]]) -> list[list[Tag]]: function make_empty_cell (line 55) | def make_empty_cell() -> Tag: function _normalize_table_cell_text (line 60) | def _normalize_table_cell_text(text: str) -> str: class TableConverter (line 66) | class TableConverter(MarkdownConverter): method convert_table (line 69) | def convert_table(self, el: BeautifulSoup, text: str, parent_tags: lis... method convert_th (line 88) | def convert_th(self, el: BeautifulSoup, text: str, parent_tags: list[s... method convert_tr (line 92) | def convert_tr(self, el: BeautifulSoup, text: str, parent_tags: list[s... method convert_td (line 96) | def convert_td(self, el: BeautifulSoup, text: str, parent_tags: list[s... method convert_thead (line 100) | def convert_thead(self, el: BeautifulSoup, text: str, parent_tags: lis... method convert_tbody (line 104) | def convert_tbody(self, el: BeautifulSoup, text: str, parent_tags: lis... method _normalize_parent_tags (line 111) | def _normalize_parent_tags( method convert_ol (line 117) | def convert_ol( method convert_li (line 133) | def convert_li( method convert_ul (line 141) | def convert_ul( method convert_p (line 154) | def convert_p( FILE: confluence_markdown_exporter/utils/type_converter.py function str_to_bool (line 1) | def str_to_bool(value: str) -> bool: FILE: scripts/build-versions.mjs function sh (line 26) | function sh(cmd, opts = {}) { function tagHasDocusaurusDocs (line 30) | function tagHasDocusaurusDocs(tag) { function listTags (line 40) | function listTags() { function snapshotTag (line 49) | function snapshotTag(tag) { function main (line 71) | function main() { FILE: src/components/HomepageFeatures/index.tsx type Feature (line 6) | type Feature = { constant FEATURES (line 13) | const FEATURES: Feature[] = [ function FeatureCard (line 83) | function FeatureCard({ icon, title, description, href }: Feature) { function HomepageFeatures (line 97) | function HomepageFeatures(): ReactNode { FILE: src/components/quickstart/index.tsx function makeStepTabs (line 14) | function makeStepTabs(local: ReactNode, docker: ReactNode) { function AuthenticateTabs (line 40) | function AuthenticateTabs() { function ExportTabs (line 63) | function ExportTabs() { function VerifyTabs (line 82) | function VerifyTabs() { FILE: src/pages/index.tsx function HomepageHeader (line 16) | function HomepageHeader() { constant INSTALL_SNIPPETS (line 46) | const INSTALL_SNIPPETS = { function InstallTabs (line 63) | function InstallTabs() { function QuickstartSection (line 88) | function QuickstartSection() { function Home (line 119) | function Home(): ReactNode { FILE: tests/conftest.py function pytest_configure (line 34) | def pytest_configure(config: pytest.Config) -> None: # noqa: ARG001 function pytest_unconfigure (line 55) | def pytest_unconfigure(config: pytest.Config) -> None: # noqa: ARG001 function restore_api_functions_for_specific_tests (line 68) | def restore_api_functions_for_specific_tests( function temp_config_dir (line 111) | def temp_config_dir() -> Generator[Path, None, None]: function mock_confluence_client (line 118) | def mock_confluence_client() -> MagicMock: function mock_jira_client (line 135) | def mock_jira_client() -> MagicMock: function sample_api_details (line 156) | def sample_api_details() -> ApiDetails: function sample_connection_config (line 166) | def sample_connection_config() -> ConnectionConfig: function sample_config_model (line 179) | def sample_config_model( function confluence_page_response (line 202) | def confluence_page_response() -> dict[str, Any]: function confluence_space_response (line 234) | def confluence_space_response() -> dict[str, Any]: function jira_issue_response (line 250) | def jira_issue_response() -> dict[str, Any]: FILE: tests/integration/test_cli_integration.py function test_package_has_version (line 12) | def test_package_has_version() -> None: function test_version_command (line 19) | def test_version_command() -> None: function test_config_list_command (line 47) | def test_config_list_command() -> None: function test_cli_entry_points (line 86) | def test_cli_entry_points() -> None: FILE: tests/unit/test_alert_conversion.py function _make_converter (line 13) | def _make_converter(editor2: str = "") -> Page.Converter: function converter (line 32) | def converter() -> Page.Converter: class TestAlertOutsideTable (line 36) | class TestAlertOutsideTable: method test_panel_renders_as_note_alert (line 37) | def test_panel_renders_as_note_alert(self, converter: Page.Converter) ... method test_warning_renders_as_caution_alert (line 43) | def test_warning_renders_as_caution_alert(self, converter: Page.Conver... class TestAlertInsideTableCell (line 49) | class TestAlertInsideTableCell: method test_panel_in_td_emits_emoji_no_blockquote (line 50) | def test_panel_in_td_emits_emoji_no_blockquote(self, converter: Page.C... method test_info_in_td_emits_important_emoji (line 61) | def test_info_in_td_emits_important_emoji(self, converter: Page.Conver... method test_warning_in_td_emits_caution_emoji (line 71) | def test_warning_in_td_emits_caution_emoji(self, converter: Page.Conve... method test_tip_in_td_emits_tip_emoji (line 81) | def test_tip_in_td_emits_tip_emoji(self, converter: Page.Converter) ->... method test_note_in_td_emits_warning_emoji (line 91) | def test_note_in_td_emits_warning_emoji(self, converter: Page.Converte... method test_panel_in_th_emits_emoji_no_blockquote (line 101) | def test_panel_in_th_emits_emoji_no_blockquote(self, converter: Page.C... class TestCustomPanelEmoji (line 112) | class TestCustomPanelEmoji: method test_custom_panel_icon_text_used_in_table_cell (line 113) | def test_custom_panel_icon_text_used_in_table_cell(self) -> None: method test_custom_panel_icon_id_decoded_when_no_text (line 132) | def test_custom_panel_icon_id_decoded_when_no_text(self) -> None: method test_panel_without_custom_icon_falls_back_to_default (line 148) | def test_panel_without_custom_icon_falls_back_to_default(self) -> None: method test_unknown_macro_id_falls_back_to_default (line 163) | def test_unknown_macro_id_falls_back_to_default(self) -> None: FILE: tests/unit/test_api_clients.py class TestParseConfluencePath (line 128) | class TestParseConfluencePath: method test_parse_confluence_path (line 132) | def test_parse_confluence_path(self, url: str, expected: ConfluenceRef... class TestResponseHook (line 142) | class TestResponseHook: method test_successful_response (line 145) | def test_successful_response(self, caplog: pytest.LogCaptureFixture) -... method test_failed_response (line 156) | def test_failed_response(self, caplog: pytest.LogCaptureFixture) -> None: class TestApiClientFactory (line 174) | class TestApiClientFactory: method test_init (line 177) | def test_init(self) -> None: method test_create_confluence_success (line 185) | def test_create_confluence_success( method test_create_confluence_connection_failure (line 209) | def test_create_confluence_connection_failure( method test_create_jira_success (line 223) | def test_create_jira_success( method test_create_jira_connection_failure (line 247) | def test_create_jira_connection_failure( class TestGetConfluenceInstance (line 261) | class TestGetConfluenceInstance: method test_successful_connection (line 267) | def test_successful_connection( method test_connection_failure_raises (line 292) | def test_connection_failure_raises( class TestAuthConfigContextPath (line 313) | class TestAuthConfigContextPath: method _make_config (line 316) | def _make_config(self, key: str) -> AuthConfig: method test_get_instance_matches_context_path_url (line 337) | def test_get_instance_matches_context_path_url( method test_get_instance_no_false_match (line 357) | def test_get_instance_no_false_match(self, stored_key: str, lookup_url... FILE: tests/unit/test_confluence.py class MockPage (line 19) | class MockPage: method __init__ (line 22) | def __init__(self) -> None: method get_attachment_by_file_id (line 44) | def get_attachment_by_file_id(self, file_id: str) -> None: function converter (line 49) | def converter() -> Page.Converter: class TestSquareBracketEscaping (line 53) | class TestSquareBracketEscaping: method test_bracket_notation_escaped (line 56) | def test_bracket_notation_escaped(self, converter: Page.Converter) -> ... method test_bracket_at_start (line 61) | def test_bracket_at_start(self, converter: Page.Converter) -> None: method test_bracket_at_end (line 66) | def test_bracket_at_end(self, converter: Page.Converter) -> None: method test_multiple_bracket_groups (line 71) | def test_multiple_bracket_groups(self, converter: Page.Converter) -> N... method test_bracket_in_code_not_escaped (line 76) | def test_bracket_in_code_not_escaped(self, converter: Page.Converter) ... method test_real_link_not_affected (line 81) | def test_real_link_not_affected(self, converter: Page.Converter) -> None: class TestAnchorLinkConversion (line 87) | class TestAnchorLinkConversion: method test_anchor_uses_href_not_link_text (line 90) | def test_anchor_uses_href_not_link_text(self, converter: Page.Converte... method test_anchor_plain_heading (line 96) | def test_anchor_plain_heading(self, converter: Page.Converter) -> None: method test_anchor_with_numbers_and_punctuation (line 102) | def test_anchor_with_numbers_and_punctuation(self, converter: Page.Con... method test_wiki_anchor_uses_link_text (line 108) | def test_wiki_anchor_uses_link_text(self, converter: Page.Converter) -... function _make_attachment (line 119) | def _make_attachment( function _make_page (line 149) | def _make_page( class TestAttachmentsForExport (line 178) | class TestAttachmentsForExport: method test_file_id_in_body_included (line 181) | def test_file_id_in_body_included(self) -> None: method test_attachment_id_in_body_included (line 193) | def test_attachment_id_in_body_included(self) -> None: method test_attachment_id_in_body_export_included (line 208) | def test_attachment_id_in_body_export_included(self) -> None: method test_title_in_body_src_url_included (line 221) | def test_title_in_body_src_url_included(self) -> None: method test_title_with_spaces_url_encoded_in_body_export_included (line 236) | def test_title_with_spaces_url_encoded_in_body_export_included(self) -... method test_unreferenced_attachment_excluded (line 248) | def test_unreferenced_attachment_excluded(self) -> None: method test_attachments_export_all_returns_all (line 256) | def test_attachments_export_all_returns_all(self) -> None: class TestAttachmentsExportFlag (line 266) | class TestAttachmentsExportFlag: method _make_attachment_mock (line 269) | def _make_attachment_mock(self, att_id: str = "att-1", version: int = ... method _make_page_mock (line 276) | def _make_page_mock(self, attachments: list) -> MagicMock: method test_referenced_default_exports_attachments (line 282) | def test_referenced_default_exports_attachments(self, tmp_path: Path) ... method test_disabled_skips_download_and_lockfile (line 303) | def test_disabled_skips_download_and_lockfile(self) -> None: method test_metadata_still_populated_when_disabled (line 323) | def test_metadata_still_populated_when_disabled(self) -> None: class TestTransformErrorImg (line 385) | class TestTransformErrorImg: method test_transform_error_resolves_attachment_by_encoded_xml (line 388) | def test_transform_error_resolves_attachment_by_encoded_xml(self) -> N... class TestParseImageCaptions (line 433) | class TestParseImageCaptions: method test_cdata_caption_extracted (line 436) | def test_cdata_caption_extracted(self) -> None: method test_plain_text_caption_extracted (line 449) | def test_plain_text_caption_extracted(self) -> None: method test_paragraph_caption_extracted (line 462) | def test_paragraph_caption_extracted(self) -> None: method test_caption_with_attributes_extracted (line 474) | def test_caption_with_attributes_extracted(self) -> None: method test_image_without_caption_excluded (line 488) | def test_image_without_caption_excluded(self) -> None: method test_multiple_images_mixed (line 498) | def test_multiple_images_mixed(self) -> None: method test_empty_storage_returns_empty (line 519) | def test_empty_storage_returns_empty(self) -> None: class TestImageCaptionsInConvertImg (line 525) | class TestImageCaptionsInConvertImg: method test_caption_rendered_as_italic_below_image (line 528) | def test_caption_rendered_as_italic_below_image(self) -> None: method test_caption_disabled_preserves_original_alt (line 561) | def test_caption_disabled_preserves_original_alt(self) -> None: class TestPageFromUrl (line 591) | class TestPageFromUrl: method test_from_url_prefers_page_id_query_parameter_for_legacy_server_url (line 594) | def test_from_url_prefers_page_id_query_parameter_for_legacy_server_ur... class TestSpanHighlightConversion (line 615) | class TestSpanHighlightConversion: method test_background_color_rgb_converted_to_mark (line 618) | def test_background_color_rgb_converted_to_mark(self, converter: Page.... method test_multiple_channels_converted_correctly (line 623) | def test_multiple_channels_converted_correctly(self, converter: Page.C... method test_highlight_disabled_returns_plain_text (line 628) | def test_highlight_disabled_returns_plain_text(self, converter: Page.C... class TestCellHighlightConversion (line 638) | class TestCellHighlightConversion: method test_td_hex_attribute_wraps_in_mark (line 641) | def test_td_hex_attribute_wraps_in_mark(self, converter: Page.Converte... method test_th_hex_attribute_wraps_in_mark (line 650) | def test_th_hex_attribute_wraps_in_mark(self, converter: Page.Converte... method test_default_header_gray_not_wrapped (line 659) | def test_default_header_gray_not_wrapped(self, converter: Page.Convert... method test_transparent_attribute_not_wrapped (line 670) | def test_transparent_attribute_not_wrapped(self, converter: Page.Conve... method test_missing_attribute_not_wrapped (line 680) | def test_missing_attribute_not_wrapped(self, converter: Page.Converter... method test_invalid_hex_not_wrapped (line 688) | def test_invalid_hex_not_wrapped(self, converter: Page.Converter) -> N... method test_empty_cell_with_highlight_renders_nbsp (line 697) | def test_empty_cell_with_highlight_renders_nbsp(self, converter: Page.... method test_setting_disabled_returns_plain_text (line 706) | def test_setting_disabled_returns_plain_text(self, converter: Page.Con... class TestSpanFontColorConversion (line 721) | class TestSpanFontColorConversion: method test_inline_color_rgb_converted_to_font (line 724) | def test_inline_color_rgb_converted_to_font(self, converter: Page.Conv... method test_background_color_not_matched_as_font_color (line 729) | def test_background_color_not_matched_as_font_color(self, converter: P... method test_data_colorid_resolved_from_style_tag (line 735) | def test_data_colorid_resolved_from_style_tag(self) -> None: method test_data_colorid_unknown_falls_through (line 746) | def test_data_colorid_unknown_falls_through(self, converter: Page.Conv... method test_font_color_disabled_returns_plain_text (line 752) | def test_font_color_disabled_returns_plain_text(self, converter: Page.... class TestStatusBadgeConversion (line 762) | class TestStatusBadgeConversion: method _badge (line 765) | def _badge(self, extra_class: str, label: str) -> str: method test_gray_badge (line 771) | def test_gray_badge(self, converter: Page.Converter) -> None: method test_blue_badge (line 776) | def test_blue_badge(self, converter: Page.Converter) -> None: method test_green_badge (line 781) | def test_green_badge(self, converter: Page.Converter) -> None: method test_yellow_badge (line 786) | def test_yellow_badge(self, converter: Page.Converter) -> None: method test_red_badge (line 791) | def test_red_badge(self, converter: Page.Converter) -> None: method test_purple_badge (line 796) | def test_purple_badge(self, converter: Page.Converter) -> None: method test_badge_disabled_returns_plain_text (line 801) | def test_badge_disabled_returns_plain_text(self, converter: Page.Conve... class TestPagePropertiesFormat (line 822) | class TestPagePropertiesFormat: method _converter (line 825) | def _converter(self) -> Page.Converter: method test_frontmatter_removes_table (line 828) | def test_frontmatter_removes_table(self) -> None: method test_table_keeps_table_no_properties (line 837) | def test_table_keeps_table_no_properties(self) -> None: method test_frontmatter_and_table_keeps_both (line 845) | def test_frontmatter_and_table_keeps_both(self) -> None: method test_dataview_inline_field (line 854) | def test_dataview_inline_field(self) -> None: method test_meta_bind_view_fields (line 864) | def test_meta_bind_view_fields(self) -> None: method test_duplicate_keys_get_numeric_suffix (line 874) | def test_duplicate_keys_get_numeric_suffix(self) -> None: method test_duplicate_keys_in_inline_fields (line 892) | def test_duplicate_keys_in_inline_fields(self) -> None: class TestPagePropertiesMigration (line 909) | class TestPagePropertiesMigration: method test_old_true_maps_to_frontmatter (line 912) | def test_old_true_maps_to_frontmatter(self) -> None: method test_old_false_maps_to_table (line 918) | def test_old_false_maps_to_table(self) -> None: method test_new_field_takes_precedence_over_old (line 924) | def test_new_field_takes_precedence_over_old(self) -> None: method test_default_is_frontmatter_and_table (line 932) | def test_default_is_frontmatter_and_table(self) -> None: class TestConfluenceUrlInFrontmatter (line 939) | class TestConfluenceUrlInFrontmatter: method _converter (line 945) | def _converter(self, *, with_urls: bool = True) -> Page.Converter: method test_get_web_url_combines_base_and_webui (line 952) | def test_get_web_url_combines_base_and_webui(self) -> None: method test_get_tiny_url_combines_base_and_tinyui (line 963) | def test_get_tiny_url_combines_base_and_tinyui(self) -> None: method test_helpers_strip_redundant_separators (line 974) | def test_helpers_strip_redundant_separators(self) -> None: method test_helpers_return_empty_when_links_missing (line 985) | def test_helpers_return_empty_when_links_missing(self) -> None: method test_helpers_return_empty_when_links_not_dict (line 992) | def test_helpers_return_empty_when_links_not_dict(self) -> None: method test_helpers_return_empty_when_base_or_rel_missing (line 999) | def test_helpers_return_empty_when_base_or_rel_missing(self) -> None: method test_frontmatter_contains_webui_url_when_mode_webui (line 1005) | def test_frontmatter_contains_webui_url_when_mode_webui(self) -> None: method test_frontmatter_contains_tinyui_url_when_mode_tinyui (line 1013) | def test_frontmatter_contains_tinyui_url_when_mode_tinyui(self) -> None: method test_frontmatter_contains_both_when_mode_both (line 1021) | def test_frontmatter_contains_both_when_mode_both(self) -> None: method test_frontmatter_omits_urls_when_mode_none (line 1029) | def test_frontmatter_omits_urls_when_mode_none(self) -> None: method test_frontmatter_skips_when_url_value_is_empty (line 1037) | def test_frontmatter_skips_when_url_value_is_empty(self) -> None: method test_macro_value_takes_precedence_over_extracted_url (line 1045) | def test_macro_value_takes_precedence_over_extracted_url(self) -> None: class TestPageMetadataInFrontmatter (line 1055) | class TestPageMetadataInFrontmatter: method _make_page (line 1058) | def _make_page( method _converter (line 1085) | def _converter(self, **kwargs: object) -> Page.Converter: method test_default_disabled_writes_no_metadata (line 1088) | def test_default_disabled_writes_no_metadata(self) -> None: method test_enabled_writes_all_eight_keys (line 1103) | def test_enabled_writes_all_eight_keys(self) -> None: method test_blogpost_type_renders (line 1119) | def test_blogpost_type_renders(self) -> None: method test_macro_precedence_for_page_id (line 1127) | def test_macro_precedence_for_page_id(self) -> None: method test_macro_precedence_for_history_fields (line 1145) | def test_macro_precedence_for_history_fields( method test_empty_display_name_skipped (line 1157) | def test_empty_display_name_skipped(self) -> None: method test_empty_creator_skipped (line 1169) | def test_empty_creator_skipped(self) -> None: method test_empty_type_skipped (line 1179) | def test_empty_type_skipped(self) -> None: class TestInlineCommentsFrontMatter (line 1190) | class TestInlineCommentsFrontMatter: method test_front_matter_uses_confluence_prefix (line 1193) | def test_front_matter_uses_confluence_prefix(self) -> None: function _make_comments_page (line 1244) | def _make_comments_page( function _run_export_capturing_save (line 1269) | def _run_export_capturing_save(page: MockPage, mode: str) -> MagicMock: function _inline_comment (line 1280) | def _inline_comment( function _page_comment (line 1297) | def _page_comment( class TestPageCommentsSidecarBody (line 1315) | class TestPageCommentsSidecarBody: method test_only_footer_writes_only_page_section (line 1318) | def test_only_footer_writes_only_page_section(self) -> None: method test_all_writes_both_sections_inline_first (line 1328) | def test_all_writes_both_sections_inline_first(self) -> None: method test_none_writes_no_file (line 1341) | def test_none_writes_no_file(self) -> None: method test_inline_only_omits_page_section (line 1349) | def test_inline_only_omits_page_section(self) -> None: method test_page_comment_title_falls_back_to_comment_id (line 1361) | def test_page_comment_title_falls_back_to_comment_id(self) -> None: method test_page_comment_replies_render_under_parent (line 1370) | def test_page_comment_replies_render_under_parent(self) -> None: method test_fetch_page_comments_filters_resolved (line 1402) | def test_fetch_page_comments_filters_resolved(self) -> None: class TestPagePropertiesReportDataview (line 1427) | class TestPagePropertiesReportDataview: class _MockPageWithExport (line 1451) | class _MockPageWithExport: method __init__ (line 1452) | def __init__(self, body_export: str = "") -> None: method get_attachment_by_file_id (line 1463) | def get_attachment_by_file_id(self, file_id: str) -> None: method test_dataview_output_contains_table_clause (line 1466) | def test_dataview_output_contains_table_clause(self) -> None: method test_dataview_output_contains_from_clause (line 1476) | def test_dataview_output_contains_from_clause(self) -> None: method test_dataview_from_clause_with_current_content_ancestor (line 1484) | def test_dataview_from_clause_with_current_content_ancestor(self) -> N... method test_dataview_output_contains_label_in_from_clause (line 1503) | def test_dataview_output_contains_label_in_from_clause(self) -> None: method test_dataview_output_contains_sort_clause (line 1511) | def test_dataview_output_contains_sort_clause(self) -> None: method test_frozen_table_when_format_is_frozen (line 1519) | def test_frozen_table_when_format_is_frozen(self) -> None: class TestAttachmentTemplateVars (line 1529) | class TestAttachmentTemplateVars: method test_cloud_style_keeps_file_id (line 1532) | def test_cloud_style_keeps_file_id(self) -> None: method test_dc_style_falls_back_to_content_id (line 1537) | def test_dc_style_falls_back_to_content_id(self) -> None: method test_two_dc_attachments_get_distinct_paths (line 1542) | def test_two_dc_attachments_get_distinct_paths(self) -> None: class TestWikiLinkDisambiguation (line 1557) | class TestWikiLinkDisambiguation: method _make_target_page (line 1560) | def _make_target_page(self, page_id: int, title: str, space_key: str) ... method test_unique_title_emits_short_wiki_link (line 1595) | def test_unique_title_emits_short_wiki_link(self) -> None: method test_colliding_title_emits_path_qualified_wiki_link (line 1617) | def test_colliding_title_emits_path_qualified_wiki_link(self) -> None: method test_relative_link_unaffected (line 1644) | def test_relative_link_unaffected(self) -> None: class TestAbsoluteUrlPageLinks (line 1673) | class TestAbsoluteUrlPageLinks: method _make_target_page (line 1676) | def _make_target_page(self, page_id: int, title: str, space_key: str) ... method test_absolute_url_same_host_resolves_page (line 1711) | def test_absolute_url_same_host_resolves_page(self) -> None: method test_absolute_url_different_host_left_alone (line 1738) | def test_absolute_url_different_host_left_alone(self) -> None: method test_legacy_pageid_query_resolves_page (line 1748) | def test_legacy_pageid_query_resolves_page(self) -> None: FILE: tests/unit/test_emoticon_conversion.py function converter (line 14) | def converter() -> Page.Converter: class TestEmoticonConversion (line 31) | class TestEmoticonConversion: method test_atlassian_check_mark (line 32) | def test_atlassian_check_mark(self, converter: Page.Converter) -> None: method test_atlassian_cross_mark (line 42) | def test_atlassian_cross_mark(self, converter: Page.Converter) -> None: method test_unicode_emoji_by_hex_id (line 52) | def test_unicode_emoji_by_hex_id(self, converter: Page.Converter) -> N... method test_unicode_emoji_fallback_direct (line 62) | def test_unicode_emoji_fallback_direct(self, converter: Page.Converter... method test_custom_emoji_uuid_falls_back_to_shortname (line 71) | def test_custom_emoji_uuid_falls_back_to_shortname(self, converter: Pa... method test_non_emoticon_img_unchanged (line 81) | def test_non_emoticon_img_unchanged(self, converter: Page.Converter) -... method test_emoticon_inline_in_text (line 87) | def test_emoticon_inline_in_text(self, converter: Page.Converter) -> N... FILE: tests/unit/test_include_macro_conversion.py function _make_page (line 11) | def _make_page(editor2: str) -> MagicMock: function test_include_macro_transclusion_mode (line 43) | def test_include_macro_transclusion_mode(mock_settings: MagicMock) -> None: function test_excerpt_include_macro_transclusion_mode (line 62) | def test_excerpt_include_macro_transclusion_mode(mock_settings: MagicMoc... function test_include_macro_inline_mode (line 81) | def test_include_macro_inline_mode(mock_settings: MagicMock) -> None: function test_excerpt_include_inline_strips_source_page_title_panel (line 100) | def test_excerpt_include_inline_strips_source_page_title_panel( function test_excerpt_include_inline_keeps_body_when_no_panel (line 126) | def test_excerpt_include_inline_keeps_body_when_no_panel( function test_include_macro_transclusion_falls_back_when_target_unresolvable (line 146) | def test_include_macro_transclusion_falls_back_when_target_unresolvable( FILE: tests/unit/test_main.py class TestVersionCommand (line 10) | class TestVersionCommand: method test_version_output (line 13) | def test_version_output(self, capsys: pytest.CaptureFixture[str]) -> N... class TestAppConfiguration (line 23) | class TestAppConfiguration: method test_app_is_typer_instance (line 26) | def test_app_is_typer_instance(self) -> None: method test_app_has_commands (line 30) | def test_app_has_commands(self) -> None: method test_app_has_config_group (line 42) | def test_app_has_config_group(self) -> None: FILE: tests/unit/test_nbsp_fix.py class TestNbspPreservation (line 13) | class TestNbspPreservation: method converter (line 17) | def converter(self) -> Page.Converter: method test_em_with_leading_nbsp (line 36) | def test_em_with_leading_nbsp(self, converter: Page.Converter) -> None: method test_em_with_trailing_nbsp (line 46) | def test_em_with_trailing_nbsp(self, converter: Page.Converter) -> None: method test_em_with_both_nbsp (line 56) | def test_em_with_both_nbsp(self, converter: Page.Converter) -> None: method test_strong_with_leading_nbsp (line 65) | def test_strong_with_leading_nbsp(self, converter: Page.Converter) -> ... method test_strong_with_trailing_nbsp (line 72) | def test_strong_with_trailing_nbsp(self, converter: Page.Converter) ->... method test_code_with_leading_nbsp (line 79) | def test_code_with_leading_nbsp(self, converter: Page.Converter) -> None: method test_code_with_trailing_nbsp (line 86) | def test_code_with_trailing_nbsp(self, converter: Page.Converter) -> N... method test_i_tag_with_nbsp (line 93) | def test_i_tag_with_nbsp(self, converter: Page.Converter) -> None: method test_b_tag_with_nbsp (line 100) | def test_b_tag_with_nbsp(self, converter: Page.Converter) -> None: method test_real_world_confluence_example (line 107) | def test_real_world_confluence_example(self, converter: Page.Converter... method test_multiple_nbsp_in_sequence (line 117) | def test_multiple_nbsp_in_sequence(self, converter: Page.Converter) ->... method test_mixed_whitespace (line 124) | def test_mixed_whitespace(self, converter: Page.Converter) -> None: method test_normalize_helper_function (line 130) | def test_normalize_helper_function(self, converter: Page.Converter) ->... method test_unicode_em_space (line 148) | def test_unicode_em_space(self, converter: Page.Converter) -> None: method test_unicode_thin_space (line 158) | def test_unicode_thin_space(self, converter: Page.Converter) -> None: method test_preserves_newlines_and_tabs (line 167) | def test_preserves_newlines_and_tabs(self, converter: Page.Converter) ... method test_no_modification_when_no_unicode_whitespace (line 177) | def test_no_modification_when_no_unicode_whitespace(self, converter: P... FILE: tests/unit/test_plantuml_code_block_detection.py class TestPlantUMLCodeBlockDetection (line 11) | class TestPlantUMLCodeBlockDetection: method _make_page (line 14) | def _make_page(self) -> MagicMock: method test_pre_with_startuml_uses_plantuml_fence (line 27) | def test_pre_with_startuml_uses_plantuml_fence(self, mock_settings: Ma... method test_pre_without_startuml_keeps_original_language (line 45) | def test_pre_without_startuml_keeps_original_language(self, mock_setti... method test_pre_empty_text_returns_empty (line 63) | def test_pre_empty_text_returns_empty(self, mock_settings: MagicMock) ... method test_pre_no_language_with_startuml (line 77) | def test_pre_no_language_with_startuml(self, mock_settings: MagicMock)... FILE: tests/unit/test_plantuml_conversion.py class TestPlantUMLConversion (line 12) | class TestPlantUMLConversion: method mock_page (line 16) | def mock_page(self) -> MagicMock: method mock_server_page (line 39) | def mock_server_page(self) -> MagicMock: method test_convert_plantuml_cloud_editor2 (line 61) | def test_convert_plantuml_cloud_editor2( method test_convert_plantuml_server_storage (line 81) | def test_convert_plantuml_server_storage( method test_convert_plantuml_server_multiple_diagrams (line 101) | def test_convert_plantuml_server_multiple_diagrams( method test_convert_plantuml_no_source_available (line 144) | def test_convert_plantuml_no_source_available( method test_convert_plantuml_complex_diagram (line 171) | def test_convert_plantuml_complex_diagram(self, mock_settings: MagicMo... method test_convert_plantuml_editor2_fallback_to_storage (line 210) | def test_convert_plantuml_editor2_fallback_to_storage( method test_convert_plantuml_invalid_json_falls_through (line 251) | def test_convert_plantuml_invalid_json_falls_through( method test_convert_span_dispatches_plantuml (line 289) | def test_convert_span_dispatches_plantuml( FILE: tests/unit/test_template_placeholders.py class TestTemplatePlaceholderEscaping (line 13) | class TestTemplatePlaceholderEscaping: method converter (line 17) | def converter(self) -> Page.Converter: method test_multi_word_placeholder_escaped (line 33) | def test_multi_word_placeholder_escaped(self, converter: Page.Converte... method test_allcaps_placeholder_escaped (line 37) | def test_allcaps_placeholder_escaped(self, converter: Page.Converter) ... method test_complex_placeholder_escaped (line 43) | def test_complex_placeholder_escaped(self, converter: Page.Converter) ... method test_placeholder_with_slash_in_name_escaped (line 49) | def test_placeholder_with_slash_in_name_escaped(self, converter: Page.... method test_fake_closing_tag_placeholder_escaped (line 55) | def test_fake_closing_tag_placeholder_escaped(self, converter: Page.Co... method test_br_tag_preserved (line 59) | def test_br_tag_preserved(self, converter: Page.Converter) -> None: method test_br_with_space_preserved (line 63) | def test_br_with_space_preserved(self, converter: Page.Converter) -> N... method test_br_uppercase_preserved (line 67) | def test_br_uppercase_preserved(self, converter: Page.Converter) -> None: method test_closing_html_tag_preserved (line 71) | def test_closing_html_tag_preserved(self, converter: Page.Converter) -... method test_inline_code_not_modified (line 75) | def test_inline_code_not_modified(self, converter: Page.Converter) -> ... method test_fenced_code_block_not_modified (line 79) | def test_fenced_code_block_not_modified(self, converter: Page.Converte... method test_tilde_fenced_code_block_not_modified (line 86) | def test_tilde_fenced_code_block_not_modified(self, converter: Page.Co... method test_text_outside_code_block_still_escaped (line 91) | def test_text_outside_code_block_still_escaped(self, converter: Page.C... method test_https_autolink_preserved (line 99) | def test_https_autolink_preserved(self, converter: Page.Converter) -> ... method test_http_autolink_preserved (line 105) | def test_http_autolink_preserved(self, converter: Page.Converter) -> N... method test_mailto_autolink_preserved (line 109) | def test_mailto_autolink_preserved(self, converter: Page.Converter) ->... method test_email_autolink_preserved (line 113) | def test_email_autolink_preserved(self, converter: Page.Converter) -> ... method test_autolink_with_space_still_escaped (line 117) | def test_autolink_with_space_still_escaped(self, converter: Page.Conve... FILE: tests/unit/utils/test_app_data_store_env.py class TestEnvVarOverrides (line 17) | class TestEnvVarOverrides: method test_log_level_env_override (line 20) | def test_log_level_env_override(self) -> None: method test_output_path_env_override (line 26) | def test_output_path_env_override(self) -> None: method test_max_workers_env_override (line 32) | def test_max_workers_env_override(self) -> None: method test_verify_ssl_env_override_false (line 38) | def test_verify_ssl_env_override_false(self) -> None: method test_skip_unchanged_env_override (line 44) | def test_skip_unchanged_env_override(self) -> None: method test_save_log_to_file_default_false (line 50) | def test_save_log_to_file_default_false(self) -> None: method test_save_log_to_file_env_override (line 54) | def test_save_log_to_file_env_override(self) -> None: method test_attachments_export_env_override (line 60) | def test_attachments_export_env_override(self) -> None: method test_comments_export_env_override (line 66) | def test_comments_export_env_override(self) -> None: method test_confluence_url_in_frontmatter_env_override (line 72) | def test_confluence_url_in_frontmatter_env_override(self) -> None: method test_page_metadata_in_frontmatter_env_override (line 78) | def test_page_metadata_in_frontmatter_env_override(self) -> None: method test_env_var_does_not_persist (line 84) | def test_env_var_does_not_persist(self) -> None: method test_file_config_used_without_env_override (line 102) | def test_file_config_used_without_env_override(self) -> None: method test_env_override_takes_precedence_over_file (line 119) | def test_env_override_takes_precedence_over_file(self) -> None: method test_multiple_env_overrides (line 134) | def test_multiple_env_overrides(self) -> None: method test_page_href_env_override (line 151) | def test_page_href_env_override(self) -> None: method test_attachment_href_env_override (line 157) | def test_attachment_href_env_override(self) -> None: method test_cleanup_stale_env_override (line 163) | def test_cleanup_stale_env_override(self) -> None: method test_backoff_and_retry_env_override (line 169) | def test_backoff_and_retry_env_override(self) -> None: method test_max_backoff_seconds_env_override (line 175) | def test_max_backoff_seconds_env_override(self) -> None: method test_enable_jira_enrichment_env_override (line 181) | def test_enable_jira_enrichment_env_override(self) -> None: method test_lockfile_name_env_override (line 187) | def test_lockfile_name_env_override(self) -> None: method test_existence_check_batch_size_env_override (line 193) | def test_existence_check_batch_size_env_override(self) -> None: method test_app_settings_is_base_settings_subclass (line 199) | def test_app_settings_is_base_settings_subclass(self) -> None: method test_invalid_log_level_env_var_raises (line 205) | def test_invalid_log_level_env_var_raises(self) -> None: class TestLoadAppData (line 215) | class TestLoadAppData: method test_empty_config_file_returns_defaults (line 218) | def test_empty_config_file_returns_defaults(self) -> None: method test_invalid_json_config_file_returns_defaults (line 228) | def test_invalid_json_config_file_returns_defaults(self) -> None: class TestAttachmentPathMigration (line 239) | class TestAttachmentPathMigration: method test_title_without_extension_gets_migrated (line 242) | def test_title_without_extension_gets_migrated(self) -> None: method test_title_with_other_path_segments_migrated (line 247) | def test_title_with_other_path_segments_migrated(self) -> None: method test_title_already_has_extension_not_changed (line 252) | def test_title_already_has_extension_not_changed(self) -> None: method test_no_attachment_title_not_changed (line 258) | def test_no_attachment_title_not_changed(self) -> None: method test_migration_via_env_var (line 264) | def test_migration_via_env_var(self) -> None: class TestAttachmentsExportMigration (line 276) | class TestAttachmentsExportMigration: method test_legacy_false_maps_to_referenced (line 279) | def test_legacy_false_maps_to_referenced(self) -> None: method test_legacy_true_maps_to_all (line 284) | def test_legacy_true_maps_to_all(self) -> None: method test_new_field_takes_precedence_over_old (line 289) | def test_new_field_takes_precedence_over_old(self) -> None: class TestCommentsExportMigration (line 297) | class TestCommentsExportMigration: method test_legacy_true_maps_to_inline (line 300) | def test_legacy_true_maps_to_inline(self) -> None: method test_legacy_false_maps_to_none (line 305) | def test_legacy_false_maps_to_none(self) -> None: method test_new_field_takes_precedence_over_old (line 310) | def test_new_field_takes_precedence_over_old(self) -> None: method test_legacy_key_does_not_appear_on_model (line 317) | def test_legacy_key_does_not_appear_on_model(self) -> None: FILE: tests/unit/utils/test_drawio_converter.py class TestLoadDrawioFile (line 12) | class TestLoadDrawioFile: method test_load_existing_file (line 15) | def test_load_existing_file(self, tmp_path: Path) -> None: method test_load_nonexistent_file (line 24) | def test_load_nonexistent_file(self, tmp_path: Path) -> None: class TestExtractMermaidData (line 31) | class TestExtractMermaidData: method test_extract_valid_mermaid_data (line 34) | def test_extract_valid_mermaid_data(self) -> None: method test_extract_no_mermaid_data (line 51) | def test_extract_no_mermaid_data(self) -> None: method test_extract_invalid_xml (line 66) | def test_extract_invalid_xml(self) -> None: class TestParseMermaidJson (line 73) | class TestParseMermaidJson: method test_parse_json_with_data_field (line 76) | def test_parse_json_with_data_field(self) -> None: method test_parse_plain_diagram (line 82) | def test_parse_plain_diagram(self) -> None: method test_parse_malformed_json (line 88) | def test_parse_malformed_json(self) -> None: class TestFormatMermaidMarkdown (line 95) | class TestFormatMermaidMarkdown: method test_format_diagram (line 98) | def test_format_diagram(self) -> None: class TestLoadAndParseDrawio (line 105) | class TestLoadAndParseDrawio: method test_full_pipeline (line 108) | def test_full_pipeline(self, tmp_path: Path) -> None: method test_nonexistent_file (line 132) | def test_nonexistent_file(self, tmp_path: Path) -> None: method test_file_without_mermaid_data (line 137) | def test_file_without_mermaid_data(self, tmp_path: Path) -> None: FILE: tests/unit/utils/test_export.py class TestParseEncodeSetting (line 18) | class TestParseEncodeSetting: method test_empty_string (line 21) | def test_empty_string(self) -> None: method test_simple_mapping (line 26) | def test_simple_mapping(self) -> None: method test_mixed_mapping (line 32) | def test_mixed_mapping(self) -> None: method test_equals_mapping (line 38) | def test_equals_mapping(self) -> None: method test_special_characters (line 44) | def test_special_characters(self) -> None: method test_invalid_json (line 50) | def test_invalid_json(self) -> None: method test_non_dict_json (line 55) | def test_non_dict_json(self) -> None: method test_malformed_json (line 60) | def test_malformed_json(self) -> None: class TestSaveFile (line 66) | class TestSaveFile: method test_save_string_content (line 69) | def test_save_string_content(self) -> None: method test_save_bytes_content (line 80) | def test_save_bytes_content(self) -> None: method test_create_parent_directories (line 91) | def test_create_parent_directories(self) -> None: method test_overwrite_existing_file (line 102) | def test_overwrite_existing_file(self) -> None: method test_invalid_content_type (line 114) | def test_invalid_content_type(self) -> None: class TestSanitizeFilename (line 123) | class TestSanitizeFilename: method test_no_encoding_specified (line 127) | def test_no_encoding_specified(self, mock_export_options: MagicMock) -... method test_with_encoding_mapping (line 137) | def test_with_encoding_mapping(self, mock_export_options: MagicMock) -... method test_with_encoding_mapping_lowercase (line 147) | def test_with_encoding_mapping_lowercase(self, mock_export_options: Ma... method test_trim_trailing_spaces_and_dots (line 157) | def test_trim_trailing_spaces_and_dots(self, mock_export_options: Magi... method test_reserved_windows_names (line 167) | def test_reserved_windows_names(self, mock_export_options: MagicMock) ... method test_filename_length_limit (line 183) | def test_filename_length_limit(self, mock_export_options: MagicMock) -... method test_complex_filename_sanitization (line 194) | def test_complex_filename_sanitization(self, mock_export_options: Magi... method test_control_characters_removed (line 206) | def test_control_characters_removed(self, mock_export_options: MagicMo... method test_multiple_control_characters (line 215) | def test_multiple_control_characters(self, mock_export_options: MagicM... class TestSanitizeKey (line 224) | class TestSanitizeKey: method test_basic_string (line 227) | def test_basic_string(self) -> None: method test_special_characters (line 232) | def test_special_characters(self) -> None: method test_multiple_underscores_collapse (line 237) | def test_multiple_underscores_collapse(self) -> None: method test_trim_leading_trailing_underscores (line 242) | def test_trim_leading_trailing_underscores(self) -> None: method test_starts_with_number (line 247) | def test_starts_with_number(self) -> None: method test_starts_with_special_character (line 252) | def test_starts_with_special_character(self) -> None: method test_custom_connector (line 259) | def test_custom_connector(self) -> None: method test_already_valid_key (line 264) | def test_already_valid_key(self) -> None: method test_empty_string (line 269) | def test_empty_string(self) -> None: method test_only_special_characters (line 274) | def test_only_special_characters(self) -> None: class TestGithubHeadingSlug (line 280) | class TestGithubHeadingSlug: method test_leading_hyphen_preserved (line 283) | def test_leading_hyphen_preserved(self) -> None: method test_plain_heading (line 287) | def test_plain_heading(self) -> None: method test_uppercase (line 290) | def test_uppercase(self) -> None: method test_special_chars_removed (line 293) | def test_special_chars_removed(self) -> None: method test_multiple_spaces_collapsed (line 296) | def test_multiple_spaces_collapsed(self) -> None: method test_trailing_hyphen (line 299) | def test_trailing_hyphen(self) -> None: method test_empty_string (line 302) | def test_empty_string(self) -> None: class TestEscapeCharacterClass (line 306) | class TestEscapeCharacterClass: method test_escape_backslash (line 309) | def test_escape_backslash(self) -> None: method test_escape_dash (line 314) | def test_escape_dash(self) -> None: method test_escape_right_bracket (line 319) | def test_escape_right_bracket(self) -> None: method test_escape_caret (line 324) | def test_escape_caret(self) -> None: method test_escape_multiple_characters (line 329) | def test_escape_multiple_characters(self) -> None: method test_no_special_characters (line 334) | def test_no_special_characters(self) -> None: method test_mixed_characters (line 339) | def test_mixed_characters(self) -> None: method test_empty_string (line 344) | def test_empty_string(self) -> None: FILE: tests/unit/utils/test_lockfile.py function _make_mock_page (line 23) | def _make_mock_page( function _lock_with_pages (line 42) | def _lock_with_pages( function _lock_data (line 58) | def _lock_data( function _reset_lockfile_manager (line 79) | def _reset_lockfile_manager() -> None: class TestLockfileManagerInit (line 88) | class TestLockfileManagerInit: method test_init_creates_empty_lock_when_no_lockfile (line 92) | def test_init_creates_empty_lock_when_no_lockfile( method test_init_loads_existing_lockfile (line 108) | def test_init_loads_existing_lockfile( method test_init_snapshots_all_entries (line 130) | def test_init_snapshots_all_entries( method test_init_discards_v1_lockfile (line 151) | def test_init_discards_v1_lockfile( class TestLockfileManagerRecordPage (line 175) | class TestLockfileManagerRecordPage: method test_record_page_creates_lockfile (line 178) | def test_record_page_creates_lockfile(self) -> None: method test_record_page_does_nothing_when_not_initialized (line 194) | def test_record_page_does_nothing_when_not_initialized(self) -> None: method test_record_page_updates_existing_entry (line 201) | def test_record_page_updates_existing_entry(self) -> None: method test_record_page_adds_to_seen_page_ids (line 217) | def test_record_page_adds_to_seen_page_ids(self) -> None: method test_record_page_across_multiple_orgs_and_spaces (line 229) | def test_record_page_across_multiple_orgs_and_spaces(self) -> None: class TestLockfileManagerShouldExport (line 250) | class TestLockfileManagerShouldExport: method test_page_not_in_lockfile_should_export (line 253) | def test_page_not_in_lockfile_should_export(self) -> None: method test_page_in_lockfile_same_version_same_path_should_not_export (line 262) | def test_page_in_lockfile_same_version_same_path_should_not_export(sel... method test_page_in_lockfile_different_version_should_export (line 271) | def test_page_in_lockfile_different_version_should_export(self) -> None: method test_page_in_lockfile_different_export_path_should_export (line 280) | def test_page_in_lockfile_different_export_path_should_export(self) ->... method test_lock_is_none_should_export (line 289) | def test_lock_is_none_should_export(self) -> None: method test_missing_output_file_should_export (line 296) | def test_missing_output_file_should_export(self) -> None: method test_existing_output_file_unchanged_should_not_export (line 309) | def test_existing_output_file_unchanged_should_not_export(self) -> None: class TestLockfileManagerMarkSeen (line 326) | class TestLockfileManagerMarkSeen: method test_mark_seen_adds_page_ids (line 329) | def test_mark_seen_adds_page_ids(self) -> None: method test_mark_seen_accumulates (line 334) | def test_mark_seen_accumulates(self) -> None: class TestLockfileManagerCleanup (line 341) | class TestLockfileManagerCleanup: method test_cleanup_noop_when_not_initialized (line 344) | def test_cleanup_noop_when_not_initialized(self) -> None: method test_cleanup_deletes_file_for_removed_page (line 348) | def test_cleanup_deletes_file_for_removed_page(self) -> None: method test_cleanup_removes_entry_from_lockfile (line 369) | def test_cleanup_removes_entry_from_lockfile(self) -> None: method test_cleanup_deletes_old_file_for_moved_page (line 390) | def test_cleanup_deletes_old_file_for_moved_page(self) -> None: method test_cleanup_keeps_page_existing_on_confluence (line 413) | def test_cleanup_keeps_page_existing_on_confluence(self) -> None: method test_cleanup_keeps_unchanged_seen_pages (line 435) | def test_cleanup_keeps_unchanged_seen_pages(self) -> None: method test_cleanup_handles_already_deleted_file (line 451) | def test_cleanup_handles_already_deleted_file(self) -> None: method test_cleanup_api_failure_keeps_pages (line 466) | def test_cleanup_api_failure_keeps_pages(self) -> None: class TestFetchDeletedPageIds (line 490) | class TestFetchDeletedPageIds: method test_empty_input_returns_empty (line 493) | def test_empty_input_returns_empty(self) -> None: method test_returns_deleted_ids (line 502) | def test_returns_deleted_ids( method test_api_error_returns_no_deleted_ids (line 521) | def test_api_error_returns_no_deleted_ids( method test_batches_large_sets (line 538) | def test_batches_large_sets( class TestConfluenceLockSave (line 556) | class TestConfluenceLockSave: method test_save_is_atomic_on_success (line 559) | def test_save_is_atomic_on_success(self) -> None: method test_save_windows_permission_error_fallback (line 576) | def test_save_windows_permission_error_fallback(self) -> None: method test_save_cleans_up_tmp_on_error (line 597) | def test_save_cleans_up_tmp_on_error(self) -> None: method test_save_preserves_original_on_error (line 617) | def test_save_preserves_original_on_error(self) -> None: method test_save_with_delete_ids (line 645) | def test_save_with_delete_ids(self) -> None: class TestConfluenceLockSaveSortsKeys (line 662) | class TestConfluenceLockSaveSortsKeys: method test_save_sorts_page_keys (line 665) | def test_save_sorts_page_keys(self) -> None: method test_save_preserves_model_field_order (line 683) | def test_save_preserves_model_field_order(self) -> None: method test_save_sorts_spaces_and_orgs (line 698) | def test_save_sorts_spaces_and_orgs(self) -> None: class TestAttachmentEntryTracking (line 725) | class TestAttachmentEntryTracking: method test_page_entry_stores_attachments (line 728) | def test_page_entry_stores_attachments(self) -> None: method test_page_entry_attachments_default_empty (line 741) | def test_page_entry_attachments_default_empty(self) -> None: method test_lock_file_roundtrip_with_attachments (line 746) | def test_lock_file_roundtrip_with_attachments(self) -> None: method test_lock_file_missing_attachments_field_loads_as_empty (line 769) | def test_lock_file_missing_attachments_field_loads_as_empty(self) -> N... method test_record_page_stores_attachment_entries (line 784) | def test_record_page_stores_attachment_entries(self) -> None: method test_get_page_attachment_entries_returns_entries (line 803) | def test_get_page_attachment_entries_returns_entries(self) -> None: method test_get_page_attachment_entries_returns_empty_for_unknown_page (line 820) | def test_get_page_attachment_entries_returns_empty_for_unknown_page(se... method test_get_page_attachment_entries_returns_empty_when_not_initialized (line 825) | def test_get_page_attachment_entries_returns_empty_when_not_initialize... FILE: tests/unit/utils/test_measure_time.py class TestMeasureTime (line 14) | class TestMeasureTime: method test_measure_time_decorator_logs (line 17) | def test_measure_time_decorator_logs(self, caplog: pytest.LogCaptureFi... method test_measure_time_with_exception (line 35) | def test_measure_time_with_exception(self, caplog: pytest.LogCaptureFi... method test_measure_time_with_return_value (line 52) | def test_measure_time_with_return_value(self) -> None: method test_measure_time_with_args_kwargs (line 62) | def test_measure_time_with_args_kwargs(self) -> None: class TestMeasureContextManager (line 73) | class TestMeasureContextManager: method test_measure_success (line 76) | def test_measure_success(self) -> None: method test_measure_with_exception (line 81) | def test_measure_with_exception(self) -> None: method test_measure_debug_logs_start (line 91) | def test_measure_debug_logs_start(self, caplog: pytest.LogCaptureFixtu... method test_measure_timing_calculation (line 103) | def test_measure_timing_calculation(self, mock_datetime: pytest.Monkey... method test_measure_no_exception_propagation (line 113) | def test_measure_no_exception_propagation(self) -> None: FILE: tests/unit/utils/test_page_registry.py function _clean_registry (line 11) | def _clean_registry() -> None: function test_unique_title_not_ambiguous (line 17) | def test_unique_title_not_ambiguous() -> None: function test_two_pages_same_title_ambiguous (line 22) | def test_two_pages_same_title_ambiguous() -> None: function test_unknown_title_not_ambiguous (line 28) | def test_unknown_title_not_ambiguous() -> None: function test_re_register_same_id_does_not_inflate_count (line 32) | def test_re_register_same_id_does_not_inflate_count() -> None: function test_renaming_page_updates_counts (line 40) | def test_renaming_page_updates_counts() -> None: function test_reset_clears_state (line 51) | def test_reset_clears_state() -> None: function test_blank_inputs_ignored (line 59) | def test_blank_inputs_ignored() -> None: FILE: tests/unit/utils/test_rich_console.py function test_setup_logging_writes_to_file (line 9) | def test_setup_logging_writes_to_file(tmp_path: Path) -> None: function test_setup_logging_without_file_does_not_create_one (line 26) | def test_setup_logging_without_file_does_not_create_one(tmp_path: Path) ... FILE: tests/unit/utils/test_table_converter.py class TestTableConverter (line 8) | class TestTableConverter: method test_pipe_character_in_cell (line 11) | def test_pipe_character_in_cell(self) -> None: method test_multiple_pipes_in_cell (line 37) | def test_multiple_pipes_in_cell(self) -> None: method test_pipe_character_in_header (line 60) | def test_pipe_character_in_header(self) -> None: method test_table_without_pipes (line 83) | def test_table_without_pipes(self) -> None: method test_convert_p_bool_parent_tags_no_crash (line 110) | def test_convert_p_bool_parent_tags_no_crash(self) -> None: method test_convert_ol_bool_parent_tags_no_crash (line 118) | def test_convert_ol_bool_parent_tags_no_crash(self) -> None: method test_convert_ul_bool_parent_tags_no_crash (line 126) | def test_convert_ul_bool_parent_tags_no_crash(self) -> None: method test_single_item_ul_in_cell_strips_list_symbol (line 134) | def test_single_item_ul_in_cell_strips_list_symbol(self) -> None: method test_multi_item_ul_in_cell_keeps_list_symbols (line 152) | def test_multi_item_ul_in_cell_keeps_list_symbols(self) -> None: method test_ol_in_cell_with_empty_paragraph_shows_number (line 170) | def test_ol_in_cell_with_empty_paragraph_shows_number(self) -> None: method test_ol_in_cell_with_empty_paragraph_respects_start (line 182) | def test_ol_in_cell_with_empty_paragraph_respects_start(self) -> None: method test_ol_in_cell_with_content (line 194) | def test_ol_in_cell_with_content(self) -> None: method test_ul_in_cell_with_paragraph_items (line 208) | def test_ul_in_cell_with_paragraph_items(self) -> None: method test_td_detection_still_works_with_set_parent_tags (line 222) | def test_td_detection_still_works_with_set_parent_tags(self) -> None: FILE: tests/unit/utils/test_type_converter.py class TestStrToBool (line 8) | class TestStrToBool: method test_true_values (line 11) | def test_true_values(self) -> None: method test_false_values (line 17) | def test_false_values(self) -> None: method test_whitespace_handling (line 34) | def test_whitespace_handling(self) -> None: method test_invalid_values (line 41) | def test_invalid_values(self) -> None: method test_empty_string (line 48) | def test_empty_string(self) -> None: method test_none_handling (line 53) | def test_none_handling(self) -> None: