notionary 0.2.19__py3-none-any.whl → 0.2.22__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.
Files changed (220) hide show
  1. notionary/__init__.py +8 -4
  2. notionary/base_notion_client.py +3 -1
  3. notionary/blocks/__init__.py +2 -91
  4. notionary/blocks/_bootstrap.py +271 -0
  5. notionary/blocks/audio/__init__.py +8 -2
  6. notionary/blocks/audio/audio_element.py +69 -106
  7. notionary/blocks/audio/audio_markdown_node.py +13 -5
  8. notionary/blocks/audio/audio_models.py +6 -55
  9. notionary/blocks/base_block_element.py +42 -0
  10. notionary/blocks/bookmark/__init__.py +9 -2
  11. notionary/blocks/bookmark/bookmark_element.py +49 -139
  12. notionary/blocks/bookmark/bookmark_markdown_node.py +19 -18
  13. notionary/blocks/bookmark/bookmark_models.py +15 -0
  14. notionary/blocks/breadcrumbs/__init__.py +17 -0
  15. notionary/blocks/breadcrumbs/breadcrumb_element.py +39 -0
  16. notionary/blocks/breadcrumbs/breadcrumb_markdown_node.py +32 -0
  17. notionary/blocks/breadcrumbs/breadcrumb_models.py +12 -0
  18. notionary/blocks/bulleted_list/__init__.py +12 -2
  19. notionary/blocks/bulleted_list/bulleted_list_element.py +55 -53
  20. notionary/blocks/bulleted_list/bulleted_list_markdown_node.py +2 -1
  21. notionary/blocks/bulleted_list/bulleted_list_models.py +18 -0
  22. notionary/blocks/callout/__init__.py +9 -2
  23. notionary/blocks/callout/callout_element.py +53 -86
  24. notionary/blocks/callout/callout_markdown_node.py +3 -1
  25. notionary/blocks/callout/callout_models.py +33 -0
  26. notionary/blocks/child_database/__init__.py +14 -0
  27. notionary/blocks/child_database/child_database_element.py +61 -0
  28. notionary/blocks/child_database/child_database_models.py +12 -0
  29. notionary/blocks/child_page/__init__.py +9 -0
  30. notionary/blocks/child_page/child_page_element.py +94 -0
  31. notionary/blocks/child_page/child_page_models.py +12 -0
  32. notionary/blocks/{shared/block_client.py → client.py} +54 -54
  33. notionary/blocks/code/__init__.py +6 -2
  34. notionary/blocks/code/code_element.py +96 -181
  35. notionary/blocks/code/code_markdown_node.py +64 -13
  36. notionary/blocks/code/code_models.py +94 -0
  37. notionary/blocks/column/__init__.py +25 -1
  38. notionary/blocks/column/column_element.py +44 -312
  39. notionary/blocks/column/column_list_element.py +52 -0
  40. notionary/blocks/column/column_list_markdown_node.py +50 -0
  41. notionary/blocks/column/column_markdown_node.py +59 -0
  42. notionary/blocks/column/column_models.py +26 -0
  43. notionary/blocks/divider/__init__.py +9 -2
  44. notionary/blocks/divider/divider_element.py +18 -49
  45. notionary/blocks/divider/divider_markdown_node.py +2 -1
  46. notionary/blocks/divider/divider_models.py +12 -0
  47. notionary/blocks/embed/__init__.py +9 -2
  48. notionary/blocks/embed/embed_element.py +65 -111
  49. notionary/blocks/embed/embed_markdown_node.py +3 -1
  50. notionary/blocks/embed/embed_models.py +14 -0
  51. notionary/blocks/equation/__init__.py +14 -0
  52. notionary/blocks/equation/equation_element.py +133 -0
  53. notionary/blocks/equation/equation_element_markdown_node.py +35 -0
  54. notionary/blocks/equation/equation_models.py +11 -0
  55. notionary/blocks/file/__init__.py +25 -0
  56. notionary/blocks/file/file_element.py +112 -0
  57. notionary/blocks/file/file_element_markdown_node.py +37 -0
  58. notionary/blocks/file/file_element_models.py +39 -0
  59. notionary/blocks/guards.py +22 -0
  60. notionary/blocks/heading/__init__.py +16 -2
  61. notionary/blocks/heading/heading_element.py +83 -69
  62. notionary/blocks/heading/heading_markdown_node.py +2 -1
  63. notionary/blocks/heading/heading_models.py +29 -0
  64. notionary/blocks/image_block/__init__.py +13 -0
  65. notionary/blocks/image_block/image_element.py +89 -0
  66. notionary/blocks/{image → image_block}/image_markdown_node.py +13 -6
  67. notionary/blocks/image_block/image_models.py +10 -0
  68. notionary/blocks/mixins/captions/__init__.py +4 -0
  69. notionary/blocks/mixins/captions/caption_markdown_node_mixin.py +31 -0
  70. notionary/blocks/mixins/captions/caption_mixin.py +92 -0
  71. notionary/blocks/models.py +174 -0
  72. notionary/blocks/numbered_list/__init__.py +12 -2
  73. notionary/blocks/numbered_list/numbered_list_element.py +48 -56
  74. notionary/blocks/numbered_list/numbered_list_markdown_node.py +3 -1
  75. notionary/blocks/numbered_list/numbered_list_models.py +17 -0
  76. notionary/blocks/paragraph/__init__.py +12 -2
  77. notionary/blocks/paragraph/paragraph_element.py +40 -66
  78. notionary/blocks/paragraph/paragraph_markdown_node.py +2 -1
  79. notionary/blocks/paragraph/paragraph_models.py +16 -0
  80. notionary/blocks/pdf/__init__.py +13 -0
  81. notionary/blocks/pdf/pdf_element.py +97 -0
  82. notionary/blocks/pdf/pdf_markdown_node.py +37 -0
  83. notionary/blocks/pdf/pdf_models.py +11 -0
  84. notionary/blocks/quote/__init__.py +11 -2
  85. notionary/blocks/quote/quote_element.py +45 -62
  86. notionary/blocks/quote/quote_markdown_node.py +6 -3
  87. notionary/blocks/quote/quote_models.py +18 -0
  88. notionary/blocks/registry/__init__.py +4 -0
  89. notionary/blocks/registry/block_registry.py +60 -121
  90. notionary/blocks/registry/block_registry_builder.py +115 -59
  91. notionary/blocks/rich_text/__init__.py +33 -0
  92. notionary/blocks/rich_text/name_to_id_resolver.py +205 -0
  93. notionary/blocks/rich_text/rich_text_models.py +221 -0
  94. notionary/blocks/rich_text/text_inline_formatter.py +456 -0
  95. notionary/blocks/syntax_prompt_builder.py +137 -0
  96. notionary/blocks/table/__init__.py +16 -2
  97. notionary/blocks/table/table_element.py +136 -228
  98. notionary/blocks/table/table_markdown_node.py +2 -1
  99. notionary/blocks/table/table_models.py +28 -0
  100. notionary/blocks/table_of_contents/__init__.py +19 -0
  101. notionary/blocks/table_of_contents/table_of_contents_element.py +68 -0
  102. notionary/blocks/table_of_contents/table_of_contents_markdown_node.py +35 -0
  103. notionary/blocks/table_of_contents/table_of_contents_models.py +18 -0
  104. notionary/blocks/todo/__init__.py +9 -2
  105. notionary/blocks/todo/todo_element.py +52 -92
  106. notionary/blocks/todo/todo_markdown_node.py +2 -1
  107. notionary/blocks/todo/todo_models.py +19 -0
  108. notionary/blocks/toggle/__init__.py +13 -3
  109. notionary/blocks/toggle/toggle_element.py +69 -260
  110. notionary/blocks/toggle/toggle_markdown_node.py +25 -15
  111. notionary/blocks/toggle/toggle_models.py +17 -0
  112. notionary/blocks/toggleable_heading/__init__.py +6 -2
  113. notionary/blocks/toggleable_heading/toggleable_heading_element.py +86 -241
  114. notionary/blocks/toggleable_heading/toggleable_heading_markdown_node.py +26 -18
  115. notionary/blocks/types.py +130 -0
  116. notionary/blocks/video/__init__.py +8 -2
  117. notionary/blocks/video/video_element.py +70 -141
  118. notionary/blocks/video/video_element_models.py +10 -0
  119. notionary/blocks/video/video_markdown_node.py +13 -6
  120. notionary/database/client.py +26 -8
  121. notionary/database/database.py +13 -14
  122. notionary/database/database_filter_builder.py +2 -2
  123. notionary/database/database_provider.py +5 -4
  124. notionary/database/models.py +337 -0
  125. notionary/database/notion_database.py +6 -7
  126. notionary/file_upload/client.py +5 -7
  127. notionary/file_upload/models.py +3 -2
  128. notionary/file_upload/notion_file_upload.py +2 -3
  129. notionary/markdown/markdown_builder.py +729 -0
  130. notionary/markdown/markdown_document_model.py +228 -0
  131. notionary/{blocks → markdown}/markdown_node.py +1 -0
  132. notionary/models/notion_database_response.py +0 -338
  133. notionary/page/client.py +34 -15
  134. notionary/page/models.py +327 -0
  135. notionary/page/notion_page.py +136 -58
  136. notionary/page/{content/page_content_writer.py → page_content_deleting_service.py} +25 -59
  137. notionary/page/page_content_writer.py +177 -0
  138. notionary/page/page_context.py +65 -0
  139. notionary/page/reader/handler/__init__.py +19 -0
  140. notionary/page/reader/handler/base_block_renderer.py +44 -0
  141. notionary/page/reader/handler/block_processing_context.py +35 -0
  142. notionary/page/reader/handler/block_rendering_context.py +48 -0
  143. notionary/page/reader/handler/column_list_renderer.py +51 -0
  144. notionary/page/reader/handler/column_renderer.py +60 -0
  145. notionary/page/reader/handler/line_renderer.py +73 -0
  146. notionary/page/reader/handler/numbered_list_renderer.py +85 -0
  147. notionary/page/reader/handler/toggle_renderer.py +69 -0
  148. notionary/page/reader/handler/toggleable_heading_renderer.py +89 -0
  149. notionary/page/reader/page_content_retriever.py +81 -0
  150. notionary/page/search_filter_builder.py +2 -1
  151. notionary/page/writer/handler/__init__.py +24 -0
  152. notionary/page/writer/handler/code_handler.py +72 -0
  153. notionary/page/writer/handler/column_handler.py +141 -0
  154. notionary/page/writer/handler/column_list_handler.py +139 -0
  155. notionary/page/writer/handler/equation_handler.py +74 -0
  156. notionary/page/writer/handler/line_handler.py +35 -0
  157. notionary/page/writer/handler/line_processing_context.py +54 -0
  158. notionary/page/writer/handler/regular_line_handler.py +86 -0
  159. notionary/page/writer/handler/table_handler.py +66 -0
  160. notionary/page/writer/handler/toggle_handler.py +155 -0
  161. notionary/page/writer/handler/toggleable_heading_handler.py +173 -0
  162. notionary/page/writer/markdown_to_notion_converter.py +95 -0
  163. notionary/page/writer/markdown_to_notion_converter_context.py +30 -0
  164. notionary/page/writer/markdown_to_notion_formatting_post_processor.py +73 -0
  165. notionary/page/writer/notion_text_length_processor.py +150 -0
  166. notionary/telemetry/__init__.py +2 -2
  167. notionary/telemetry/service.py +3 -3
  168. notionary/user/__init__.py +2 -2
  169. notionary/user/base_notion_user.py +2 -1
  170. notionary/user/client.py +2 -3
  171. notionary/user/models.py +1 -0
  172. notionary/user/notion_bot_user.py +4 -5
  173. notionary/user/notion_user.py +3 -4
  174. notionary/user/notion_user_manager.py +23 -95
  175. notionary/util/__init__.py +3 -2
  176. notionary/util/fuzzy.py +2 -1
  177. notionary/util/logging_mixin.py +2 -2
  178. notionary/util/singleton_metaclass.py +1 -1
  179. notionary/workspace.py +6 -5
  180. notionary-0.2.22.dist-info/METADATA +237 -0
  181. notionary-0.2.22.dist-info/RECORD +200 -0
  182. notionary/blocks/document/__init__.py +0 -7
  183. notionary/blocks/document/document_element.py +0 -102
  184. notionary/blocks/document/document_markdown_node.py +0 -31
  185. notionary/blocks/image/__init__.py +0 -7
  186. notionary/blocks/image/image_element.py +0 -151
  187. notionary/blocks/markdown_builder.py +0 -356
  188. notionary/blocks/mention/__init__.py +0 -7
  189. notionary/blocks/mention/mention_element.py +0 -229
  190. notionary/blocks/mention/mention_markdown_node.py +0 -38
  191. notionary/blocks/prompts/element_prompt_builder.py +0 -83
  192. notionary/blocks/prompts/element_prompt_content.py +0 -41
  193. notionary/blocks/shared/models.py +0 -713
  194. notionary/blocks/shared/notion_block_element.py +0 -37
  195. notionary/blocks/shared/text_inline_formatter.py +0 -262
  196. notionary/blocks/shared/text_inline_formatter_new.py +0 -139
  197. notionary/database/models/page_result.py +0 -10
  198. notionary/models/notion_block_response.py +0 -264
  199. notionary/models/notion_page_response.py +0 -78
  200. notionary/models/search_response.py +0 -0
  201. notionary/page/__init__.py +0 -0
  202. notionary/page/content/markdown_whitespace_processor.py +0 -80
  203. notionary/page/content/notion_text_length_utils.py +0 -87
  204. notionary/page/content/page_content_retriever.py +0 -60
  205. notionary/page/formatting/line_processor.py +0 -153
  206. notionary/page/formatting/markdown_to_notion_converter.py +0 -153
  207. notionary/page/markdown_syntax_prompt_generator.py +0 -114
  208. notionary/page/notion_to_markdown_converter.py +0 -179
  209. notionary/page/properites/property_value_extractor.py +0 -0
  210. notionary/user/notion_user_provider.py +0 -1
  211. notionary-0.2.19.dist-info/METADATA +0 -225
  212. notionary-0.2.19.dist-info/RECORD +0 -150
  213. /notionary/{blocks/document/document_models.py → markdown/___init__.py} +0 -0
  214. /notionary/{blocks/image/image_models.py → markdown/makdown_document_model.py} +0 -0
  215. /notionary/{blocks/mention/mention_models.py → page/reader/handler/equation_renderer.py} +0 -0
  216. /notionary/{blocks/shared/__init__.py → page/writer/markdown_to_notion_post_processor.py} +0 -0
  217. /notionary/{blocks/toggleable_heading/toggleable_heading_models.py → page/writer/markdown_to_notion_text_length_post_processor.py} +0 -0
  218. /notionary/{elements/__init__.py → util/concurrency_limiter.py} +0 -0
  219. {notionary-0.2.19.dist-info → notionary-0.2.22.dist-info}/LICENSE +0 -0
  220. {notionary-0.2.19.dist-info → notionary-0.2.22.dist-info}/WHEEL +0 -0
