notionary 0.2.26__py3-none-any.whl → 0.2.28__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- notionary/__init__.py +5 -20
- notionary/blocks/client.py +87 -215
- notionary/blocks/enums.py +167 -0
- notionary/blocks/rich_text/markdown_rich_text_converter.py +266 -0
- notionary/blocks/rich_text/models.py +164 -0
- notionary/blocks/rich_text/name_id_resolver/__init__.py +11 -0
- notionary/blocks/rich_text/name_id_resolver/database.py +31 -0
- notionary/blocks/rich_text/name_id_resolver/page.py +34 -0
- notionary/blocks/rich_text/name_id_resolver/person.py +37 -0
- notionary/blocks/rich_text/name_id_resolver/port.py +11 -0
- notionary/blocks/rich_text/rich_text_markdown_converter.py +132 -0
- notionary/blocks/rich_text/rich_text_patterns.py +39 -0
- notionary/blocks/schemas.py +746 -0
- notionary/comments/client.py +52 -187
- notionary/comments/factory.py +40 -0
- notionary/comments/models.py +5 -127
- notionary/comments/schemas.py +240 -0
- notionary/comments/service.py +34 -0
- notionary/data_source/http/client.py +11 -0
- notionary/data_source/http/data_source_instance_client.py +94 -0
- notionary/data_source/properties/models.py +406 -0
- notionary/data_source/query/builder.py +429 -0
- notionary/data_source/query/resolver.py +114 -0
- notionary/data_source/query/schema.py +304 -0
- notionary/data_source/query/validator.py +73 -0
- notionary/data_source/schemas.py +27 -0
- notionary/data_source/service.py +353 -0
- notionary/database/client.py +30 -135
- notionary/database/database_metadata_update_client.py +19 -0
- notionary/database/schemas.py +29 -0
- notionary/database/service.py +169 -0
- notionary/exceptions/__init__.py +33 -0
- notionary/exceptions/api.py +41 -0
- notionary/exceptions/base.py +2 -0
- notionary/exceptions/block_parsing.py +16 -0
- notionary/exceptions/data_source/__init__.py +6 -0
- notionary/exceptions/data_source/builder.py +182 -0
- notionary/exceptions/data_source/properties.py +34 -0
- notionary/exceptions/properties.py +58 -0
- notionary/exceptions/search.py +33 -0
- notionary/file_upload/client.py +18 -30
- notionary/file_upload/models.py +7 -8
- notionary/file_upload/{notion_file_upload.py → service.py} +29 -64
- notionary/http/client.py +205 -0
- notionary/http/models.py +49 -0
- notionary/page/blocks/client.py +1 -0
- notionary/page/content/factory.py +68 -0
- notionary/page/content/markdown/__init__.py +5 -0
- notionary/page/content/markdown/builder.py +304 -0
- notionary/page/content/markdown/nodes/__init__.py +54 -0
- notionary/page/content/markdown/nodes/audio.py +23 -0
- notionary/page/content/markdown/nodes/base.py +12 -0
- notionary/page/content/markdown/nodes/bookmark.py +25 -0
- notionary/page/content/markdown/nodes/breadcrumb.py +14 -0
- notionary/page/content/markdown/nodes/bulleted_list.py +18 -0
- notionary/page/content/markdown/nodes/callout.py +32 -0
- notionary/page/content/markdown/nodes/code.py +30 -0
- notionary/page/content/markdown/nodes/columns.py +51 -0
- notionary/page/content/markdown/nodes/divider.py +14 -0
- notionary/page/content/markdown/nodes/embed.py +23 -0
- notionary/page/content/markdown/nodes/equation.py +19 -0
- notionary/page/content/markdown/nodes/file.py +23 -0
- notionary/page/content/markdown/nodes/heading.py +16 -0
- notionary/page/content/markdown/nodes/image.py +23 -0
- notionary/page/content/markdown/nodes/mixins/caption.py +12 -0
- notionary/page/content/markdown/nodes/numbered_list.py +15 -0
- notionary/page/content/markdown/nodes/paragraph.py +14 -0
- notionary/page/content/markdown/nodes/pdf.py +23 -0
- notionary/page/content/markdown/nodes/quote.py +15 -0
- notionary/page/content/markdown/nodes/space.py +14 -0
- notionary/page/content/markdown/nodes/table.py +45 -0
- notionary/page/content/markdown/nodes/table_of_contents.py +14 -0
- notionary/page/content/markdown/nodes/todo.py +22 -0
- notionary/page/content/markdown/nodes/toggle.py +28 -0
- notionary/page/content/markdown/nodes/toggleable_heading.py +35 -0
- notionary/page/content/markdown/nodes/video.py +23 -0
- notionary/page/content/parser/context.py +49 -0
- notionary/page/content/parser/factory.py +219 -0
- notionary/page/content/parser/parsers/__init__.py +60 -0
- notionary/page/content/parser/parsers/audio.py +40 -0
- notionary/page/content/parser/parsers/base.py +30 -0
- notionary/page/content/parser/parsers/bookmark.py +33 -0
- notionary/page/content/parser/parsers/breadcrumb.py +33 -0
- notionary/page/content/parser/parsers/bulleted_list.py +41 -0
- notionary/page/content/parser/parsers/callout.py +129 -0
- notionary/page/content/parser/parsers/caption.py +55 -0
- notionary/page/content/parser/parsers/code.py +81 -0
- notionary/page/content/parser/parsers/column.py +117 -0
- notionary/page/content/parser/parsers/column_list.py +81 -0
- notionary/page/content/parser/parsers/divider.py +33 -0
- notionary/page/content/parser/parsers/embed.py +33 -0
- notionary/page/content/parser/parsers/equation.py +65 -0
- notionary/page/content/parser/parsers/file.py +42 -0
- notionary/page/content/parser/parsers/heading.py +58 -0
- notionary/page/content/parser/parsers/image.py +42 -0
- notionary/page/content/parser/parsers/numbered_list.py +45 -0
- notionary/page/content/parser/parsers/paragraph.py +36 -0
- notionary/page/content/parser/parsers/pdf.py +42 -0
- notionary/page/content/parser/parsers/quote.py +65 -0
- notionary/page/content/parser/parsers/space.py +35 -0
- notionary/page/content/parser/parsers/table.py +144 -0
- notionary/page/content/parser/parsers/table_of_contents.py +32 -0
- notionary/page/content/parser/parsers/todo.py +58 -0
- notionary/page/content/parser/parsers/toggle.py +127 -0
- notionary/page/content/parser/parsers/toggleable_heading.py +150 -0
- notionary/page/content/parser/parsers/video.py +42 -0
- notionary/page/content/parser/post_processing/handlers/__init__.py +5 -0
- notionary/page/content/parser/post_processing/handlers/rich_text_length.py +93 -0
- notionary/page/content/parser/post_processing/handlers/rich_text_length_truncation.py +93 -0
- notionary/page/content/parser/post_processing/port.py +9 -0
- notionary/page/content/parser/post_processing/service.py +16 -0
- notionary/page/content/parser/pre_processsing/handlers/__init__.py +9 -0
- notionary/page/content/parser/pre_processsing/handlers/column_syntax.py +80 -0
- notionary/page/content/parser/pre_processsing/handlers/port.py +7 -0
- notionary/page/content/parser/pre_processsing/handlers/whitespace.py +68 -0
- notionary/page/content/parser/pre_processsing/service.py +15 -0
- notionary/page/content/parser/service.py +69 -0
- notionary/page/content/renderer/context.py +48 -0
- notionary/page/content/renderer/factory.py +240 -0
- notionary/page/content/renderer/post_processing/handlers/__init__.py +5 -0
- notionary/page/content/renderer/post_processing/handlers/numbered_list_placeholdere.py +62 -0
- notionary/page/content/renderer/post_processing/port.py +7 -0
- notionary/page/content/renderer/post_processing/service.py +15 -0
- notionary/page/content/renderer/renderers/__init__.py +57 -0
- notionary/page/content/renderer/renderers/audio.py +31 -0
- notionary/page/content/renderer/renderers/base.py +31 -0
- notionary/page/content/renderer/renderers/bookmark.py +25 -0
- notionary/page/content/renderer/renderers/breadcrumb.py +21 -0
- notionary/page/content/renderer/renderers/bulleted_list.py +48 -0
- notionary/page/content/renderer/renderers/callout.py +65 -0
- notionary/page/content/renderer/renderers/captioned_block.py +58 -0
- notionary/page/content/renderer/renderers/code.py +34 -0
- notionary/page/content/renderer/renderers/column.py +44 -0
- notionary/page/content/renderer/renderers/column_list.py +31 -0
- notionary/page/content/renderer/renderers/divider.py +22 -0
- notionary/page/content/renderer/renderers/embed.py +25 -0
- notionary/page/content/renderer/renderers/equation.py +37 -0
- notionary/page/content/renderer/renderers/fallback.py +24 -0
- notionary/page/content/renderer/renderers/file.py +40 -0
- notionary/page/content/renderer/renderers/heading.py +69 -0
- notionary/page/content/renderer/renderers/image.py +31 -0
- notionary/page/content/renderer/renderers/numbered_list.py +41 -0
- notionary/page/content/renderer/renderers/paragraph.py +40 -0
- notionary/page/content/renderer/renderers/pdf.py +31 -0
- notionary/page/content/renderer/renderers/quote.py +49 -0
- notionary/page/content/renderer/renderers/table.py +115 -0
- notionary/page/content/renderer/renderers/table_of_contents.py +26 -0
- notionary/page/content/renderer/renderers/table_row.py +17 -0
- notionary/page/content/renderer/renderers/todo.py +56 -0
- notionary/page/content/renderer/renderers/toggle.py +53 -0
- notionary/page/content/renderer/renderers/toggleable_heading.py +78 -0
- notionary/page/content/renderer/renderers/video.py +31 -0
- notionary/page/content/renderer/service.py +50 -0
- notionary/page/content/service.py +65 -0
- notionary/page/content/syntax/models.py +68 -0
- notionary/page/content/syntax/service.py +453 -0
- notionary/page/page_context.py +7 -16
- notionary/page/page_http_client.py +15 -0
- notionary/page/page_metadata_update_client.py +19 -0
- notionary/page/properties/client.py +144 -0
- notionary/page/properties/factory.py +26 -0
- notionary/page/properties/models.py +307 -0
- notionary/page/properties/service.py +257 -0
- notionary/page/schemas.py +13 -0
- notionary/page/service.py +222 -0
- notionary/shared/entity/client.py +29 -0
- notionary/shared/entity/dto_parsers.py +53 -0
- notionary/shared/entity/entity_metadata_update_client.py +41 -0
- notionary/shared/entity/schemas.py +45 -0
- notionary/shared/entity/service.py +171 -0
- notionary/shared/models/cover.py +20 -0
- notionary/shared/models/file.py +21 -0
- notionary/shared/models/icon.py +28 -0
- notionary/shared/models/parent.py +41 -0
- notionary/shared/properties/type.py +30 -0
- notionary/user/__init__.py +4 -8
- notionary/user/base.py +89 -0
- notionary/user/bot.py +70 -0
- notionary/user/client.py +22 -111
- notionary/user/person.py +41 -0
- notionary/user/schemas.py +67 -0
- notionary/user/service.py +65 -0
- notionary/utils/async_retry.py +39 -0
- notionary/utils/date.py +51 -0
- notionary/utils/fuzzy.py +56 -0
- notionary/{util/logging_mixin.py → utils/mixins/logging.py} +4 -16
- notionary/utils/pagination.py +50 -0
- notionary/utils/singleton.py +13 -0
- notionary/utils/uuid_utils.py +20 -0
- notionary/workspace/__init__.py +3 -0
- notionary/workspace/client.py +62 -0
- notionary/workspace/query/builder.py +60 -0
- notionary/workspace/query/models.py +60 -0
- notionary/workspace/query/service.py +93 -0
- notionary/workspace/schemas.py +21 -0
- notionary/workspace/service.py +116 -0
- {notionary-0.2.26.dist-info → notionary-0.2.28.dist-info}/METADATA +54 -49
- notionary-0.2.28.dist-info/RECORD +200 -0
- {notionary-0.2.26.dist-info → notionary-0.2.28.dist-info}/WHEEL +1 -1
- {notionary-0.2.26.dist-info → notionary-0.2.28.dist-info/licenses}/LICENSE +9 -9
- notionary/base_notion_client.py +0 -219
- notionary/blocks/__init__.py +0 -5
- notionary/blocks/_bootstrap.py +0 -271
- notionary/blocks/audio/__init__.py +0 -11
- notionary/blocks/audio/audio_element.py +0 -158
- notionary/blocks/audio/audio_markdown_node.py +0 -24
- notionary/blocks/audio/audio_models.py +0 -10
- notionary/blocks/base_block_element.py +0 -42
- notionary/blocks/bookmark/__init__.py +0 -12
- notionary/blocks/bookmark/bookmark_element.py +0 -83
- notionary/blocks/bookmark/bookmark_markdown_node.py +0 -28
- notionary/blocks/bookmark/bookmark_models.py +0 -15
- notionary/blocks/breadcrumbs/__init__.py +0 -15
- notionary/blocks/breadcrumbs/breadcrumb_element.py +0 -39
- notionary/blocks/breadcrumbs/breadcrumb_markdown_node.py +0 -13
- notionary/blocks/breadcrumbs/breadcrumb_models.py +0 -12
- notionary/blocks/bulleted_list/__init__.py +0 -15
- notionary/blocks/bulleted_list/bulleted_list_element.py +0 -74
- notionary/blocks/bulleted_list/bulleted_list_markdown_node.py +0 -20
- notionary/blocks/bulleted_list/bulleted_list_models.py +0 -17
- notionary/blocks/callout/__init__.py +0 -12
- notionary/blocks/callout/callout_element.py +0 -99
- notionary/blocks/callout/callout_markdown_node.py +0 -19
- notionary/blocks/callout/callout_models.py +0 -33
- notionary/blocks/child_database/__init__.py +0 -14
- notionary/blocks/child_database/child_database_element.py +0 -59
- notionary/blocks/child_database/child_database_models.py +0 -12
- notionary/blocks/child_page/__init__.py +0 -9
- notionary/blocks/child_page/child_page_element.py +0 -94
- notionary/blocks/child_page/child_page_models.py +0 -12
- notionary/blocks/code/__init__.py +0 -11
- notionary/blocks/code/code_element.py +0 -149
- notionary/blocks/code/code_markdown_node.py +0 -80
- notionary/blocks/code/code_models.py +0 -94
- notionary/blocks/column/__init__.py +0 -25
- notionary/blocks/column/column_element.py +0 -65
- notionary/blocks/column/column_list_element.py +0 -52
- notionary/blocks/column/column_list_markdown_node.py +0 -34
- notionary/blocks/column/column_markdown_node.py +0 -42
- notionary/blocks/column/column_models.py +0 -26
- notionary/blocks/divider/__init__.py +0 -12
- notionary/blocks/divider/divider_element.py +0 -41
- notionary/blocks/divider/divider_markdown_node.py +0 -11
- notionary/blocks/divider/divider_models.py +0 -12
- notionary/blocks/embed/__init__.py +0 -12
- notionary/blocks/embed/embed_element.py +0 -98
- notionary/blocks/embed/embed_markdown_node.py +0 -19
- notionary/blocks/embed/embed_models.py +0 -14
- notionary/blocks/equation/__init__.py +0 -13
- notionary/blocks/equation/equation_element.py +0 -133
- notionary/blocks/equation/equation_element_markdown_node.py +0 -23
- notionary/blocks/equation/equation_models.py +0 -11
- notionary/blocks/file/__init__.py +0 -23
- notionary/blocks/file/file_element.py +0 -133
- notionary/blocks/file/file_element_markdown_node.py +0 -24
- notionary/blocks/file/file_element_models.py +0 -39
- notionary/blocks/heading/__init__.py +0 -19
- notionary/blocks/heading/heading_element.py +0 -112
- notionary/blocks/heading/heading_markdown_node.py +0 -16
- notionary/blocks/heading/heading_models.py +0 -29
- notionary/blocks/image_block/__init__.py +0 -11
- notionary/blocks/image_block/image_element.py +0 -130
- notionary/blocks/image_block/image_markdown_node.py +0 -25
- notionary/blocks/image_block/image_models.py +0 -10
- notionary/blocks/markdown/markdown_builder.py +0 -525
- notionary/blocks/markdown/markdown_document_model.py +0 -0
- notionary/blocks/markdown/markdown_node.py +0 -25
- notionary/blocks/mixins/captions/__init__.py +0 -4
- notionary/blocks/mixins/captions/caption_markdown_node_mixin.py +0 -31
- notionary/blocks/mixins/captions/caption_mixin.py +0 -92
- notionary/blocks/mixins/file_upload/__init__.py +0 -3
- notionary/blocks/mixins/file_upload/file_upload_mixin.py +0 -320
- notionary/blocks/models.py +0 -174
- notionary/blocks/numbered_list/__init__.py +0 -16
- notionary/blocks/numbered_list/numbered_list_element.py +0 -65
- notionary/blocks/numbered_list/numbered_list_markdown_node.py +0 -17
- notionary/blocks/numbered_list/numbered_list_models.py +0 -17
- notionary/blocks/paragraph/__init__.py +0 -15
- notionary/blocks/paragraph/paragraph_element.py +0 -58
- notionary/blocks/paragraph/paragraph_markdown_node.py +0 -16
- notionary/blocks/paragraph/paragraph_models.py +0 -16
- notionary/blocks/pdf/__init__.py +0 -11
- notionary/blocks/pdf/pdf_element.py +0 -146
- notionary/blocks/pdf/pdf_markdown_node.py +0 -24
- notionary/blocks/pdf/pdf_models.py +0 -11
- notionary/blocks/quote/__init__.py +0 -14
- notionary/blocks/quote/quote_element.py +0 -75
- notionary/blocks/quote/quote_markdown_node.py +0 -16
- notionary/blocks/quote/quote_models.py +0 -18
- notionary/blocks/registry/__init__.py +0 -3
- notionary/blocks/registry/block_registry.py +0 -150
- notionary/blocks/rich_text/__init__.py +0 -33
- notionary/blocks/rich_text/rich_text_models.py +0 -221
- notionary/blocks/rich_text/text_inline_formatter.py +0 -456
- notionary/blocks/syntax_prompt_builder.py +0 -137
- notionary/blocks/table/__init__.py +0 -19
- notionary/blocks/table/table_element.py +0 -225
- notionary/blocks/table/table_markdown_node.py +0 -42
- notionary/blocks/table/table_models.py +0 -28
- notionary/blocks/table_of_contents/__init__.py +0 -17
- notionary/blocks/table_of_contents/table_of_contents_element.py +0 -80
- notionary/blocks/table_of_contents/table_of_contents_markdown_node.py +0 -21
- notionary/blocks/table_of_contents/table_of_contents_models.py +0 -18
- notionary/blocks/todo/__init__.py +0 -12
- notionary/blocks/todo/todo_element.py +0 -81
- notionary/blocks/todo/todo_markdown_node.py +0 -21
- notionary/blocks/todo/todo_models.py +0 -18
- notionary/blocks/toggle/__init__.py +0 -12
- notionary/blocks/toggle/toggle_element.py +0 -112
- notionary/blocks/toggle/toggle_markdown_node.py +0 -31
- notionary/blocks/toggle/toggle_models.py +0 -17
- notionary/blocks/toggleable_heading/__init__.py +0 -11
- notionary/blocks/toggleable_heading/toggleable_heading_element.py +0 -115
- notionary/blocks/toggleable_heading/toggleable_heading_markdown_node.py +0 -34
- notionary/blocks/types.py +0 -130
- notionary/blocks/video/__init__.py +0 -11
- notionary/blocks/video/video_element.py +0 -187
- notionary/blocks/video/video_element_models.py +0 -10
- notionary/blocks/video/video_markdown_node.py +0 -26
- notionary/comments/__init__.py +0 -26
- notionary/database/__init__.py +0 -4
- notionary/database/database.py +0 -480
- notionary/database/database_filter_builder.py +0 -173
- notionary/database/database_provider.py +0 -227
- notionary/database/exceptions.py +0 -13
- notionary/database/factory.py +0 -0
- notionary/database/models.py +0 -337
- notionary/database/notion_database.py +0 -487
- notionary/file_upload/__init__.py +0 -7
- notionary/page/client.py +0 -124
- notionary/page/markdown_whitespace_processor.py +0 -129
- notionary/page/models.py +0 -322
- notionary/page/notion_page.py +0 -674
- notionary/page/page_content_deleting_service.py +0 -117
- notionary/page/page_content_writer.py +0 -80
- notionary/page/property_formatter.py +0 -99
- notionary/page/reader/handler/__init__.py +0 -19
- notionary/page/reader/handler/base_block_renderer.py +0 -44
- notionary/page/reader/handler/block_processing_context.py +0 -35
- notionary/page/reader/handler/block_rendering_context.py +0 -48
- notionary/page/reader/handler/column_list_renderer.py +0 -51
- notionary/page/reader/handler/column_renderer.py +0 -60
- notionary/page/reader/handler/equation_renderer.py +0 -0
- notionary/page/reader/handler/line_renderer.py +0 -73
- notionary/page/reader/handler/numbered_list_renderer.py +0 -85
- notionary/page/reader/handler/toggle_renderer.py +0 -69
- notionary/page/reader/handler/toggleable_heading_renderer.py +0 -89
- notionary/page/reader/page_content_retriever.py +0 -81
- notionary/page/search_filter_builder.py +0 -132
- notionary/page/utils.py +0 -60
- notionary/page/writer/handler/__init__.py +0 -24
- notionary/page/writer/handler/code_handler.py +0 -72
- notionary/page/writer/handler/column_handler.py +0 -141
- notionary/page/writer/handler/column_list_handler.py +0 -139
- notionary/page/writer/handler/equation_handler.py +0 -74
- notionary/page/writer/handler/line_handler.py +0 -35
- notionary/page/writer/handler/line_processing_context.py +0 -54
- notionary/page/writer/handler/regular_line_handler.py +0 -86
- notionary/page/writer/handler/table_handler.py +0 -66
- notionary/page/writer/handler/toggle_handler.py +0 -159
- notionary/page/writer/handler/toggleable_heading_handler.py +0 -174
- notionary/page/writer/markdown_to_notion_converter.py +0 -139
- notionary/page/writer/markdown_to_notion_converter_context.py +0 -30
- notionary/page/writer/markdown_to_notion_text_length_post_processor.py +0 -0
- notionary/page/writer/notion_text_length_processor.py +0 -150
- notionary/schemas/__init__.py +0 -3
- notionary/schemas/base.py +0 -73
- notionary/shared/__init__.py +0 -3
- notionary/shared/name_to_id_resolver.py +0 -203
- notionary/telemetry/__init__.py +0 -19
- notionary/telemetry/service.py +0 -136
- notionary/telemetry/views.py +0 -73
- notionary/user/base_notion_user.py +0 -53
- notionary/user/models.py +0 -84
- notionary/user/notion_bot_user.py +0 -226
- notionary/user/notion_user.py +0 -255
- notionary/user/notion_user_manager.py +0 -101
- notionary/util/__init__.py +0 -15
- notionary/util/concurrency_limiter.py +0 -0
- notionary/util/factory_decorator.py +0 -0
- notionary/util/factory_only.py +0 -37
- notionary/util/fuzzy.py +0 -75
- notionary/util/page_id_utils.py +0 -27
- notionary/util/singleton.py +0 -18
- notionary/util/singleton_metaclass.py +0 -22
- notionary/workspace.py +0 -105
- notionary-0.2.26.dist-info/RECORD +0 -202
@@ -1,137 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
|
3
|
-
from dataclasses import dataclass
|
4
|
-
from textwrap import dedent
|
5
|
-
from typing import TYPE_CHECKING, Optional
|
6
|
-
|
7
|
-
|
8
|
-
if TYPE_CHECKING:
|
9
|
-
from notionary.blocks.registry.block_registry import BlockRegistry
|
10
|
-
|
11
|
-
|
12
|
-
@dataclass
|
13
|
-
class BlockElementMarkdownInformation:
|
14
|
-
"""Metadata describing how a Notion block maps to Markdown syntax."""
|
15
|
-
|
16
|
-
block_type: str
|
17
|
-
description: str
|
18
|
-
syntax_examples: list[str]
|
19
|
-
usage_guidelines: str
|
20
|
-
|
21
|
-
|
22
|
-
class SyntaxPromptBuilder:
|
23
|
-
"""
|
24
|
-
Builds a comprehensive markdown syntax reference from a block registry.
|
25
|
-
Iterates over all registered elements and collects their system prompt information.
|
26
|
-
"""
|
27
|
-
|
28
|
-
def __init__(self, block_registry: BlockRegistry):
|
29
|
-
self.block_registry = block_registry
|
30
|
-
|
31
|
-
def build_markdown_reference(self) -> str:
|
32
|
-
"""
|
33
|
-
Build a complete markdown syntax reference string.
|
34
|
-
"""
|
35
|
-
sections = [
|
36
|
-
self._build_header(),
|
37
|
-
*self._build_element_sections(),
|
38
|
-
]
|
39
|
-
|
40
|
-
return "\n\n".join(sections)
|
41
|
-
|
42
|
-
def build_concise_reference(self) -> str:
|
43
|
-
"""
|
44
|
-
Build a more concise reference suitable for system prompts.
|
45
|
-
"""
|
46
|
-
lines = ["# Notionary Markdown Syntax"]
|
47
|
-
|
48
|
-
for element_class in self.block_registry.get_elements():
|
49
|
-
info: Optional[BlockElementMarkdownInformation] = (
|
50
|
-
element_class.get_system_prompt_information()
|
51
|
-
)
|
52
|
-
if info and info.syntax_examples:
|
53
|
-
# Just show the first example for conciseness
|
54
|
-
example = info.syntax_examples[0]
|
55
|
-
lines.append(f"- {info.block_type}: `{example}`")
|
56
|
-
|
57
|
-
return "\n".join(lines)
|
58
|
-
|
59
|
-
def get_blocks_with_information(self) -> list[str]:
|
60
|
-
"""Get list of block names that provide system prompt information."""
|
61
|
-
blocks = []
|
62
|
-
|
63
|
-
for element_class in self.block_registry.get_elements():
|
64
|
-
info: Optional[BlockElementMarkdownInformation] = (
|
65
|
-
element_class.get_system_prompt_information()
|
66
|
-
)
|
67
|
-
if info:
|
68
|
-
blocks.append(info.block_type)
|
69
|
-
|
70
|
-
return blocks
|
71
|
-
|
72
|
-
def _build_header(self) -> str:
|
73
|
-
"""Build the header section of the reference."""
|
74
|
-
return dedent(
|
75
|
-
"""
|
76
|
-
# Notionary Markdown Syntax Reference
|
77
|
-
|
78
|
-
This comprehensive reference documents all supported markdown syntax for converting between Markdown and Notion blocks.
|
79
|
-
|
80
|
-
Each block type includes:
|
81
|
-
- **Description:** What the block does
|
82
|
-
- **When to use:** Guidelines for appropriate usage
|
83
|
-
- **Syntax:** Complete syntax examples with variations
|
84
|
-
"""
|
85
|
-
).strip()
|
86
|
-
|
87
|
-
def _build_element_sections(self) -> list[str]:
|
88
|
-
"""Build sections for all registered elements."""
|
89
|
-
sections = []
|
90
|
-
|
91
|
-
for element_class in self.block_registry.get_elements():
|
92
|
-
info = element_class.get_system_prompt_information()
|
93
|
-
if info:
|
94
|
-
sections.append(self._build_element_section(info))
|
95
|
-
|
96
|
-
return sections
|
97
|
-
|
98
|
-
def _build_element_section(self, info: BlockElementMarkdownInformation) -> str:
|
99
|
-
"""Build a well-structured section for a single block element."""
|
100
|
-
section_parts = [
|
101
|
-
f"## {info.block_type}",
|
102
|
-
"",
|
103
|
-
f"**Description:** {info.description}",
|
104
|
-
"",
|
105
|
-
]
|
106
|
-
|
107
|
-
if info.usage_guidelines:
|
108
|
-
section_parts.extend(["**When to use:**", info.usage_guidelines, ""])
|
109
|
-
|
110
|
-
if info.syntax_examples:
|
111
|
-
section_parts.extend(
|
112
|
-
[
|
113
|
-
"**Syntax:**",
|
114
|
-
"",
|
115
|
-
*self._format_syntax_examples(info.syntax_examples),
|
116
|
-
"",
|
117
|
-
]
|
118
|
-
)
|
119
|
-
|
120
|
-
return "\n".join(section_parts).rstrip()
|
121
|
-
|
122
|
-
def _format_syntax_examples(self, examples: list[str]) -> list[str]:
|
123
|
-
"""Format syntax examples with proper markdown and clear structure."""
|
124
|
-
formatted = []
|
125
|
-
|
126
|
-
for i, example in enumerate(examples, 1):
|
127
|
-
if len(examples) > 1:
|
128
|
-
formatted.append(f"**Example {i}:**")
|
129
|
-
|
130
|
-
if "\n" in example:
|
131
|
-
# Multi-line example - use code block
|
132
|
-
formatted.extend(["```", example, "```", ""])
|
133
|
-
else:
|
134
|
-
# Single line - use inline code with description
|
135
|
-
formatted.extend([f"`{example}`", ""])
|
136
|
-
|
137
|
-
return formatted
|
@@ -1,19 +0,0 @@
|
|
1
|
-
from notionary.blocks.table.table_element import TableElement
|
2
|
-
from notionary.blocks.table.table_markdown_node import (
|
3
|
-
TableMarkdownNode,
|
4
|
-
)
|
5
|
-
from notionary.blocks.table.table_models import (
|
6
|
-
CreateTableBlock,
|
7
|
-
CreateTableRowBlock,
|
8
|
-
TableBlock,
|
9
|
-
TableRowBlock,
|
10
|
-
)
|
11
|
-
|
12
|
-
__all__ = [
|
13
|
-
"TableElement",
|
14
|
-
"TableBlock",
|
15
|
-
"TableRowBlock",
|
16
|
-
"CreateTableRowBlock",
|
17
|
-
"CreateTableBlock",
|
18
|
-
"TableMarkdownNode",
|
19
|
-
]
|
@@ -1,225 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
|
3
|
-
import re
|
4
|
-
from typing import Optional
|
5
|
-
|
6
|
-
from notionary.blocks.base_block_element import BaseBlockElement
|
7
|
-
from notionary.blocks.syntax_prompt_builder import BlockElementMarkdownInformation
|
8
|
-
from notionary.blocks.models import Block, BlockCreateResult
|
9
|
-
from notionary.blocks.rich_text.rich_text_models import RichTextObject
|
10
|
-
from notionary.blocks.rich_text.text_inline_formatter import TextInlineFormatter
|
11
|
-
from notionary.blocks.table.table_models import (
|
12
|
-
CreateTableBlock,
|
13
|
-
TableBlock,
|
14
|
-
CreateTableRowBlock,
|
15
|
-
TableRowBlock,
|
16
|
-
)
|
17
|
-
from notionary.blocks.types import BlockType
|
18
|
-
|
19
|
-
|
20
|
-
class TableElement(BaseBlockElement):
|
21
|
-
"""
|
22
|
-
Handles conversion between Markdown tables and Notion table blocks.
|
23
|
-
Now integrated into the LineProcessor stack system.
|
24
|
-
|
25
|
-
Markdown table syntax:
|
26
|
-
| Header 1 | Header 2 | Header 3 |
|
27
|
-
| -------- | -------- | -------- |
|
28
|
-
| Cell 1 | Cell 2 | Cell 3 |
|
29
|
-
"""
|
30
|
-
|
31
|
-
ROW_PATTERN = re.compile(r"^\s*\|(.+)\|\s*$")
|
32
|
-
SEPARATOR_PATTERN = re.compile(r"^\s*\|([\s\-:|]+)\|\s*$")
|
33
|
-
|
34
|
-
@classmethod
|
35
|
-
def match_notion(cls, block: Block) -> bool:
|
36
|
-
"""Check if block is a Notion table."""
|
37
|
-
return block.type == BlockType.TABLE and block.table
|
38
|
-
|
39
|
-
@classmethod
|
40
|
-
async def markdown_to_notion(cls, text: str) -> BlockCreateResult:
|
41
|
-
"""Convert opening table row to Notion table block."""
|
42
|
-
if not cls.ROW_PATTERN.match(text.strip()):
|
43
|
-
return None
|
44
|
-
|
45
|
-
# Parse the header row to determine column count
|
46
|
-
header_cells = cls._parse_table_row(text)
|
47
|
-
col_count = len(header_cells)
|
48
|
-
|
49
|
-
table_block = TableBlock(
|
50
|
-
table_width=col_count,
|
51
|
-
has_column_header=True,
|
52
|
-
has_row_header=False,
|
53
|
-
children=[], # Will be populated by stack processor
|
54
|
-
)
|
55
|
-
|
56
|
-
return CreateTableBlock(table=table_block)
|
57
|
-
|
58
|
-
@classmethod
|
59
|
-
async def create_from_markdown_table(
|
60
|
-
cls, table_lines: list[str]
|
61
|
-
) -> BlockCreateResult:
|
62
|
-
"""
|
63
|
-
Create a complete table block from markdown table lines.
|
64
|
-
"""
|
65
|
-
if not table_lines:
|
66
|
-
return None
|
67
|
-
|
68
|
-
first_row = None
|
69
|
-
for line in table_lines:
|
70
|
-
line = line.strip()
|
71
|
-
if line and cls.ROW_PATTERN.match(line):
|
72
|
-
first_row = line
|
73
|
-
break
|
74
|
-
|
75
|
-
if not first_row:
|
76
|
-
return None
|
77
|
-
|
78
|
-
# Parse header row to determine column count
|
79
|
-
header_cells = cls._parse_table_row(first_row)
|
80
|
-
col_count = len(header_cells)
|
81
|
-
|
82
|
-
# Process all table lines
|
83
|
-
table_rows, separator_found = await cls._process_table_lines(table_lines)
|
84
|
-
|
85
|
-
# Create complete TableBlock
|
86
|
-
table_block = TableBlock(
|
87
|
-
table_width=col_count,
|
88
|
-
has_column_header=separator_found,
|
89
|
-
has_row_header=False,
|
90
|
-
children=table_rows,
|
91
|
-
)
|
92
|
-
|
93
|
-
return CreateTableBlock(table=table_block)
|
94
|
-
|
95
|
-
@classmethod
|
96
|
-
async def _process_table_lines(
|
97
|
-
cls, table_lines: list[str]
|
98
|
-
) -> tuple[list[CreateTableRowBlock], bool]:
|
99
|
-
"""Process all table lines and return rows and separator status."""
|
100
|
-
table_rows = []
|
101
|
-
separator_found = False
|
102
|
-
|
103
|
-
for line in table_lines:
|
104
|
-
line = line.strip()
|
105
|
-
if not line:
|
106
|
-
continue
|
107
|
-
|
108
|
-
if cls._is_separator_line(line):
|
109
|
-
separator_found = True
|
110
|
-
continue
|
111
|
-
|
112
|
-
if cls.ROW_PATTERN.match(line):
|
113
|
-
table_row = await cls._create_table_row_from_line(line)
|
114
|
-
table_rows.append(table_row)
|
115
|
-
|
116
|
-
return table_rows, separator_found
|
117
|
-
|
118
|
-
@classmethod
|
119
|
-
def _is_separator_line(cls, line: str) -> bool:
|
120
|
-
"""Check if line is a table separator (|---|---|)."""
|
121
|
-
return cls.SEPARATOR_PATTERN.match(line) is not None
|
122
|
-
|
123
|
-
@classmethod
|
124
|
-
async def _create_table_row_from_line(cls, line: str) -> CreateTableRowBlock:
|
125
|
-
"""Create a table row block from a markdown line."""
|
126
|
-
cells = cls._parse_table_row(line)
|
127
|
-
rich_text_cells = []
|
128
|
-
for cell in cells:
|
129
|
-
rich_text_cell = await cls._convert_cell_to_rich_text(cell)
|
130
|
-
rich_text_cells.append(rich_text_cell)
|
131
|
-
table_row = TableRowBlock(cells=rich_text_cells)
|
132
|
-
return CreateTableRowBlock(table_row=table_row)
|
133
|
-
|
134
|
-
@classmethod
|
135
|
-
async def _convert_cell_to_rich_text(cls, cell: str) -> list[RichTextObject]:
|
136
|
-
"""Convert cell text to rich text objects."""
|
137
|
-
rich_text = await TextInlineFormatter.parse_inline_formatting(cell)
|
138
|
-
if not rich_text:
|
139
|
-
rich_text = [RichTextObject.from_plain_text(cell)]
|
140
|
-
return rich_text
|
141
|
-
|
142
|
-
@classmethod
|
143
|
-
async def notion_to_markdown(cls, block: Block) -> Optional[str]:
|
144
|
-
"""Convert Notion table block to markdown table."""
|
145
|
-
if block.type != BlockType.TABLE:
|
146
|
-
return None
|
147
|
-
|
148
|
-
if not block.table:
|
149
|
-
return None
|
150
|
-
|
151
|
-
table_data = block.table
|
152
|
-
children = block.children or []
|
153
|
-
|
154
|
-
if not children:
|
155
|
-
table_width = table_data.table_width or 3
|
156
|
-
header = (
|
157
|
-
"| " + " | ".join([f"Column {i+1}" for i in range(table_width)]) + " |"
|
158
|
-
)
|
159
|
-
separator = (
|
160
|
-
"| " + " | ".join(["--------" for _ in range(table_width)]) + " |"
|
161
|
-
)
|
162
|
-
data_row = (
|
163
|
-
"| " + " | ".join([" " for _ in range(table_width)]) + " |"
|
164
|
-
)
|
165
|
-
table_rows = [header, separator, data_row]
|
166
|
-
return "\n".join(table_rows)
|
167
|
-
|
168
|
-
table_rows = []
|
169
|
-
header_processed = False
|
170
|
-
|
171
|
-
for child in children:
|
172
|
-
if child.type != BlockType.TABLE_ROW:
|
173
|
-
continue
|
174
|
-
|
175
|
-
if not child.table_row:
|
176
|
-
continue
|
177
|
-
|
178
|
-
row_data = child.table_row
|
179
|
-
cells = row_data.cells or []
|
180
|
-
|
181
|
-
row_cells = []
|
182
|
-
for cell in cells:
|
183
|
-
cell_text = await TextInlineFormatter.extract_text_with_formatting(cell)
|
184
|
-
row_cells.append(cell_text or "")
|
185
|
-
|
186
|
-
row = "| " + " | ".join(row_cells) + " |"
|
187
|
-
table_rows.append(row)
|
188
|
-
|
189
|
-
if not header_processed and table_data.has_column_header:
|
190
|
-
header_processed = True
|
191
|
-
separator = (
|
192
|
-
"| " + " | ".join(["--------" for _ in range(len(cells))]) + " |"
|
193
|
-
)
|
194
|
-
table_rows.append(separator)
|
195
|
-
|
196
|
-
return "\n".join(table_rows)
|
197
|
-
|
198
|
-
@classmethod
|
199
|
-
def _parse_table_row(cls, row_text: str) -> list[str]:
|
200
|
-
"""Convert table row text to cell contents."""
|
201
|
-
row_content = row_text.strip()
|
202
|
-
|
203
|
-
if row_content.startswith("|"):
|
204
|
-
row_content = row_content[1:]
|
205
|
-
if row_content.endswith("|"):
|
206
|
-
row_content = row_content[:-1]
|
207
|
-
|
208
|
-
return [cell.strip() for cell in row_content.split("|")]
|
209
|
-
|
210
|
-
@classmethod
|
211
|
-
def is_table_row(cls, line: str) -> bool:
|
212
|
-
"""Check if a line is a valid table row."""
|
213
|
-
return bool(cls.ROW_PATTERN.match(line.strip()))
|
214
|
-
|
215
|
-
@classmethod
|
216
|
-
def get_system_prompt_information(cls) -> Optional[BlockElementMarkdownInformation]:
|
217
|
-
"""Get system prompt information for table blocks."""
|
218
|
-
return BlockElementMarkdownInformation(
|
219
|
-
block_type=cls.__name__,
|
220
|
-
description="Table blocks create structured data in rows and columns with headers",
|
221
|
-
syntax_examples=[
|
222
|
-
"| Name | Age | City |\n| -------- | -------- | -------- |\n| Alice | 25 | Berlin |\n| Bob | 30 | Munich |"
|
223
|
-
],
|
224
|
-
usage_guidelines="Use for structured data presentation. First row is header, second row is separator with dashes, following rows are data. Cells are separated by | characters.",
|
225
|
-
)
|
@@ -1,42 +0,0 @@
|
|
1
|
-
from pydantic import field_validator
|
2
|
-
|
3
|
-
from notionary.blocks.markdown.markdown_node import MarkdownNode
|
4
|
-
|
5
|
-
|
6
|
-
class TableMarkdownNode(MarkdownNode):
|
7
|
-
"""
|
8
|
-
Enhanced Table node with Pydantic integration.
|
9
|
-
Programmatic interface for creating Markdown tables.
|
10
|
-
Example:
|
11
|
-
| Header 1 | Header 2 | Header 3 |
|
12
|
-
| -------- | -------- | -------- |
|
13
|
-
| Cell 1 | Cell 2 | Cell 3 |
|
14
|
-
| Cell 4 | Cell 5 | Cell 6 |
|
15
|
-
"""
|
16
|
-
|
17
|
-
headers: list[str]
|
18
|
-
rows: list[list[str]]
|
19
|
-
|
20
|
-
@field_validator("headers")
|
21
|
-
@classmethod
|
22
|
-
def validate_headers(cls, v):
|
23
|
-
if not v:
|
24
|
-
raise ValueError("headers must not be empty")
|
25
|
-
return v
|
26
|
-
|
27
|
-
@field_validator("rows")
|
28
|
-
@classmethod
|
29
|
-
def validate_rows(cls, v):
|
30
|
-
if not all(isinstance(row, list) for row in v):
|
31
|
-
raise ValueError("rows must be a list of lists")
|
32
|
-
return v
|
33
|
-
|
34
|
-
def to_markdown(self) -> str:
|
35
|
-
col_count = len(self.headers)
|
36
|
-
# Header row
|
37
|
-
header = "| " + " | ".join(self.headers) + " |"
|
38
|
-
# Separator row
|
39
|
-
separator = "| " + " | ".join(["--------"] * col_count) + " |"
|
40
|
-
# Data rows
|
41
|
-
data_rows = ["| " + " | ".join(row) + " |" for row in self.rows]
|
42
|
-
return "\n".join([header, separator] + data_rows)
|
@@ -1,28 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
|
3
|
-
from typing import Literal
|
4
|
-
|
5
|
-
from pydantic import BaseModel
|
6
|
-
|
7
|
-
from notionary.blocks.rich_text.rich_text_models import RichTextObject
|
8
|
-
|
9
|
-
|
10
|
-
class TableBlock(BaseModel):
|
11
|
-
table_width: int
|
12
|
-
has_column_header: bool = False
|
13
|
-
has_row_header: bool = False
|
14
|
-
children: list[CreateTableRowBlock] = []
|
15
|
-
|
16
|
-
|
17
|
-
class TableRowBlock(BaseModel):
|
18
|
-
cells: list[list[RichTextObject]]
|
19
|
-
|
20
|
-
|
21
|
-
class CreateTableRowBlock(BaseModel):
|
22
|
-
type: Literal["table_row"] = "table_row"
|
23
|
-
table_row: TableRowBlock
|
24
|
-
|
25
|
-
|
26
|
-
class CreateTableBlock(BaseModel):
|
27
|
-
type: Literal["table"] = "table"
|
28
|
-
table: TableBlock
|
@@ -1,17 +0,0 @@
|
|
1
|
-
from notionary.blocks.table_of_contents.table_of_contents_element import (
|
2
|
-
TableOfContentsElement,
|
3
|
-
)
|
4
|
-
from notionary.blocks.table_of_contents.table_of_contents_markdown_node import (
|
5
|
-
TableOfContentsMarkdownNode,
|
6
|
-
)
|
7
|
-
from notionary.blocks.table_of_contents.table_of_contents_models import (
|
8
|
-
CreateTableOfContentsBlock,
|
9
|
-
TableOfContentsBlock,
|
10
|
-
)
|
11
|
-
|
12
|
-
__all__ = [
|
13
|
-
"TableOfContentsElement",
|
14
|
-
"TableOfContentsBlock",
|
15
|
-
"CreateTableOfContentsBlock",
|
16
|
-
"TableOfContentsMarkdownNode",
|
17
|
-
]
|
@@ -1,80 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
|
3
|
-
import re
|
4
|
-
from typing import Optional
|
5
|
-
|
6
|
-
from notionary.blocks.base_block_element import BaseBlockElement
|
7
|
-
from notionary.blocks.syntax_prompt_builder import BlockElementMarkdownInformation
|
8
|
-
from notionary.blocks.models import Block, BlockCreateResult
|
9
|
-
from notionary.blocks.table_of_contents.table_of_contents_models import (
|
10
|
-
CreateTableOfContentsBlock,
|
11
|
-
TableOfContentsBlock,
|
12
|
-
)
|
13
|
-
from notionary.blocks.types import BlockType, BlockColor
|
14
|
-
|
15
|
-
|
16
|
-
class TableOfContentsElement(BaseBlockElement):
|
17
|
-
"""
|
18
|
-
Handles conversion between Markdown [toc] syntax and Notion table_of_contents blocks.
|
19
|
-
|
20
|
-
Markdown syntax:
|
21
|
-
- [toc] → default color (enum default)
|
22
|
-
- [toc](blue) → custom color
|
23
|
-
- [toc](blue_background) → custom background color
|
24
|
-
"""
|
25
|
-
|
26
|
-
PATTERN = re.compile(r"^\[toc\](?:\((?P<color>[a-z_]+)\))?$", re.IGNORECASE)
|
27
|
-
|
28
|
-
@classmethod
|
29
|
-
def match_notion(cls, block: Block) -> bool:
|
30
|
-
return block.type == BlockType.TABLE_OF_CONTENTS and block.table_of_contents
|
31
|
-
|
32
|
-
@classmethod
|
33
|
-
async def markdown_to_notion(cls, text: str) -> BlockCreateResult:
|
34
|
-
if not (input_match := cls.PATTERN.match(text.strip())):
|
35
|
-
return None
|
36
|
-
|
37
|
-
color_str = input_match.group("color")
|
38
|
-
if color_str:
|
39
|
-
# Validate against the enum; fallback to default if unknown
|
40
|
-
try:
|
41
|
-
color = BlockColor(color_str.lower())
|
42
|
-
toc_payload = TableOfContentsBlock(color=color)
|
43
|
-
except ValueError:
|
44
|
-
# Unknown color → omit to use enum default
|
45
|
-
toc_payload = TableOfContentsBlock()
|
46
|
-
else:
|
47
|
-
# No color provided → omit to let enum default apply
|
48
|
-
toc_payload = TableOfContentsBlock()
|
49
|
-
|
50
|
-
return CreateTableOfContentsBlock(table_of_contents=toc_payload)
|
51
|
-
|
52
|
-
@classmethod
|
53
|
-
async def notion_to_markdown(cls, block: Block) -> Optional[str]:
|
54
|
-
# Correct guard: if not a TOC or missing payload → no match
|
55
|
-
if block.type != BlockType.TABLE_OF_CONTENTS or not block.table_of_contents:
|
56
|
-
return None
|
57
|
-
|
58
|
-
color = block.table_of_contents.color
|
59
|
-
# If None or default → plain [toc]
|
60
|
-
if color is None or color == BlockColor.DEFAULT:
|
61
|
-
return "[toc]"
|
62
|
-
return f"[toc]({color.value})"
|
63
|
-
|
64
|
-
@classmethod
|
65
|
-
def get_system_prompt_information(cls) -> Optional[BlockElementMarkdownInformation]:
|
66
|
-
"""System prompt info for table of contents blocks."""
|
67
|
-
return BlockElementMarkdownInformation(
|
68
|
-
block_type=cls.__name__,
|
69
|
-
description="Table of contents blocks automatically generate navigation for page headings.",
|
70
|
-
syntax_examples=[
|
71
|
-
"[toc]",
|
72
|
-
"[toc](blue)",
|
73
|
-
"[toc](blue_background)",
|
74
|
-
"[toc](gray_background)",
|
75
|
-
],
|
76
|
-
usage_guidelines=(
|
77
|
-
"Use to auto-generate a clickable table of contents from page headings. "
|
78
|
-
"The color parameter is optional; if omitted, the default enum color is used."
|
79
|
-
),
|
80
|
-
)
|
@@ -1,21 +0,0 @@
|
|
1
|
-
from typing import Optional
|
2
|
-
|
3
|
-
from notionary.blocks.markdown.markdown_node import MarkdownNode
|
4
|
-
|
5
|
-
|
6
|
-
class TableOfContentsMarkdownNode(MarkdownNode):
|
7
|
-
"""
|
8
|
-
Enhanced Table of Contents node with Pydantic integration.
|
9
|
-
Programmatic interface for creating Markdown table of contents blocks.
|
10
|
-
Example:
|
11
|
-
[toc]
|
12
|
-
[toc](blue)
|
13
|
-
[toc](blue_background)
|
14
|
-
"""
|
15
|
-
|
16
|
-
color: Optional[str] = "default"
|
17
|
-
|
18
|
-
def to_markdown(self) -> str:
|
19
|
-
if self.color == "default":
|
20
|
-
return "[toc]"
|
21
|
-
return f"[toc]({self.color})"
|
@@ -1,18 +0,0 @@
|
|
1
|
-
from typing import Literal, Optional
|
2
|
-
|
3
|
-
from pydantic import BaseModel
|
4
|
-
|
5
|
-
from notionary.blocks.types import BlockColor
|
6
|
-
|
7
|
-
|
8
|
-
class TableOfContentsBlock(BaseModel):
|
9
|
-
"""Inneres Payload-Objekt: { table_of_contents: { color: ... } }"""
|
10
|
-
|
11
|
-
color: Optional[BlockColor] = BlockColor.DEFAULT
|
12
|
-
|
13
|
-
|
14
|
-
class CreateTableOfContentsBlock(BaseModel):
|
15
|
-
"""Create-Payload für den Block: { type: 'table_of_contents', table_of_contents: {...} }"""
|
16
|
-
|
17
|
-
type: Literal["table_of_contents"] = "table_of_contents"
|
18
|
-
table_of_contents: TableOfContentsBlock
|
@@ -1,12 +0,0 @@
|
|
1
|
-
from notionary.blocks.todo.todo_element import TodoElement
|
2
|
-
from notionary.blocks.todo.todo_markdown_node import (
|
3
|
-
TodoMarkdownNode,
|
4
|
-
)
|
5
|
-
from notionary.blocks.todo.todo_models import CreateToDoBlock, ToDoBlock
|
6
|
-
|
7
|
-
__all__ = [
|
8
|
-
"TodoElement",
|
9
|
-
"ToDoBlock",
|
10
|
-
"CreateToDoBlock",
|
11
|
-
"TodoMarkdownNode",
|
12
|
-
]
|
@@ -1,81 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
|
3
|
-
import re
|
4
|
-
from typing import TYPE_CHECKING, Optional
|
5
|
-
|
6
|
-
from notionary.blocks.base_block_element import BaseBlockElement
|
7
|
-
from notionary.blocks.syntax_prompt_builder import BlockElementMarkdownInformation
|
8
|
-
from notionary.blocks.models import Block, BlockCreateResult, BlockType
|
9
|
-
from notionary.blocks.rich_text.text_inline_formatter import TextInlineFormatter
|
10
|
-
from notionary.blocks.todo.todo_models import CreateToDoBlock, ToDoBlock
|
11
|
-
|
12
|
-
|
13
|
-
class TodoElement(BaseBlockElement):
|
14
|
-
"""
|
15
|
-
Handles conversion between Markdown todo items and Notion to_do blocks.
|
16
|
-
|
17
|
-
Markdown syntax examples:
|
18
|
-
- [ ] Unchecked todo item
|
19
|
-
- [x] Checked todo item
|
20
|
-
* [ ] Also works with asterisk
|
21
|
-
+ [ ] Also works with plus sign
|
22
|
-
"""
|
23
|
-
|
24
|
-
PATTERN = re.compile(r"^\s*[-*+]\s+\[ \]\s+(.+)$")
|
25
|
-
DONE_PATTERN = re.compile(r"^\s*[-*+]\s+\[x\]\s+(.+)$", re.IGNORECASE)
|
26
|
-
|
27
|
-
@classmethod
|
28
|
-
def match_notion(cls, block: Block) -> bool:
|
29
|
-
return block.type == BlockType.TO_DO and block.to_do
|
30
|
-
|
31
|
-
@classmethod
|
32
|
-
async def markdown_to_notion(cls, text: str) -> BlockCreateResult:
|
33
|
-
"""Convert markdown todo or done item to Notion to_do block."""
|
34
|
-
m_done = cls.DONE_PATTERN.match(text)
|
35
|
-
m_todo = None if m_done else cls.PATTERN.match(text)
|
36
|
-
|
37
|
-
if m_done:
|
38
|
-
content = m_done.group(1)
|
39
|
-
checked = True
|
40
|
-
elif m_todo:
|
41
|
-
content = m_todo.group(1)
|
42
|
-
checked = False
|
43
|
-
else:
|
44
|
-
return None
|
45
|
-
|
46
|
-
# build rich text
|
47
|
-
rich = await TextInlineFormatter.parse_inline_formatting(content)
|
48
|
-
|
49
|
-
todo_content = ToDoBlock(
|
50
|
-
rich_text=rich,
|
51
|
-
checked=checked,
|
52
|
-
color="default",
|
53
|
-
)
|
54
|
-
return CreateToDoBlock(to_do=todo_content)
|
55
|
-
|
56
|
-
@classmethod
|
57
|
-
async def notion_to_markdown(cls, block: Block) -> Optional[str]:
|
58
|
-
"""Convert Notion to_do block to markdown todo item."""
|
59
|
-
if block.type != BlockType.TO_DO or not block.to_do:
|
60
|
-
return None
|
61
|
-
|
62
|
-
td = block.to_do
|
63
|
-
content = await TextInlineFormatter.extract_text_with_formatting(td.rich_text)
|
64
|
-
checkbox = "[x]" if td.checked else "[ ]"
|
65
|
-
return f"- {checkbox} {content}"
|
66
|
-
|
67
|
-
@classmethod
|
68
|
-
def get_system_prompt_information(cls) -> Optional[BlockElementMarkdownInformation]:
|
69
|
-
"""Get system prompt information for todo blocks."""
|
70
|
-
return BlockElementMarkdownInformation(
|
71
|
-
block_type=cls.__name__,
|
72
|
-
description="Todo blocks create interactive checkboxes for task management",
|
73
|
-
syntax_examples=[
|
74
|
-
"- [ ] Unchecked todo item",
|
75
|
-
"- [x] Checked todo item",
|
76
|
-
"* [ ] Todo with asterisk",
|
77
|
-
"+ [ ] Todo with plus sign",
|
78
|
-
"- [x] Completed task",
|
79
|
-
],
|
80
|
-
usage_guidelines="Use for task lists and checkboxes. [ ] for unchecked, [x] for checked items. Supports -, *, or + as bullet markers. Interactive in Notion interface.",
|
81
|
-
)
|