notionary 0.2.17__py3-none-any.whl → 0.2.19__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 +3 -2
- notionary/blocks/__init__.py +54 -25
- notionary/blocks/audio/__init__.py +7 -0
- notionary/blocks/audio/audio_element.py +152 -0
- notionary/blocks/audio/audio_markdown_node.py +29 -0
- notionary/blocks/audio/audio_models.py +59 -0
- notionary/blocks/bookmark/__init__.py +7 -0
- notionary/blocks/{bookmark_element.py → bookmark/bookmark_element.py} +20 -65
- notionary/blocks/bookmark/bookmark_markdown_node.py +43 -0
- notionary/blocks/bookmark/bookmark_models.py +0 -0
- notionary/blocks/bulleted_list/__init__.py +7 -0
- notionary/blocks/{bulleted_list_element.py → bulleted_list/bulleted_list_element.py} +7 -3
- notionary/blocks/bulleted_list/bulleted_list_markdown_node.py +33 -0
- notionary/blocks/bulleted_list/bulleted_list_models.py +0 -0
- notionary/blocks/callout/__init__.py +7 -0
- notionary/blocks/callout/callout_element.py +132 -0
- notionary/blocks/callout/callout_markdown_node.py +31 -0
- notionary/blocks/callout/callout_models.py +0 -0
- notionary/blocks/code/__init__.py +7 -0
- notionary/blocks/{code_block_element.py → code/code_element.py} +72 -40
- notionary/blocks/code/code_markdown_node.py +43 -0
- notionary/blocks/code/code_models.py +0 -0
- notionary/blocks/column/__init__.py +5 -0
- notionary/blocks/{column_element.py → column/column_element.py} +24 -55
- notionary/blocks/column/column_models.py +0 -0
- notionary/blocks/divider/__init__.py +7 -0
- notionary/blocks/{divider_element.py → divider/divider_element.py} +11 -3
- notionary/blocks/divider/divider_markdown_node.py +24 -0
- notionary/blocks/divider/divider_models.py +0 -0
- notionary/blocks/document/__init__.py +7 -0
- notionary/blocks/document/document_element.py +102 -0
- notionary/blocks/document/document_markdown_node.py +31 -0
- notionary/blocks/document/document_models.py +0 -0
- notionary/blocks/embed/__init__.py +7 -0
- notionary/blocks/{embed_element.py → embed/embed_element.py} +50 -32
- notionary/blocks/embed/embed_markdown_node.py +30 -0
- notionary/blocks/embed/embed_models.py +0 -0
- notionary/blocks/heading/__init__.py +7 -0
- notionary/blocks/{heading_element.py → heading/heading_element.py} +25 -17
- notionary/blocks/heading/heading_markdown_node.py +29 -0
- notionary/blocks/heading/heading_models.py +0 -0
- notionary/blocks/image/__init__.py +7 -0
- notionary/blocks/{image_element.py → image/image_element.py} +62 -42
- notionary/blocks/image/image_markdown_node.py +33 -0
- notionary/blocks/image/image_models.py +0 -0
- notionary/blocks/markdown_builder.py +356 -0
- notionary/blocks/markdown_node.py +29 -0
- notionary/blocks/mention/__init__.py +7 -0
- notionary/blocks/{mention_element.py → mention/mention_element.py} +6 -2
- notionary/blocks/mention/mention_markdown_node.py +38 -0
- notionary/blocks/mention/mention_models.py +0 -0
- notionary/blocks/numbered_list/__init__.py +7 -0
- notionary/blocks/{numbered_list_element.py → numbered_list/numbered_list_element.py} +10 -6
- notionary/blocks/numbered_list/numbered_list_markdown_node.py +29 -0
- notionary/blocks/numbered_list/numbered_list_models.py +0 -0
- notionary/blocks/paragraph/__init__.py +7 -0
- notionary/blocks/{paragraph_element.py → paragraph/paragraph_element.py} +7 -3
- notionary/blocks/paragraph/paragraph_markdown_node.py +25 -0
- notionary/blocks/paragraph/paragraph_models.py +0 -0
- notionary/blocks/quote/__init__.py +7 -0
- notionary/blocks/quote/quote_element.py +92 -0
- notionary/blocks/quote/quote_markdown_node.py +23 -0
- notionary/blocks/quote/quote_models.py +0 -0
- notionary/blocks/registry/block_registry.py +17 -3
- notionary/blocks/registry/block_registry_builder.py +90 -178
- notionary/blocks/shared/__init__.py +0 -0
- notionary/blocks/shared/block_client.py +256 -0
- notionary/blocks/shared/models.py +713 -0
- notionary/blocks/{notion_block_element.py → shared/notion_block_element.py} +8 -5
- notionary/blocks/{text_inline_formatter.py → shared/text_inline_formatter.py} +14 -14
- notionary/blocks/shared/text_inline_formatter_new.py +139 -0
- notionary/blocks/table/__init__.py +7 -0
- notionary/blocks/{table_element.py → table/table_element.py} +23 -11
- notionary/blocks/table/table_markdown_node.py +40 -0
- notionary/blocks/table/table_models.py +0 -0
- notionary/blocks/todo/__init__.py +7 -0
- notionary/blocks/{todo_element.py → todo/todo_element.py} +8 -4
- notionary/blocks/todo/todo_markdown_node.py +31 -0
- notionary/blocks/todo/todo_models.py +0 -0
- notionary/blocks/toggle/__init__.py +4 -0
- notionary/blocks/{toggle_element.py → toggle/toggle_element.py} +7 -3
- notionary/blocks/toggle/toggle_markdown_node.py +35 -0
- notionary/blocks/toggle/toggle_models.py +0 -0
- notionary/blocks/toggleable_heading/__init__.py +9 -0
- notionary/blocks/{toggleable_heading_element.py → toggleable_heading/toggleable_heading_element.py} +8 -4
- notionary/blocks/toggleable_heading/toggleable_heading_markdown_node.py +43 -0
- notionary/blocks/toggleable_heading/toggleable_heading_models.py +0 -0
- notionary/blocks/video/__init__.py +7 -0
- notionary/blocks/{video_element.py → video/video_element.py} +82 -57
- notionary/blocks/video/video_markdown_node.py +30 -0
- notionary/file_upload/notion_file_upload.py +1 -1
- notionary/page/content/markdown_whitespace_processor.py +80 -0
- notionary/page/content/notion_text_length_utils.py +87 -0
- notionary/page/content/page_content_retriever.py +18 -10
- notionary/page/content/page_content_writer.py +97 -148
- notionary/page/formatting/line_processor.py +153 -0
- notionary/page/formatting/markdown_to_notion_converter.py +104 -425
- notionary/page/notion_page.py +9 -11
- notionary/page/notion_to_markdown_converter.py +9 -13
- notionary/util/factory_decorator.py +0 -0
- notionary/workspace.py +0 -1
- {notionary-0.2.17.dist-info → notionary-0.2.19.dist-info}/METADATA +1 -1
- notionary-0.2.19.dist-info/RECORD +150 -0
- notionary/blocks/audio_element.py +0 -144
- notionary/blocks/callout_element.py +0 -122
- notionary/blocks/document_element.py +0 -194
- notionary/blocks/notion_block_client.py +0 -26
- notionary/blocks/qoute_element.py +0 -169
- notionary/page/content/notion_page_content_chunker.py +0 -84
- notionary/page/formatting/spacer_rules.py +0 -483
- notionary-0.2.17.dist-info/RECORD +0 -85
- {notionary-0.2.17.dist-info → notionary-0.2.19.dist-info}/LICENSE +0 -0
- {notionary-0.2.17.dist-info → notionary-0.2.19.dist-info}/WHEEL +0 -0
@@ -1,6 +1,4 @@
|
|
1
|
-
from typing import Dict, Any
|
2
|
-
|
3
|
-
from notionary.blocks import BlockRegistry, BlockRegistryBuilder
|
1
|
+
from typing import Dict, Any
|
4
2
|
|
5
3
|
|
6
4
|
class NotionToMarkdownConverter:
|
@@ -9,15 +7,13 @@ class NotionToMarkdownConverter:
|
|
9
7
|
TOGGLE_ELEMENT_TYPES = ["toggle", "toggleable_heading"]
|
10
8
|
LIST_ITEM_TYPES = ["numbered_list_item", "bulleted_list_item"]
|
11
9
|
|
12
|
-
def __init__(self, block_registry
|
10
|
+
def __init__(self, block_registry):
|
13
11
|
"""
|
14
12
|
Initialize the NotionToMarkdownConverter.
|
15
13
|
"""
|
16
|
-
self._block_registry =
|
17
|
-
block_registry or BlockRegistryBuilder().create_full_registry()
|
18
|
-
)
|
14
|
+
self._block_registry = block_registry
|
19
15
|
|
20
|
-
def convert(self, blocks:
|
16
|
+
def convert(self, blocks: list[Dict[str, Any]]) -> str:
|
21
17
|
"""
|
22
18
|
Convert Notion blocks to Markdown text, handling nested structures.
|
23
19
|
"""
|
@@ -102,7 +98,7 @@ class NotionToMarkdownConverter:
|
|
102
98
|
indent = " " * spaces
|
103
99
|
return "\n".join([f"{indent}{line}" for line in text.split("\n")])
|
104
100
|
|
105
|
-
def extract_toggle_content(self, blocks:
|
101
|
+
def extract_toggle_content(self, blocks: list[Dict[str, Any]]) -> str:
|
106
102
|
"""
|
107
103
|
Extract only the content of toggles from blocks.
|
108
104
|
"""
|
@@ -117,7 +113,7 @@ class NotionToMarkdownConverter:
|
|
117
113
|
return "\n".join(toggle_contents)
|
118
114
|
|
119
115
|
def _extract_toggle_content_recursive(
|
120
|
-
self, block: Dict[str, Any], result:
|
116
|
+
self, block: Dict[str, Any], result: list[str]
|
121
117
|
) -> None:
|
122
118
|
"""
|
123
119
|
Recursively extract toggle content from a block and its children.
|
@@ -137,7 +133,7 @@ class NotionToMarkdownConverter:
|
|
137
133
|
return block.get("type") in self.TOGGLE_ELEMENT_TYPES and "children" in block
|
138
134
|
|
139
135
|
def _add_toggle_header_to_result(
|
140
|
-
self, block: Dict[str, Any], result:
|
136
|
+
self, block: Dict[str, Any], result: list[str]
|
141
137
|
) -> None:
|
142
138
|
"""
|
143
139
|
Add toggle header text to result list.
|
@@ -156,7 +152,7 @@ class NotionToMarkdownConverter:
|
|
156
152
|
result.append(f"### {toggle_text}")
|
157
153
|
|
158
154
|
def _add_toggle_children_to_result(
|
159
|
-
self, block: Dict[str, Any], result:
|
155
|
+
self, block: Dict[str, Any], result: list[str]
|
160
156
|
) -> None:
|
161
157
|
"""
|
162
158
|
Add formatted toggle children to result list.
|
@@ -173,7 +169,7 @@ class NotionToMarkdownConverter:
|
|
173
169
|
if child_text:
|
174
170
|
result.append(f"- {child_text}")
|
175
171
|
|
176
|
-
def _extract_text_from_rich_text(self, rich_text:
|
172
|
+
def _extract_text_from_rich_text(self, rich_text: list[Dict[str, Any]]) -> str:
|
177
173
|
"""
|
178
174
|
Extract plain text from Notion's rich text array.
|
179
175
|
"""
|
File without changes
|
notionary/workspace.py
CHANGED
@@ -28,7 +28,6 @@ class NotionWorkspace(LoggingMixin):
|
|
28
28
|
Search for pages globally across Notion workspace.
|
29
29
|
"""
|
30
30
|
response = await self.page_client.search_pages(query, limit=limit)
|
31
|
-
# Parallelisiere die Erzeugung der NotionPage-Instanzen
|
32
31
|
return await asyncio.gather(
|
33
32
|
*(NotionPage.from_page_id(page.id) for page in response.results)
|
34
33
|
)
|
@@ -0,0 +1,150 @@
|
|
1
|
+
notionary/__init__.py,sha256=klSdVgq1HZ6OU8bPo3YsyG7RTKCth5MjM8SkI7EH7Is,534
|
2
|
+
notionary/base_notion_client.py,sha256=WIAIKZeGCeAwtHWnL4Kfcmzv2TBlxvz7cfGF26i89y0,7067
|
3
|
+
notionary/blocks/__init__.py,sha256=CzHZg3ml2HD96fXRIgu-WXlH86UfQrlV77NdXN1C6UI,3155
|
4
|
+
notionary/blocks/audio/__init__.py,sha256=0GSTSbjAu4RV56qm22_xd7JkDRvrJNRDgGPTJT1leIQ,158
|
5
|
+
notionary/blocks/audio/audio_element.py,sha256=sjKTJR23whKTdp5pzkphTmd4q2hIFMwQvo6Qyoov3c0,5344
|
6
|
+
notionary/blocks/audio/audio_markdown_node.py,sha256=y0-qgrUM06XUFLdHhszC5OChhSRHpHKYXmOhEXrtetQ,831
|
7
|
+
notionary/blocks/audio/audio_models.py,sha256=rMNzvvhj8gYFKNALCT1oDdmuI6I5zlJgmVyENzij21s,1472
|
8
|
+
notionary/blocks/bookmark/__init__.py,sha256=ewtAXUCrqzY3VZ30A3SJf3lf5x_aX1K7u_HGDj0mVR8,176
|
9
|
+
notionary/blocks/bookmark/bookmark_element.py,sha256=OrDRXdCO6VzIY6OuNj9BNJuobEoGM3IUoO1fVjz_SoM,6148
|
10
|
+
notionary/blocks/bookmark/bookmark_markdown_node.py,sha256=39Uh518tTutU4_UDFQlpAY8lHgiCLW0_a9Kt7EMhsvg,1440
|
11
|
+
notionary/blocks/bookmark/bookmark_models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
|
+
notionary/blocks/bulleted_list/__init__.py,sha256=7hlIuGEp29mCZX_HOA2LksJr1wOUggwGKe-g08WxadY,202
|
13
|
+
notionary/blocks/bulleted_list/bulleted_list_element.py,sha256=g6nYmLisJh8zhXTPZO6DPsNZK4NaeZp8fqB2YJ89Pqo,2639
|
14
|
+
notionary/blocks/bulleted_list/bulleted_list_markdown_node.py,sha256=B7MP6dwCgwoyaeGmbGdvCsPNUhLHUl7oElV8-h-rzhY,823
|
15
|
+
notionary/blocks/bulleted_list/bulleted_list_models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
16
|
+
notionary/blocks/callout/__init__.py,sha256=PQnqH15cj1u5GVvbGm6jsWA_zN9SH7maSNNPP7quiUg,170
|
17
|
+
notionary/blocks/callout/callout_element.py,sha256=jn8DOCW86fuavZrjRu3AvW3aEj_P0jXmOyc7Av4tfVs,4553
|
18
|
+
notionary/blocks/callout/callout_markdown_node.py,sha256=sRy-F5kXPQRQU1HEnOPbZaJZ-nxDD8XmLHBIQFQOUDE,942
|
19
|
+
notionary/blocks/callout/callout_models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
20
|
+
notionary/blocks/code/__init__.py,sha256=24uLJhL8tcGXWX1eNT9YYzZ6qKobQnxYoe5lASTOwzc,152
|
21
|
+
notionary/blocks/code/code_element.py,sha256=EV21-3VhW6ItrGq497bAgG_SKl65YuXb486XjixJIes,8732
|
22
|
+
notionary/blocks/code/code_markdown_node.py,sha256=DxWeiovmO9aP4eTX98ihMNQfwdZeItXOgO2J0YfkNf0,1191
|
23
|
+
notionary/blocks/code/code_models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
24
|
+
notionary/blocks/column/__init__.py,sha256=QAC1nPTy8fQIBke1liI5sILFCyvN92yrjBTIRnVd6lE,83
|
25
|
+
notionary/blocks/column/column_element.py,sha256=MU6fY0WdzJz5XI8MHe-Nl_vadSXWHCrHXQKWgvEnVAY,11615
|
26
|
+
notionary/blocks/column/column_models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
27
|
+
notionary/blocks/divider/__init__.py,sha256=gxDX3HtNXSjqqyu3j7LcpcxnxobTjKlS2nj_Zf9VSpc,170
|
28
|
+
notionary/blocks/divider/divider_element.py,sha256=RGM0X7Y_mQnBnPC2rRb9rdlYuHDhaiCRurHkaGJf4H8,2443
|
29
|
+
notionary/blocks/divider/divider_markdown_node.py,sha256=PtUyYSDGAiGBfP7AKEpAP3XERpEi75qyz2_MFZ0U4jk,579
|
30
|
+
notionary/blocks/divider/divider_models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
31
|
+
notionary/blocks/document/__init__.py,sha256=KF_7ISXLqvEESomvERpLFwUxy2g5IYWR-uuZajfjt0Y,176
|
32
|
+
notionary/blocks/document/document_element.py,sha256=7gEOpv3CeryxkOQ5mrJI-yVKYFq8nzq7d5af0qVEmAo,4022
|
33
|
+
notionary/blocks/document/document_markdown_node.py,sha256=vtqTgyZ2xnxbIocpfg2UYCGffx4aCp7Ng9mvK14v9DA,1058
|
34
|
+
notionary/blocks/document/document_models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
35
|
+
notionary/blocks/embed/__init__.py,sha256=7fEUdAsekiE3wc2YjbUOEFXqD77602q22KyPKqP9ns0,158
|
36
|
+
notionary/blocks/embed/embed_element.py,sha256=A0hX_wBbvEbq0yd5pcWpNQIOcNBVn0JDBC1p3HJ9_2U,5080
|
37
|
+
notionary/blocks/embed/embed_markdown_node.py,sha256=HFh9lMjV3zQz0HPEG7ib77i2PKt6PwZIXpokcjrdh8U,902
|
38
|
+
notionary/blocks/embed/embed_models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
39
|
+
notionary/blocks/heading/__init__.py,sha256=OUFLp3Oketw4BTiqqxld9Hp-I-_oUWYL630IltZK6xA,170
|
40
|
+
notionary/blocks/heading/heading_element.py,sha256=BQDjSwnd9vpu-qxaKgOb0TBqfy8koT5YH6BTDgtbXm0,3447
|
41
|
+
notionary/blocks/heading/heading_markdown_node.py,sha256=XIfoxPdBihykAySQTfV94-WIU0cMsUxtfbhgiEIiP7Y,877
|
42
|
+
notionary/blocks/heading/heading_models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
43
|
+
notionary/blocks/image/__init__.py,sha256=4ky2S6bYkrsfswati_bRwrl6IVaFqCJlLDJROS7IvOA,158
|
44
|
+
notionary/blocks/image/image_element.py,sha256=5MjO3ZaJTh2ld8J5f9JlgSU9O4mqmKV8-ztBqTSGppY,5432
|
45
|
+
notionary/blocks/image/image_markdown_node.py,sha256=hxSASo5lXEBbFHXXu9U8xPz5Z7wpWGLJqSu-RRIRhWE,1029
|
46
|
+
notionary/blocks/image/image_models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
47
|
+
notionary/blocks/markdown_builder.py,sha256=HJKN1mmxBO_zI3D9JPPKXX10brdN1bf8Q2FEJg1ay4Q,10387
|
48
|
+
notionary/blocks/markdown_node.py,sha256=ZIbdok878aCMHnMh6k1kAftcPexQgiWFyHcSMNWepZo,715
|
49
|
+
notionary/blocks/mention/__init__.py,sha256=C6l5WqMjrD8MrA_rE0e22U-gSddlVWNVtGg8lcYfFyk,170
|
50
|
+
notionary/blocks/mention/mention_element.py,sha256=wEmw6l65CIin9rfrM4Hnb9kraRA5US0LKB-SpstjlqA,8155
|
51
|
+
notionary/blocks/mention/mention_markdown_node.py,sha256=zcKMRIWXHJzPg8C8nj5U_r2Q-WZrIPmNMcTwC-pTU60,1325
|
52
|
+
notionary/blocks/mention/mention_models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
53
|
+
notionary/blocks/numbered_list/__init__.py,sha256=T7IMAp542u56X8vooRbs1NcbggMRDQ778QSCxMyifbA,202
|
54
|
+
notionary/blocks/numbered_list/numbered_list_element.py,sha256=UA_VKldZ8bxRSe4qnikvTMcTyIM5BsRZf5QOlmAZxo8,2630
|
55
|
+
notionary/blocks/numbered_list/numbered_list_markdown_node.py,sha256=BTyfhoInvTcw-6zSRtIzBNjIOpQvHPtqoXBp3bKrkgY,779
|
56
|
+
notionary/blocks/numbered_list/numbered_list_models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
57
|
+
notionary/blocks/paragraph/__init__.py,sha256=XudhEdGaD2uIdJM4saygESClU5w3TBIq38kpR8huLps,182
|
58
|
+
notionary/blocks/paragraph/paragraph_element.py,sha256=mBYiRP-pqCQuDGr9hz1qpqXNeSwbE6uoAkjOaaCsbns,3228
|
59
|
+
notionary/blocks/paragraph/paragraph_markdown_node.py,sha256=-7e5hyGVaIU3G9nqyyqlANoGjRRZKZIWKGCIAExl6vs,665
|
60
|
+
notionary/blocks/paragraph/paragraph_models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
61
|
+
notionary/blocks/prompts/element_prompt_builder.py,sha256=rYMKPmpEFyk26JFZlwcTzMHATpvHnn4Dn284vewFog0,2953
|
62
|
+
notionary/blocks/prompts/element_prompt_content.py,sha256=ItnhGwKsHGnnY9E_LGgZZeTCT9ZfnkJY8xad4wFViWk,1567
|
63
|
+
notionary/blocks/quote/__init__.py,sha256=rZ8-t7a2TAN57flHXkaynodRat8vLZ07y2Rz3rpbur0,158
|
64
|
+
notionary/blocks/quote/quote_element.py,sha256=KuRi22nMC621JtYCCxItGJSTSkYrxZqaxUFXviX7xV4,3174
|
65
|
+
notionary/blocks/quote/quote_markdown_node.py,sha256=XNlo-8rm3s6k08dy4m-kQ7llo5jdm_EKSicN9xcK2Z0,636
|
66
|
+
notionary/blocks/quote/quote_models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
67
|
+
notionary/blocks/registry/block_registry.py,sha256=O0yo3B6QIZa-a6gClt_rzaxO_ijwsYc5clv2B0NLCQw,5366
|
68
|
+
notionary/blocks/registry/block_registry_builder.py,sha256=r7wVIjvfCRZWby9RabX9zBSeH_BuoqrRNCl-8yHwt5I,6551
|
69
|
+
notionary/blocks/shared/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
70
|
+
notionary/blocks/shared/block_client.py,sha256=EF2xYcrpJ2pF5LYSc9UNDw74Izf25gw5a05-P4CRmZE,8997
|
71
|
+
notionary/blocks/shared/models.py,sha256=lpLtDOLxpiEQzEYAroaLpCgjCn4XoInsVyJHK-bBcDE,18007
|
72
|
+
notionary/blocks/shared/notion_block_element.py,sha256=pKsGRPrSa_IqZHmer4HL5DCzFuhqo34vYXptXoXToX0,1443
|
73
|
+
notionary/blocks/shared/text_inline_formatter.py,sha256=mCqFS05oJwSU5fPoUUHVeud_hU8G4Z5mYFx7KeMY-s8,8564
|
74
|
+
notionary/blocks/shared/text_inline_formatter_new.py,sha256=nYmoFQVuAkfouCpGYULxFr4hHVCnRgvf3zxoiHBxIKg,4665
|
75
|
+
notionary/blocks/table/__init__.py,sha256=mul3r3dU5U9Z1hqa1QMlQc9aIwHM-9yKru9-RbLmWs8,158
|
76
|
+
notionary/blocks/table/table_element.py,sha256=oZV0p7gIbm7344SzSz-fKmQYmA5KS4-lcZiD8ZvxBH8,11479
|
77
|
+
notionary/blocks/table/table_markdown_node.py,sha256=pzdegpxB5bYRXsWQd7oUy-p2YjuEFdWd7NeHSd4PrRI,1398
|
78
|
+
notionary/blocks/table/table_models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
79
|
+
notionary/blocks/todo/__init__.py,sha256=4hbX7RIqbFn1H2Tz9mb2jkmSbav6AMdleTYKfVhGGIc,152
|
80
|
+
notionary/blocks/todo/todo_element.py,sha256=WFA9chSa9Nvh0MgMObeh4DXkjTBBGJpYmMFKjQikkhI,4075
|
81
|
+
notionary/blocks/todo/todo_markdown_node.py,sha256=X578oPFA_KBzqCeY5-Be3_5TZ45QEyWayzt0MitIli8,992
|
82
|
+
notionary/blocks/todo/todo_models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
83
|
+
notionary/blocks/toggle/__init__.py,sha256=N_-3QGKf4RPBmCF6GmYqbbmcY7K7KD10KpwsMLWAp1Y,206
|
84
|
+
notionary/blocks/toggle/toggle_element.py,sha256=Oj1Pmvdik7RmliME_maa0FfdoMM6Hvy5cS2aFyFQ114,11026
|
85
|
+
notionary/blocks/toggle/toggle_markdown_node.py,sha256=joEPiUQoC-D0fhypeJF3GaZHOYw4vuyry5OGSEZF4tY,1065
|
86
|
+
notionary/blocks/toggle/toggle_models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
87
|
+
notionary/blocks/toggleable_heading/__init__.py,sha256=rn-8AsL9Fp04k4dA7ugmhZ0RxLJ1vuqdCHAORcvt6Ns,243
|
88
|
+
notionary/blocks/toggleable_heading/toggleable_heading_element.py,sha256=_5Acptg4wFDhxSyMm3C0UJkSv8bssS0J7p_TmNfA6Pg,9909
|
89
|
+
notionary/blocks/toggleable_heading/toggleable_heading_markdown_node.py,sha256=KFX1Xba4zW60zQf6_AWZG0YPbERZq1f7CmTqQgGNnQo,1409
|
90
|
+
notionary/blocks/toggleable_heading/toggleable_heading_models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
91
|
+
notionary/blocks/video/__init__.py,sha256=kEhoKaHblyDyapIYj4DFhFlKm_0aQy3SCVyI5WmavJQ,158
|
92
|
+
notionary/blocks/video/video_element.py,sha256=fSPZ8yfFw6njFyZP0mGwxmHZXvM4m9Ayjb4ACc6MmhQ,6452
|
93
|
+
notionary/blocks/video/video_markdown_node.py,sha256=v4KgYJPLFy75a1d-ETya2JDf_JHy79QiQJNLw1l_jMU,903
|
94
|
+
notionary/database/__init__.py,sha256=4tdML0fBzkOCpiWT6q-L--5NELFLbTPD0IUA_E8yZno,155
|
95
|
+
notionary/database/client.py,sha256=ZcfydeYlpgGJt6wV1ib33KeXUiL-cGNJ1qraQZ4RVRc,4775
|
96
|
+
notionary/database/database.py,sha256=7KBe6DWbtsakPvjUO45eCphD2sq0ZKuYHY3kXJsk4P8,16582
|
97
|
+
notionary/database/database_filter_builder.py,sha256=PCnq3M9REt-NHRgBIfSrTCIPykUqBs5RqZK13WOAHKA,5950
|
98
|
+
notionary/database/database_provider.py,sha256=MveBSMkYG8nLUzKTS7KjbFVH8H-vLdH0t6yGArs-vPQ,8976
|
99
|
+
notionary/database/exceptions.py,sha256=jwFdxoIQHLO3mO3p5t890--1FjbTX60fNyqBAe-sszo,452
|
100
|
+
notionary/database/factory.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
101
|
+
notionary/database/models/page_result.py,sha256=Vmm5_oYpYAkIIJVoTd1ZZGloeC3cmFLMYP255mAmtaw,233
|
102
|
+
notionary/database/notion_database.py,sha256=wSqPfVtOnDL-aKRrE9BSMP1cpHe0_8RYyfCMxrlJSNo,16746
|
103
|
+
notionary/elements/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
104
|
+
notionary/file_upload/__init__.py,sha256=7TNyiIgLMD_IGRXTwRiAmStokF3rLoG4zXPwNb9KQqk,168
|
105
|
+
notionary/file_upload/client.py,sha256=qlxgu7_Ia0wbBflInoGki4mR8Po_RZgfLjO2wa279jY,8581
|
106
|
+
notionary/file_upload/models.py,sha256=0mYtuGkZ_eh_YmX0uxqye5vg3wWgqWuwOupAmLJXMUY,1625
|
107
|
+
notionary/file_upload/notion_file_upload.py,sha256=kUwFOoYclwbyesfPWPOJPbANFJORskzUvSgC8fsn8VM,13175
|
108
|
+
notionary/models/notion_block_response.py,sha256=gzL4C6K9QPcaMS6NbAZaRceSEnMbNwYBVVzxysza5VU,6002
|
109
|
+
notionary/models/notion_database_response.py,sha256=3kvADIP1dSxgITSK4n8Ex3QpF8n_Lxnu_IXbPVGcq4o,7648
|
110
|
+
notionary/models/notion_page_response.py,sha256=7ZwDYhlyK-avix_joQpGuNQZopjlQFI8jS3nvNNumoc,1544
|
111
|
+
notionary/models/search_response.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
112
|
+
notionary/page/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
113
|
+
notionary/page/client.py,sha256=XQ72lOEwn-gO8fmhKSKHqSHs3hRmoKH0TkJ3TtblcAg,4030
|
114
|
+
notionary/page/content/markdown_whitespace_processor.py,sha256=azsYau4eDrFN9CY7kzlG-ketoVKSkqSTc1bFq_i7ggQ,2942
|
115
|
+
notionary/page/content/notion_text_length_utils.py,sha256=RZqlcolvBBR1krlTMGS8q9xiZYYDGTyxZAjKhhONQyk,2757
|
116
|
+
notionary/page/content/page_content_retriever.py,sha256=NOJ4ubLgZJECtQYcactVkeB6eiIYRBTM1llk5fh_6uc,1901
|
117
|
+
notionary/page/content/page_content_writer.py,sha256=0evYwdR7dSWECer_nHGAQsXbbkcbpnGQuacNXp14nG8,5656
|
118
|
+
notionary/page/formatting/line_processor.py,sha256=zr1P2zG0lSGgBlP1KbFvcnazOUTHGnF_uQeFUtLakfw,5404
|
119
|
+
notionary/page/formatting/markdown_to_notion_converter.py,sha256=tbgaoEPJ96-JfCsyEsEK5-abdfmXapm9F2CAEX2rpig,6073
|
120
|
+
notionary/page/markdown_syntax_prompt_generator.py,sha256=uHCPNV9aQi3GzLVimyUKwza29hfxu6DTMVIa_QevJbk,4987
|
121
|
+
notionary/page/notion_page.py,sha256=5RbKxlA2RBoGiNXjO4bvgV9OMIIKwsTPbM3XolDOU2w,19026
|
122
|
+
notionary/page/notion_to_markdown_converter.py,sha256=3zvP1HSnUp3YlvK3PfIqh8GUi7xAuVWGQB0c38uK5VU,6117
|
123
|
+
notionary/page/properites/property_value_extractor.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
124
|
+
notionary/page/property_formatter.py,sha256=_978ViH83gfcr-XtDscWTfyBI2srGW2hzC-gzgp5NR8,3788
|
125
|
+
notionary/page/search_filter_builder.py,sha256=wZpW_KHmPXql3sNIyQd9EzZ2-ERy2i0vYNdoLkoBUfc,4597
|
126
|
+
notionary/page/utils.py,sha256=2nfBrWeczBdPH13R3q8dKP4OY4MwEdfKbcs2UJ9kg1o,2041
|
127
|
+
notionary/telemetry/__init__.py,sha256=Y7KyXeN4PiA6GtzV3NnwoH4hJnPwdjikWP22ckPYuHM,511
|
128
|
+
notionary/telemetry/service.py,sha256=DD7RbkSN0HWRK2YpOJTgFD7PeXGhSe9KrLkhiVIaC7Y,4763
|
129
|
+
notionary/telemetry/views.py,sha256=FgFZGYaxP7pRYx-9wg18skMh_MJAwf4W3rCfe9JOZe4,1796
|
130
|
+
notionary/user/__init__.py,sha256=D8r_WtQimdT-l3P1wd8O9Iki5JXF7jg2KV_hOgzWraw,281
|
131
|
+
notionary/user/base_notion_user.py,sha256=QB1701CfQTeu1ZNWOHYnGvTSHZuiritr6xYNMqyVg_U,1500
|
132
|
+
notionary/user/client.py,sha256=v8-lpyKzY_gSWPdWkBEjqxEPSg1WCy9AYSAJLXRrfKA,4563
|
133
|
+
notionary/user/models.py,sha256=3WPUysO96hMZUZYUWoCH5cdqNvnWgdiw5Qd7QKOv2UY,2063
|
134
|
+
notionary/user/notion_bot_user.py,sha256=cwrwmfst5RbAgppIjoFMJjExms1epfRM9VBd-S-3y5Q,7784
|
135
|
+
notionary/user/notion_user.py,sha256=l0GOMakk_xzsUUt7SsDJ5j-3dbtX64cUyyQPxn0r0Zc,8512
|
136
|
+
notionary/user/notion_user_manager.py,sha256=JQddAvbKJiLCLCn0mfxmvoi5uLW95vHhMWEYZD_F9zk,6339
|
137
|
+
notionary/user/notion_user_provider.py,sha256=7ImQ7T76g88W4YyHGOoO0aUJQfdGlhbh1fMT9PzR1mU,19
|
138
|
+
notionary/util/__init__.py,sha256=Bu2yGFd3xPasBrMRMk-6DcmMXfkdXn-KfFRETApBcP8,351
|
139
|
+
notionary/util/factory_decorator.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
140
|
+
notionary/util/factory_only.py,sha256=q-ZXUEvQ8lsuD1JQwx-ai6e9Lhie65waRE1BcRhCR_4,1235
|
141
|
+
notionary/util/fuzzy.py,sha256=lTlWuYEs0lhLa7QIRre3GVJ8-biIV_NmcJnMzBYFF5U,2061
|
142
|
+
notionary/util/logging_mixin.py,sha256=t08dx3nhSJq2-6_N8G39aydPEkQ76D4MlRfymxCsCVM,1690
|
143
|
+
notionary/util/page_id_utils.py,sha256=AA00kRO-g3Cc50tf_XW_tb5RBuPKLuBxRa0D8LYhLXg,736
|
144
|
+
notionary/util/singleton.py,sha256=CKAvykndwPRZsA3n3MAY_XdCR59MBjjKP0vtm2BcvF0,428
|
145
|
+
notionary/util/singleton_metaclass.py,sha256=uNeHiqS6TwhljvG1RE4NflIp2HyMuMmrCg2xI-vxmHE,809
|
146
|
+
notionary/workspace.py,sha256=hp5JPVT_aQsZNuxg2R-DiODobcGlVP4CusxNhzpnxKw,3813
|
147
|
+
notionary-0.2.19.dist-info/LICENSE,sha256=zOm3cRT1qD49eg7vgw95MI79rpUAZa1kRBFwL2FkAr8,1120
|
148
|
+
notionary-0.2.19.dist-info/METADATA,sha256=iKAerIgfYBeA0i8JunODWf3Wr54rsL9ZDmmJLLWy6Ms,6867
|
149
|
+
notionary-0.2.19.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
150
|
+
notionary-0.2.19.dist-info/RECORD,,
|
@@ -1,144 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
from typing import Dict, Any, Optional, List
|
3
|
-
import re
|
4
|
-
|
5
|
-
from notionary.blocks.notion_block_element import NotionBlockElement
|
6
|
-
from notionary.blocks import (
|
7
|
-
ElementPromptBuilder,
|
8
|
-
ElementPromptContent,
|
9
|
-
)
|
10
|
-
|
11
|
-
|
12
|
-
class AudioElement(NotionBlockElement):
|
13
|
-
"""
|
14
|
-
Handles conversion between Markdown audio embeds and Notion audio blocks.
|
15
|
-
|
16
|
-
Markdown audio syntax (custom format since standard Markdown doesn't support audio):
|
17
|
-
- $[Caption](https://example.com/audio.mp3) - Basic audio with caption
|
18
|
-
- $[](https://example.com/audio.mp3) - Audio without caption
|
19
|
-
- $[Caption](https://storage.googleapis.com/audio_summaries/example.mp3) - CDN hosted audio
|
20
|
-
|
21
|
-
Supports various audio URLs including direct audio file links from CDNs and other sources.
|
22
|
-
"""
|
23
|
-
|
24
|
-
PATTERN = re.compile(r"^\$\[(.*?)\]" + r'\((https?://[^\s"]+)' + r"\)$")
|
25
|
-
|
26
|
-
AUDIO_EXTENSIONS = [".mp3", ".wav", ".ogg", ".m4a", ".flac", ".aac"]
|
27
|
-
|
28
|
-
@classmethod
|
29
|
-
def match_markdown(cls, text: str) -> bool:
|
30
|
-
"""Check if text is a markdown audio embed."""
|
31
|
-
text = text.strip()
|
32
|
-
return text.startswith("$[") and bool(cls.PATTERN.match(text))
|
33
|
-
|
34
|
-
@classmethod
|
35
|
-
def match_notion(cls, block: Dict[str, Any]) -> bool:
|
36
|
-
"""Check if block is a Notion audio."""
|
37
|
-
return block.get("type") == "audio"
|
38
|
-
|
39
|
-
@classmethod
|
40
|
-
def is_audio_url(cls, url: str) -> bool:
|
41
|
-
"""Check if URL points to an audio file."""
|
42
|
-
return (
|
43
|
-
any(url.lower().endswith(ext) for ext in cls.AUDIO_EXTENSIONS)
|
44
|
-
or "audio" in url.lower()
|
45
|
-
or "storage.googleapis.com/audio_summaries" in url.lower()
|
46
|
-
)
|
47
|
-
|
48
|
-
@classmethod
|
49
|
-
def markdown_to_notion(cls, text: str) -> Optional[Dict[str, Any]]:
|
50
|
-
"""Convert markdown audio embed to Notion audio block."""
|
51
|
-
audio_match = cls.PATTERN.match(text.strip())
|
52
|
-
if not audio_match:
|
53
|
-
return None
|
54
|
-
|
55
|
-
caption = audio_match.group(1)
|
56
|
-
url = audio_match.group(2)
|
57
|
-
|
58
|
-
if not url:
|
59
|
-
return None
|
60
|
-
|
61
|
-
# Make sure this is an audio URL
|
62
|
-
if not cls.is_audio_url(url):
|
63
|
-
# If not obviously an audio URL, we'll still accept it as the user might know better
|
64
|
-
pass
|
65
|
-
|
66
|
-
# Prepare the audio block
|
67
|
-
audio_block = {
|
68
|
-
"type": "audio",
|
69
|
-
"audio": {"type": "external", "external": {"url": url}},
|
70
|
-
}
|
71
|
-
|
72
|
-
# Add caption if provided
|
73
|
-
if caption:
|
74
|
-
audio_block["audio"]["caption"] = [
|
75
|
-
{"type": "text", "text": {"content": caption}}
|
76
|
-
]
|
77
|
-
|
78
|
-
return audio_block
|
79
|
-
|
80
|
-
@classmethod
|
81
|
-
def notion_to_markdown(cls, block: Dict[str, Any]) -> Optional[str]:
|
82
|
-
"""Convert Notion audio block to markdown audio embed."""
|
83
|
-
if block.get("type") != "audio":
|
84
|
-
return None
|
85
|
-
|
86
|
-
audio_data = block.get("audio", {})
|
87
|
-
|
88
|
-
# Handle both external and file (uploaded) audios
|
89
|
-
if audio_data.get("type") == "external":
|
90
|
-
url = audio_data.get("external", {}).get("url", "")
|
91
|
-
elif audio_data.get("type") == "file":
|
92
|
-
url = audio_data.get("file", {}).get("url", "")
|
93
|
-
else:
|
94
|
-
return None
|
95
|
-
|
96
|
-
if not url:
|
97
|
-
return None
|
98
|
-
|
99
|
-
# Extract caption if available
|
100
|
-
caption = ""
|
101
|
-
caption_rich_text = audio_data.get("caption", [])
|
102
|
-
if caption_rich_text:
|
103
|
-
caption = cls._extract_text_content(caption_rich_text)
|
104
|
-
|
105
|
-
return f"$[{caption}]({url})"
|
106
|
-
|
107
|
-
@classmethod
|
108
|
-
def is_multiline(cls) -> bool:
|
109
|
-
"""Audio embeds are single-line elements."""
|
110
|
-
return False
|
111
|
-
|
112
|
-
@classmethod
|
113
|
-
def _extract_text_content(cls, rich_text: List[Dict[str, Any]]) -> str:
|
114
|
-
"""Extract plain text content from Notion rich_text elements."""
|
115
|
-
result = ""
|
116
|
-
for text_obj in rich_text:
|
117
|
-
if text_obj.get("type") == "text":
|
118
|
-
result += text_obj.get("text", {}).get("content", "")
|
119
|
-
elif "plain_text" in text_obj:
|
120
|
-
result += text_obj.get("plain_text", "")
|
121
|
-
return result
|
122
|
-
|
123
|
-
@classmethod
|
124
|
-
def get_llm_prompt_content(cls) -> ElementPromptContent:
|
125
|
-
"""Returns information for LLM prompts about this element."""
|
126
|
-
return (
|
127
|
-
ElementPromptBuilder()
|
128
|
-
.with_description(
|
129
|
-
"Embeds audio content from external sources like CDNs or direct audio URLs."
|
130
|
-
)
|
131
|
-
.with_syntax("$[Caption](https://example.com/audio.mp3)")
|
132
|
-
.with_examples(
|
133
|
-
[
|
134
|
-
"$[Podcast Episode](https://storage.googleapis.com/audio_summaries/ep_ai_summary_127d02ec-ca12-4312-a5ed-cb14b185480c.mp3)",
|
135
|
-
"$[Voice recording](https://example.com/audio/recording.mp3)",
|
136
|
-
"$[](https://storage.googleapis.com/audio_summaries/example.mp3)",
|
137
|
-
]
|
138
|
-
)
|
139
|
-
.with_usage_guidelines(
|
140
|
-
"Use audio embeds when you want to include audio content directly in your document. "
|
141
|
-
"Audio embeds are useful for podcasts, music, voice recordings, or any content that benefits from audio explanation."
|
142
|
-
)
|
143
|
-
.build()
|
144
|
-
)
|
@@ -1,122 +0,0 @@
|
|
1
|
-
import re
|
2
|
-
from typing import Dict, Any, Optional
|
3
|
-
|
4
|
-
from notionary.blocks import ElementPromptContent, ElementPromptBuilder
|
5
|
-
from notionary.blocks.text_inline_formatter import TextInlineFormatter
|
6
|
-
from notionary.blocks.notion_block_element import NotionBlockElement
|
7
|
-
|
8
|
-
|
9
|
-
class CalloutElement(NotionBlockElement):
|
10
|
-
"""
|
11
|
-
Handles conversion between Markdown callouts and Notion callout blocks.
|
12
|
-
|
13
|
-
Markdown callout syntax:
|
14
|
-
- !> [emoji] Text - Callout with custom emoji
|
15
|
-
- !> Text - Simple callout with default emoji
|
16
|
-
|
17
|
-
Where:
|
18
|
-
- [emoji] is any emoji character
|
19
|
-
- Text is the callout content with optional inline formatting
|
20
|
-
"""
|
21
|
-
|
22
|
-
EMOJI_PATTERN = r"(?:\[([^\]]+)\])?\s*"
|
23
|
-
TEXT_PATTERN = r"(.+)"
|
24
|
-
|
25
|
-
PATTERN = re.compile(r"^!>\s+" + EMOJI_PATTERN + TEXT_PATTERN + r"$")
|
26
|
-
|
27
|
-
DEFAULT_EMOJI = "💡"
|
28
|
-
DEFAULT_COLOR = "gray_background"
|
29
|
-
|
30
|
-
@classmethod
|
31
|
-
def match_markdown(cls, text: str) -> bool:
|
32
|
-
"""Check if text is a markdown callout."""
|
33
|
-
return text.strip().startswith("!>") and bool(
|
34
|
-
CalloutElement.PATTERN.match(text)
|
35
|
-
)
|
36
|
-
|
37
|
-
@classmethod
|
38
|
-
def match_notion(cls, block: Dict[str, Any]) -> bool:
|
39
|
-
"""Check if block is a Notion callout."""
|
40
|
-
return block.get("type") == "callout"
|
41
|
-
|
42
|
-
@classmethod
|
43
|
-
def markdown_to_notion(cls, text: str) -> Optional[Dict[str, Any]]:
|
44
|
-
"""Convert markdown callout to Notion callout block."""
|
45
|
-
callout_match = CalloutElement.PATTERN.match(text)
|
46
|
-
if not callout_match:
|
47
|
-
return None
|
48
|
-
|
49
|
-
emoji = callout_match.group(1)
|
50
|
-
content = callout_match.group(2)
|
51
|
-
|
52
|
-
if not emoji:
|
53
|
-
emoji = CalloutElement.DEFAULT_EMOJI
|
54
|
-
|
55
|
-
return {
|
56
|
-
"type": "callout",
|
57
|
-
"callout": {
|
58
|
-
"rich_text": TextInlineFormatter.parse_inline_formatting(content),
|
59
|
-
"icon": {"type": "emoji", "emoji": emoji},
|
60
|
-
"color": CalloutElement.DEFAULT_COLOR,
|
61
|
-
},
|
62
|
-
}
|
63
|
-
|
64
|
-
@classmethod
|
65
|
-
def notion_to_markdown(cls, block: Dict[str, Any]) -> Optional[str]:
|
66
|
-
"""Convert Notion callout block to markdown callout."""
|
67
|
-
if block.get("type") != "callout":
|
68
|
-
return None
|
69
|
-
|
70
|
-
callout_data = block.get("callout", {})
|
71
|
-
rich_text = callout_data.get("rich_text", [])
|
72
|
-
icon = callout_data.get("icon", {})
|
73
|
-
|
74
|
-
text = TextInlineFormatter.extract_text_with_formatting(rich_text)
|
75
|
-
if not text:
|
76
|
-
return None
|
77
|
-
|
78
|
-
emoji = ""
|
79
|
-
if icon and icon.get("type") == "emoji":
|
80
|
-
emoji = icon.get("emoji", "")
|
81
|
-
|
82
|
-
emoji_str = ""
|
83
|
-
if emoji and emoji != CalloutElement.DEFAULT_EMOJI:
|
84
|
-
emoji_str = f"[{emoji}] "
|
85
|
-
|
86
|
-
return f"!> {emoji_str}{text}"
|
87
|
-
|
88
|
-
@classmethod
|
89
|
-
def is_multiline(cls) -> bool:
|
90
|
-
return False
|
91
|
-
|
92
|
-
@classmethod
|
93
|
-
def get_llm_prompt_content(cls) -> ElementPromptContent:
|
94
|
-
"""
|
95
|
-
Returns structured LLM prompt metadata for the callout element.
|
96
|
-
Includes description, usage guidance, syntax options, and examples.
|
97
|
-
"""
|
98
|
-
return (
|
99
|
-
ElementPromptBuilder()
|
100
|
-
.with_description(
|
101
|
-
"Creates a callout block to highlight important information with an icon."
|
102
|
-
)
|
103
|
-
.with_usage_guidelines(
|
104
|
-
"Use callouts when you want to draw attention to important information, "
|
105
|
-
"tips, warnings, or notes that stand out from the main content. "
|
106
|
-
"The emoji MUST be enclosed in square brackets to properly display."
|
107
|
-
)
|
108
|
-
.with_syntax("!> [emoji] Text")
|
109
|
-
.with_examples(
|
110
|
-
[
|
111
|
-
"!> [💡] This is a default callout with the light bulb emoji",
|
112
|
-
"!> [🔔] This is a callout with a bell emoji",
|
113
|
-
"!> [⚠️] Warning: This is an important note to pay attention to",
|
114
|
-
"!> [💡] Tip: Add emoji that matches your content's purpose",
|
115
|
-
]
|
116
|
-
)
|
117
|
-
.with_avoidance_guidelines(
|
118
|
-
"NEVER omit the square brackets around the emoji. The format MUST be !> [emoji] and not !> emoji. "
|
119
|
-
"Without the square brackets, Notion will not properly render the callout with the specified emoji."
|
120
|
-
)
|
121
|
-
.build()
|
122
|
-
)
|