@@ -0,0 +1,68 @@
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
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
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 = (input_match.group("color") or "default").lower()
38
+ return CreateTableOfContentsBlock(
39
+ table_of_contents=TableOfContentsBlock(color=color)
40
+ )
41
+
42
+ @classmethod
43
+ async def notion_to_markdown(cls, block: Block) -> Optional[str]:
44
+ # Fix: Use 'or' instead of 'and'
45
+ if block.type != BlockType.TABLE_OF_CONTENTS or not block.table_of_contents:
46
+ return None
47
+
48
+ color = block.table_of_contents.color.value
49
+
50
+ if color == "default":
51
+ return "[toc]"
52
+ return f"[toc]({color})"
53
+
54
+ @classmethod
55
+ @classmethod
56
+ def get_system_prompt_information(cls) -> Optional[BlockElementMarkdownInformation]:
57
+ """Get system prompt information for table of contents blocks."""
58
+ return BlockElementMarkdownInformation(
59
+ block_type=cls.__name__,
60
+ description="Table of contents blocks automatically generate navigation for page headings",
61
+ syntax_examples=[
62
+ "[toc]",
63
+ "[toc](blue)",
64
+ "[toc](blue_background)",
65
+ "[toc](gray_background)",
66
+ ],
67
+ usage_guidelines="Use to automatically generate a clickable table of contents from page headings. Optional color parameter changes the appearance. Default color is gray.",
68
+ )
@@ -0,0 +1,35 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Optional
4
+
5
+ from pydantic import BaseModel
6
+
7
+ from notionary.markdown.markdown_node import MarkdownNode
8
+
9
+
10
+ class TableOfContentsMarkdownBlockParams(BaseModel):
11
+ color: Optional[str] = "default"
12
+
13
+
14
+ class TableOfContentsMarkdownNode(MarkdownNode):
15
+ """
16
+ Programmatic interface for creating Markdown table of contents blocks.
17
+ Example:
18
+ [toc]
19
+ [toc](blue)
20
+ [toc](blue_background)
21
+ """
22
+
23
+ def __init__(self, color: Optional[str] = "default"):
24
+ self.color = color or "default"
25
+
26
+ @classmethod
27
+ def from_params(
28
+ cls, params: TableOfContentsMarkdownBlockParams
29
+ ) -> TableOfContentsMarkdownNode:
30
+ return cls(color=params.color)
31
+
32
+ def to_markdown(self) -> str:
33
+ if self.color == "default":
34
+ return "[toc]"
35
+ return f"[toc]({self.color})"
@@ -0,0 +1,18 @@
1
+ from typing import Literal
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: 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,7 +1,14 @@
1
- from .todo_element import TodoElement
2
- from .todo_markdown_node import TodoMarkdownNode
1
+ from notionary.blocks.todo.todo_element import TodoElement
2
+ from notionary.blocks.todo.todo_markdown_node import (
3
+ TodoMarkdownBlockParams,
4
+ TodoMarkdownNode,
5
+ )
6
+ from notionary.blocks.todo.todo_models import CreateToDoBlock, ToDoBlock
3
7
 
