notionary 0.1.25__py3-none-any.whl → 0.1.27__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/elements/audio_element.py +41 -38
- notionary/elements/bookmark_element.py +36 -27
- notionary/elements/bulleted_list_element.py +28 -21
- notionary/elements/callout_element.py +39 -31
- notionary/elements/code_block_element.py +38 -26
- notionary/elements/divider_element.py +29 -18
- notionary/elements/embed_element.py +37 -28
- notionary/elements/heading_element.py +39 -24
- notionary/elements/image_element.py +33 -24
- notionary/elements/mention_element.py +40 -29
- notionary/elements/notion_block_element.py +13 -31
- notionary/elements/numbered_list_element.py +29 -20
- notionary/elements/paragraph_element.py +37 -31
- notionary/elements/prompts/element_prompt_content.py +91 -7
- notionary/elements/prompts/synthax_prompt_builder.py +63 -16
- notionary/elements/qoute_element.py +72 -74
- notionary/elements/registry/block_element_registry_builder.py +6 -9
- notionary/elements/table_element.py +49 -36
- notionary/elements/text_inline_formatter.py +23 -15
- notionary/elements/{todo_lists.py → todo_element.py} +34 -25
- notionary/elements/toggle_element.py +184 -108
- notionary/elements/toggleable_heading_element.py +269 -0
- notionary/elements/video_element.py +37 -28
- notionary/page/content/page_content_manager.py +3 -8
- notionary/page/markdown_to_notion_converter.py +269 -274
- notionary/page/metadata/notion_icon_manager.py +13 -7
- notionary/page/notion_page.py +3 -5
- notionary/page/notion_to_markdown_converter.py +20 -95
- {notionary-0.1.25.dist-info → notionary-0.1.27.dist-info}/METADATA +1 -1
- notionary-0.1.27.dist-info/RECORD +58 -0
- {notionary-0.1.25.dist-info → notionary-0.1.27.dist-info}/WHEEL +1 -1
- notionary/elements/column_element.py +0 -307
- notionary-0.1.25.dist-info/RECORD +0 -58
- {notionary-0.1.25.dist-info → notionary-0.1.27.dist-info}/licenses/LICENSE +0 -0
- {notionary-0.1.25.dist-info → notionary-0.1.27.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,10 @@
|
|
1
1
|
import re
|
2
2
|
from typing import Dict, Any, Optional, List
|
3
3
|
from notionary.elements.notion_block_element import NotionBlockElement
|
4
|
-
from notionary.elements.prompts.element_prompt_content import
|
4
|
+
from notionary.elements.prompts.element_prompt_content import (
|
5
|
+
ElementPromptBuilder,
|
6
|
+
ElementPromptContent,
|
7
|
+
)
|
5
8
|
|
6
9
|
|
7
10
|
class VideoElement(NotionBlockElement):
|
@@ -30,19 +33,19 @@ class VideoElement(NotionBlockElement):
|
|
30
33
|
re.compile(r"(?:https?://)?(?:www\.)?youtu\.be/([a-zA-Z0-9_-]{11})"),
|
31
34
|
]
|
32
35
|
|
33
|
-
@
|
34
|
-
def match_markdown(text: str) -> bool:
|
36
|
+
@classmethod
|
37
|
+
def match_markdown(cls, text: str) -> bool:
|
35
38
|
"""Check if text is a markdown video embed."""
|
36
39
|
text = text.strip()
|
37
40
|
return text.startswith("@[") and bool(VideoElement.PATTERN.match(text))
|
38
41
|
|
39
|
-
@
|
40
|
-
def match_notion(block: Dict[str, Any]) -> bool:
|
42
|
+
@classmethod
|
43
|
+
def match_notion(cls, block: Dict[str, Any]) -> bool:
|
41
44
|
"""Check if block is a Notion video."""
|
42
45
|
return block.get("type") == "video"
|
43
46
|
|
44
|
-
@
|
45
|
-
def is_youtube_url(url: str) -> bool:
|
47
|
+
@classmethod
|
48
|
+
def is_youtube_url(cls, url: str) -> bool:
|
46
49
|
"""Check if URL is a YouTube video and return video ID if it is."""
|
47
50
|
for pattern in VideoElement.YOUTUBE_PATTERNS:
|
48
51
|
match = pattern.match(url)
|
@@ -50,8 +53,8 @@ class VideoElement(NotionBlockElement):
|
|
50
53
|
return True
|
51
54
|
return False
|
52
55
|
|
53
|
-
@
|
54
|
-
def get_youtube_id(url: str) -> Optional[str]:
|
56
|
+
@classmethod
|
57
|
+
def get_youtube_id(cls, url: str) -> Optional[str]:
|
55
58
|
"""Extract YouTube video ID from URL."""
|
56
59
|
for pattern in VideoElement.YOUTUBE_PATTERNS:
|
57
60
|
match = pattern.match(url)
|
@@ -59,8 +62,8 @@ class VideoElement(NotionBlockElement):
|
|
59
62
|
return match.group(1)
|
60
63
|
return None
|
61
64
|
|
62
|
-
@
|
63
|
-
def markdown_to_notion(text: str) -> Optional[Dict[str, Any]]:
|
65
|
+
@classmethod
|
66
|
+
def markdown_to_notion(cls, text: str) -> Optional[Dict[str, Any]]:
|
64
67
|
"""Convert markdown video embed to Notion video block."""
|
65
68
|
video_match = VideoElement.PATTERN.match(text.strip())
|
66
69
|
if not video_match:
|
@@ -88,8 +91,8 @@ class VideoElement(NotionBlockElement):
|
|
88
91
|
|
89
92
|
return video_block
|
90
93
|
|
91
|
-
@
|
92
|
-
def notion_to_markdown(block: Dict[str, Any]) -> Optional[str]:
|
94
|
+
@classmethod
|
95
|
+
def notion_to_markdown(cls, block: Dict[str, Any]) -> Optional[str]:
|
93
96
|
"""Convert Notion video block to markdown video embed."""
|
94
97
|
if block.get("type") != "video":
|
95
98
|
return None
|
@@ -114,13 +117,13 @@ class VideoElement(NotionBlockElement):
|
|
114
117
|
|
115
118
|
return f"@[{caption}]({url})"
|
116
119
|
|
117
|
-
@
|
118
|
-
def is_multiline() -> bool:
|
120
|
+
@classmethod
|
121
|
+
def is_multiline(cls) -> bool:
|
119
122
|
"""Videos are single-line elements."""
|
120
123
|
return False
|
121
124
|
|
122
|
-
@
|
123
|
-
def _extract_text_content(rich_text: List[Dict[str, Any]]) -> str:
|
125
|
+
@classmethod
|
126
|
+
def _extract_text_content(cls, rich_text: List[Dict[str, Any]]) -> str:
|
124
127
|
"""Extract plain text content from Notion rich_text elements."""
|
125
128
|
result = ""
|
126
129
|
for text_obj in rich_text:
|
@@ -135,16 +138,22 @@ class VideoElement(NotionBlockElement):
|
|
135
138
|
"""
|
136
139
|
Returns structured LLM prompt metadata for the video element.
|
137
140
|
"""
|
138
|
-
return
|
139
|
-
|
140
|
-
|
141
|
+
return (
|
142
|
+
ElementPromptBuilder()
|
143
|
+
.with_description(
|
144
|
+
"Embeds video content from external sources like YouTube or direct video URLs."
|
145
|
+
)
|
146
|
+
.with_usage_guidelines(
|
141
147
|
"Use video embeds when you want to include multimedia content directly in your document. "
|
142
148
|
"Videos are useful for tutorials, demonstrations, presentations, or any content that benefits from visual explanation."
|
143
|
-
)
|
144
|
-
"
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
149
|
+
)
|
150
|
+
.with_syntax("@[Caption](https://example.com/video.mp4)")
|
151
|
+
.with_examples(
|
152
|
+
[
|
153
|
+
"@[How to use this feature](https://www.youtube.com/watch?v=dQw4w9WgXcQ)",
|
154
|
+
"@[Product demo](https://example.com/videos/demo.mp4)",
|
155
|
+
"@[](https://youtu.be/dQw4w9WgXcQ)",
|
156
|
+
]
|
157
|
+
)
|
158
|
+
.build()
|
159
|
+
)
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import json
|
1
2
|
from typing import Any, Dict, List, Optional
|
2
3
|
|
3
4
|
from notionary.elements.registry.block_element_registry import BlockElementRegistry
|
@@ -32,9 +33,7 @@ class PageContentManager(LoggingMixin):
|
|
32
33
|
)
|
33
34
|
self._chunker = NotionPageContentChunker()
|
34
35
|
|
35
|
-
async def append_markdown(
|
36
|
-
self, markdown_text: str, append_divider: bool = False
|
37
|
-
) -> str:
|
36
|
+
async def append_markdown(self, markdown_text: str) -> str:
|
38
37
|
"""
|
39
38
|
Append markdown text to a Notion page, automatically handling content length limits.
|
40
39
|
First strips out triple backtick markdown fences if they wrap the entire content.
|
@@ -45,11 +44,6 @@ class PageContentManager(LoggingMixin):
|
|
45
44
|
"""
|
46
45
|
try:
|
47
46
|
blocks = self._markdown_to_notion_converter.convert(markdown_text)
|
48
|
-
|
49
|
-
if append_divider:
|
50
|
-
divider_block = {"type": "divider", "divider": {}}
|
51
|
-
blocks.append(divider_block)
|
52
|
-
|
53
47
|
fixed_blocks = self._chunker.fix_blocks_content_length(blocks)
|
54
48
|
|
55
49
|
result = await self._client.patch(
|
@@ -162,6 +156,7 @@ class PageContentManager(LoggingMixin):
|
|
162
156
|
if parent_id is None
|
163
157
|
else await self.get_block_children(parent_id)
|
164
158
|
)
|
159
|
+
|
165
160
|
if not blocks:
|
166
161
|
return []
|
167
162
|
|