4
8
  __all__ = [
5
9
  "TodoElement",
10
+ "ToDoBlock",
11
+ "CreateToDoBlock",
6
12
  "TodoMarkdownNode",
13
+ "TodoMarkdownBlockParams",
7
14
  ]
@@ -1,16 +1,16 @@
1
+ from __future__ import annotations
2
+
1
3
  import re
2
- from typing import Dict, Any, Optional
4
+ from typing import TYPE_CHECKING, Optional
3
5
 
4
- from notionary.blocks import (
5
- ElementPromptContent,
6
- ElementPromptBuilder,
7
- NotionBlockResult,
8
- NotionBlockElement,
9
- )
10
- from notionary.blocks.shared.text_inline_formatter import TextInlineFormatter
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
11
 
12
12
 
13
- class TodoElement(NotionBlockElement):
13
+ class TodoElement(BaseBlockElement):
14
14
  """
15
15
  Handles conversion between Markdown todo items and Notion to_do blocks.
16
16
 
@@ -21,101 +21,61 @@ class TodoElement(NotionBlockElement):
21
21
  + [ ] Also works with plus sign
22
22
  """
23
23
 
24
- # Patterns for detecting Markdown todo items
25
- TODO_PATTERN = re.compile(r"^\s*[-*+]\s+\[\s?\]\s+(.+)$")
26
- DONE_PATTERN = re.compile(r"^\s*[-*+]\s+\[x\]\s+(.+)$")
27
-
28
- @classmethod
29
- def match_markdown(cls, text: str) -> bool:
30
- """Check if text is a markdown todo item."""
31
- return bool(
32
- TodoElement.TODO_PATTERN.match(text) or TodoElement.DONE_PATTERN.match(text)
33
- )
24
+ PATTERN = re.compile(r"^\s*[-*+]\s+\[ \]\s+(.+)$")
25
+ DONE_PATTERN = re.compile(r"^\s*[-*+]\s+\[x\]\s+(.+)$", re.IGNORECASE)
34
26
 
35
27
  @classmethod
36
- def match_notion(cls, block: Dict[str, Any]) -> bool:
37
- """Check if block is a Notion to_do block."""
38
- return block.get("type") == "to_do"
28
+ def match_notion(cls, block: Block) -> bool:
29
+ return block.type == BlockType.TO_DO and block.to_do
39
30
 
40
31
  @classmethod
41
- def markdown_to_notion(cls, text: str) -> NotionBlockResult:
42
- """Convert markdown todo item to Notion to_do block."""
43
- done_match = TodoElement.DONE_PATTERN.match(text)
44
- if done_match:
45
- content = done_match.group(1)
46
- return TodoElement._create_todo_block(content, True)
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
47
45
 
48
- todo_match = TodoElement.TODO_PATTERN.match(text)
49
- if todo_match:
50
- content = todo_match.group(1)
51
- return TodoElement._create_todo_block(content, False)
46
+ # build rich text
47
+ rich = await TextInlineFormatter.parse_inline_formatting(content)
52
48
 
53
- return None
49
+ todo_content = ToDoBlock(
50
+ rich_text=rich,
51
+ checked=checked,
52
+ color="default",
53
+ )
54
+ return CreateToDoBlock(to_do=todo_content)
54
55
 
55
56
  @classmethod
56
- def notion_to_markdown(cls, block: Dict[str, Any]) -> Optional[str]:
57
+ async def notion_to_markdown(cls, block: Block) -> Optional[str]:
57
58
  """Convert Notion to_do block to markdown todo item."""
58
- if block.get("type") != "to_do":
59
+ if block.type != BlockType.TO_DO or not block.to_do:
59
60
  return None
60
61
 
61
- todo_data = block.get("to_do", {})
62
- checked = todo_data.get("checked", False)
63
-
64
- # Extract text content
65
- rich_text = todo_data.get("rich_text", [])
66
- content = TextInlineFormatter.extract_text_with_formatting(rich_text)
67
-
68
- # Format as markdown todo item
69
- checkbox = "[x]" if checked else "[ ]"
62
+ td = block.to_do
63
+ content = await TextInlineFormatter.extract_text_with_formatting(td.rich_text)
64
+ checkbox = "[x]" if td.checked else "[ ]"
70
65
  return f"- {checkbox} {content}"
71
66
 
72
67
  @classmethod
73
- def _create_todo_block(cls, content: str, checked: bool) -> Dict[str, Any]:
74
- """
75
- Create a Notion to_do block.
76
-
77
- Args:
78
- content: The text content of the todo item
79
- checked: Whether the todo item is checked
80
-
81
- Returns:
82
- Notion to_do block dictionary
83
- """
84
- return {
85
- "type": "to_do",
86
- "to_do": {
87
- "rich_text": TextInlineFormatter.parse_inline_formatting(content),
88
- "checked": checked,
89
- "color": "default",
90
- },
91
- }
92
-
93
- @classmethod
94
- def is_multiline(cls) -> bool:
95
- return False
96
-
97
- @classmethod
98
- def get_llm_prompt_content(cls) -> ElementPromptContent:
99
- """
100
- Returns structured LLM prompt metadata for the todo element.
101
- """
102
- return (
103
- ElementPromptBuilder()
104
- .with_description(
105
- "Creates interactive to-do items with checkboxes that can be marked as complete."
106
- )
107
- .with_usage_guidelines(
108
- "Use to-do items for task lists, checklists, or tracking progress on items that need to be completed. "
109
- "Todo items are interactive in Notion and can be checked/unchecked directly."
110
- )
111
- .with_syntax("- [ ] Task to complete")
112
- .with_examples(
113
- [
114
- "- [ ] Draft project proposal",
115
- "- [x] Create initial timeline",
116
- "* [ ] Review code changes",
117
- "+ [x] Finalize handoff checklist",
118
- ]
119
- )
120
- .build()
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.",
121
81
  )
@@ -1,7 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from pydantic import BaseModel
4
- from notionary.blocks.markdown_node import MarkdownNode
4
+
5
+ from notionary.markdown.markdown_node import MarkdownNode
5
6
 
6
7
 
7
8
  class TodoMarkdownBlockParams(BaseModel):
@@ -0,0 +1,19 @@
1
+ from typing import Literal
2
+
3
+ from pydantic import BaseModel, Field
4
+
5
+ from notionary.blocks.models import Block
6
+ from notionary.blocks.rich_text.rich_text_models import RichTextObject
7
+ from notionary.blocks.types import BlockColor
8
+
9
+
10
+ class ToDoBlock(BaseModel):
11
+ rich_text: list[RichTextObject]
12
+ checked: bool = False
13
+ color: BlockColor = BlockColor.DEFAULT
14
+ children: list[Block] = Field(default_factory=list)
15
+
16
+
17
+ class CreateToDoBlock(BaseModel):
18
+ type: Literal["to_do"] = "to_do"
19
+ to_do: ToDoBlock
@@ -1,4 +1,14 @@
1
- from .toggle_element import ToggleElement
2
- from .toggle_markdown_node import ToggleMarkdownNode, ToggleMarkdownBlockParams
1
+ from notionary.blocks.toggle.toggle_element import ToggleElement
2
+ from notionary.blocks.toggle.toggle_markdown_node import (
3
+ ToggleMarkdownBlockParams,
4
+ ToggleMarkdownNode,
5
+ )
6
+ from notionary.blocks.toggle.toggle_models import CreateToggleBlock, ToggleBlock
3
7
 
4
- __all__ = ["ToggleElement", "ToggleMarkdownNode", "ToggleMarkdownBlockParams"]
8
+ __all__ = [
9
+ "ToggleElement",
10
+ "ToggleBlock",
11
+ "CreateToggleBlock",
12
+ "ToggleMarkdownNode",
13
+ "ToggleMarkdownBlockParams",
14
+ ]