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
@@ -2,7 +2,10 @@ import re
|
|
2
2
|
from typing import Dict, Any, Optional, List, Tuple
|
3
3
|
from notionary.elements.notion_block_element import NotionBlockElement
|
4
4
|
from notionary.elements.text_inline_formatter import TextInlineFormatter
|
5
|
-
from notionary.elements.prompts.element_prompt_content import
|
5
|
+
from notionary.elements.prompts.element_prompt_content import (
|
6
|
+
ElementPromptBuilder,
|
7
|
+
ElementPromptContent,
|
8
|
+
)
|
6
9
|
|
7
10
|
|
8
11
|
class TableElement(NotionBlockElement):
|
@@ -21,8 +24,8 @@ class TableElement(NotionBlockElement):
|
|
21
24
|
ROW_PATTERN = re.compile(r"^\s*\|(.+)\|\s*$")
|
22
25
|
SEPARATOR_PATTERN = re.compile(r"^\s*\|([\s\-:|]+)\|\s*$")
|
23
26
|
|
24
|
-
@
|
25
|
-
def match_markdown(text: str) -> bool:
|
27
|
+
@classmethod
|
28
|
+
def match_markdown(cls, text: str) -> bool:
|
26
29
|
"""Check if text contains a markdown table."""
|
27
30
|
lines = text.split("\n")
|
28
31
|
|
@@ -39,13 +42,13 @@ class TableElement(NotionBlockElement):
|
|
39
42
|
|
40
43
|
return False
|
41
44
|
|
42
|
-
@
|
43
|
-
def match_notion(block: Dict[str, Any]) -> bool:
|
45
|
+
@classmethod
|
46
|
+
def match_notion(cls, block: Dict[str, Any]) -> bool:
|
44
47
|
"""Check if block is a Notion table."""
|
45
48
|
return block.get("type") == "table"
|
46
49
|
|
47
|
-
@
|
48
|
-
def markdown_to_notion(text: str) -> Optional[Dict[str, Any]]:
|
50
|
+
@classmethod
|
51
|
+
def markdown_to_notion(cls, text: str) -> Optional[Dict[str, Any]]:
|
49
52
|
"""Convert markdown table to Notion table block."""
|
50
53
|
if not TableElement.match_markdown(text):
|
51
54
|
return None
|
@@ -76,8 +79,8 @@ class TableElement(NotionBlockElement):
|
|
76
79
|
},
|
77
80
|
}
|
78
81
|
|
79
|
-
@
|
80
|
-
def notion_to_markdown(block: Dict[str, Any]) -> Optional[str]:
|
82
|
+
@classmethod
|
83
|
+
def notion_to_markdown(cls, block: Dict[str, Any]) -> Optional[str]:
|
81
84
|
"""Convert Notion table block to markdown table."""
|
82
85
|
if block.get("type") != "table":
|
83
86
|
return None
|
@@ -138,13 +141,13 @@ class TableElement(NotionBlockElement):
|
|
138
141
|
|
139
142
|
return "\n".join(table_rows)
|
140
143
|
|
141
|
-
@
|
142
|
-
def is_multiline() -> bool:
|
144
|
+
@classmethod
|
145
|
+
def is_multiline(cls) -> bool:
|
143
146
|
"""Indicates if this element handles content that spans multiple lines."""
|
144
147
|
return True
|
145
148
|
|
146
|
-
@
|
147
|
-
def _find_table_start(lines: List[str]) -> Optional[int]:
|
149
|
+
@classmethod
|
150
|
+
def _find_table_start(cls, lines: List[str]) -> Optional[int]:
|
148
151
|
"""Find the start index of a table in the lines."""
|
149
152
|
for i in range(len(lines) - 2):
|
150
153
|
if (
|
@@ -155,16 +158,16 @@ class TableElement(NotionBlockElement):
|
|
155
158
|
return i
|
156
159
|
return None
|
157
160
|
|
158
|
-
@
|
159
|
-
def _find_table_end(lines: List[str], start_idx: int) -> int:
|
161
|
+
@classmethod
|
162
|
+
def _find_table_end(cls, lines: List[str], start_idx: int) -> int:
|
160
163
|
"""Find the end index of a table, starting from start_idx."""
|
161
164
|
end_idx = start_idx + 3 # Minimum: Header, Separator, one data row
|
162
165
|
while end_idx < len(lines) and TableElement.ROW_PATTERN.match(lines[end_idx]):
|
163
166
|
end_idx += 1
|
164
167
|
return end_idx
|
165
168
|
|
166
|
-
@
|
167
|
-
def _extract_table_rows(table_lines: List[str]) -> List[List[str]]:
|
169
|
+
@classmethod
|
170
|
+
def _extract_table_rows(cls, table_lines: List[str]) -> List[List[str]]:
|
168
171
|
"""Extract row contents from table lines, excluding separator line."""
|
169
172
|
rows = []
|
170
173
|
for i, line in enumerate(table_lines):
|
@@ -174,8 +177,8 @@ class TableElement(NotionBlockElement):
|
|
174
177
|
rows.append(cells)
|
175
178
|
return rows
|
176
179
|
|
177
|
-
@
|
178
|
-
def _normalize_row_lengths(rows: List[List[str]], column_count: int) -> None:
|
180
|
+
@classmethod
|
181
|
+
def _normalize_row_lengths(cls, rows: List[List[str]], column_count: int) -> None:
|
179
182
|
"""Normalize row lengths to the specified column count."""
|
180
183
|
for row in rows:
|
181
184
|
if len(row) < column_count:
|
@@ -183,8 +186,8 @@ class TableElement(NotionBlockElement):
|
|
183
186
|
elif len(row) > column_count:
|
184
187
|
del row[column_count:]
|
185
188
|
|
186
|
-
@
|
187
|
-
def _parse_table_row(row_text: str) -> List[str]:
|
189
|
+
@classmethod
|
190
|
+
def _parse_table_row(cls, row_text: str) -> List[str]:
|
188
191
|
"""Convert table row text to cell contents."""
|
189
192
|
row_content = row_text.strip()
|
190
193
|
|
@@ -195,8 +198,8 @@ class TableElement(NotionBlockElement):
|
|
195
198
|
|
196
199
|
return [cell.strip() for cell in row_content.split("|")]
|
197
200
|
|
198
|
-
@
|
199
|
-
def _create_table_rows(rows: List[List[str]]) -> List[Dict[str, Any]]:
|
201
|
+
@classmethod
|
202
|
+
def _create_table_rows(cls, rows: List[List[str]]) -> List[Dict[str, Any]]:
|
200
203
|
"""Create Notion table rows from cell contents."""
|
201
204
|
table_rows = []
|
202
205
|
|
@@ -230,8 +233,8 @@ class TableElement(NotionBlockElement):
|
|
230
233
|
|
231
234
|
return table_rows
|
232
235
|
|
233
|
-
@
|
234
|
-
def find_matches(text: str) -> List[Tuple[int, int, Dict[str, Any]]]:
|
236
|
+
@classmethod
|
237
|
+
def find_matches(cls, text: str) -> List[Tuple[int, int, Dict[str, Any]]]:
|
235
238
|
"""
|
236
239
|
Find all tables in the text and return their positions.
|
237
240
|
|
@@ -272,8 +275,8 @@ class TableElement(NotionBlockElement):
|
|
272
275
|
|
273
276
|
return matches
|
274
277
|
|
275
|
-
@
|
276
|
-
def _calculate_position(lines: List[str], start: int, end: int) -> int:
|
278
|
+
@classmethod
|
279
|
+
def _calculate_position(cls, lines: List[str], start: int, end: int) -> int:
|
277
280
|
"""Calculate the text position in characters from line start to end."""
|
278
281
|
position = 0
|
279
282
|
for i in range(start, end):
|
@@ -283,12 +286,22 @@ class TableElement(NotionBlockElement):
|
|
283
286
|
@classmethod
|
284
287
|
def get_llm_prompt_content(cls) -> ElementPromptContent:
|
285
288
|
"""Returns information for LLM prompts about this element."""
|
286
|
-
return
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
"
|
293
|
-
|
294
|
-
|
289
|
+
return (
|
290
|
+
ElementPromptBuilder()
|
291
|
+
.with_description(
|
292
|
+
"Creates formatted tables with rows and columns for structured data."
|
293
|
+
)
|
294
|
+
.with_usage_guidelines(
|
295
|
+
"Use tables to organize and present structured data in a grid format, making information easier to compare and analyze. Tables are ideal for data sets, comparison charts, pricing information, or any content that benefits from columnar organization."
|
296
|
+
)
|
297
|
+
.with_syntax(
|
298
|
+
"| Header 1 | Header 2 | Header 3 |\n| -------- | -------- | -------- |\n| Cell 1 | Cell 2 | Cell 3 |"
|
299
|
+
)
|
300
|
+
.with_examples(
|
301
|
+
[
|
302
|
+
"| Product | Price | Stock |\n| ------- | ----- | ----- |\n| Widget A | $10.99 | 42 |\n| Widget B | $14.99 | 27 |",
|
303
|
+
"| Name | Role | Department |\n| ---- | ---- | ---------- |\n| John Smith | Manager | Marketing |\n| Jane Doe | Director | Sales |",
|
304
|
+
]
|
305
|
+
)
|
306
|
+
.build()
|
307
|
+
)
|
@@ -1,7 +1,10 @@
|
|
1
1
|
from typing import Dict, Any, List, Tuple
|
2
2
|
import re
|
3
3
|
|
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 TextInlineFormatter:
|
@@ -15,7 +18,6 @@ class TextInlineFormatter:
|
|
15
18
|
- Strikethrough: ~~text~~
|
16
19
|
- Code: `text`
|
17
20
|
- Links: [text](url)
|
18
|
-
- Highlights: ==text== (default yellow) or ==color:text== (custom color)
|
19
21
|
"""
|
20
22
|
|
21
23
|
# Format patterns for matching Markdown formatting
|
@@ -214,18 +216,24 @@ class TextInlineFormatter:
|
|
214
216
|
"""
|
215
217
|
Returns structured LLM prompt metadata for inline formatting.
|
216
218
|
"""
|
217
|
-
return
|
218
|
-
|
219
|
-
|
219
|
+
return (
|
220
|
+
ElementPromptBuilder()
|
221
|
+
.with_description(
|
222
|
+
"Enables inline formatting like bold, italics, strikethrough, code, links, and underlining for enhanced readability and emphasis."
|
223
|
+
)
|
224
|
+
.with_usage_guidelines(
|
220
225
|
"Use inline formatting to highlight important words, provide emphasis, show code or paths, or add hyperlinks. "
|
221
226
|
"Helps create a visual hierarchy and improves scanability of long texts."
|
222
|
-
)
|
223
|
-
"
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
227
|
+
)
|
228
|
+
.with_syntax("**bold**, *italic*, `code`, [text](url)")
|
229
|
+
.with_examples(
|
230
|
+
[
|
231
|
+
"This is a **bold** word.",
|
232
|
+
"Use *italics* for emphasis.",
|
233
|
+
"Mark outdated content like ~~this~~.",
|
234
|
+
"Write `config.json` to reference a file.",
|
235
|
+
"Visit [Notion](https://notion.so) for more info.",
|
236
|
+
]
|
237
|
+
)
|
238
|
+
.build()
|
239
|
+
)
|
@@ -1,7 +1,10 @@
|
|
1
1
|
import re
|
2
2
|
from typing import Dict, Any, Optional
|
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
|
from notionary.elements.text_inline_formatter import TextInlineFormatter
|
6
9
|
|
7
10
|
|
@@ -20,20 +23,20 @@ class TodoElement(NotionBlockElement):
|
|
20
23
|
TODO_PATTERN = re.compile(r"^\s*[-*+]\s+\[\s?\]\s+(.+)$")
|
21
24
|
DONE_PATTERN = re.compile(r"^\s*[-*+]\s+\[x\]\s+(.+)$")
|
22
25
|
|
23
|
-
@
|
24
|
-
def match_markdown(text: str) -> bool:
|
26
|
+
@classmethod
|
27
|
+
def match_markdown(cls, text: str) -> bool:
|
25
28
|
"""Check if text is a markdown todo item."""
|
26
29
|
return bool(
|
27
30
|
TodoElement.TODO_PATTERN.match(text) or TodoElement.DONE_PATTERN.match(text)
|
28
31
|
)
|
29
32
|
|
30
|
-
@
|
31
|
-
def match_notion(block: Dict[str, Any]) -> bool:
|
33
|
+
@classmethod
|
34
|
+
def match_notion(cls, block: Dict[str, Any]) -> bool:
|
32
35
|
"""Check if block is a Notion to_do block."""
|
33
36
|
return block.get("type") == "to_do"
|
34
37
|
|
35
|
-
@
|
36
|
-
def markdown_to_notion(text: str) -> Optional[Dict[str, Any]]:
|
38
|
+
@classmethod
|
39
|
+
def markdown_to_notion(cls, text: str) -> Optional[Dict[str, Any]]:
|
37
40
|
"""Convert markdown todo item to Notion to_do block."""
|
38
41
|
done_match = TodoElement.DONE_PATTERN.match(text)
|
39
42
|
if done_match:
|
@@ -47,8 +50,8 @@ class TodoElement(NotionBlockElement):
|
|
47
50
|
|
48
51
|
return None
|
49
52
|
|
50
|
-
@
|
51
|
-
def notion_to_markdown(block: Dict[str, Any]) -> Optional[str]:
|
53
|
+
@classmethod
|
54
|
+
def notion_to_markdown(cls, block: Dict[str, Any]) -> Optional[str]:
|
52
55
|
"""Convert Notion to_do block to markdown todo item."""
|
53
56
|
if block.get("type") != "to_do":
|
54
57
|
return None
|
@@ -64,8 +67,8 @@ class TodoElement(NotionBlockElement):
|
|
64
67
|
checkbox = "[x]" if checked else "[ ]"
|
65
68
|
return f"- {checkbox} {content}"
|
66
69
|
|
67
|
-
@
|
68
|
-
def _create_todo_block(content: str, checked: bool) -> Dict[str, Any]:
|
70
|
+
@classmethod
|
71
|
+
def _create_todo_block(cls, content: str, checked: bool) -> Dict[str, Any]:
|
69
72
|
"""
|
70
73
|
Create a Notion to_do block.
|
71
74
|
|
@@ -85,8 +88,8 @@ class TodoElement(NotionBlockElement):
|
|
85
88
|
},
|
86
89
|
}
|
87
90
|
|
88
|
-
@
|
89
|
-
def is_multiline() -> bool:
|
91
|
+
@classmethod
|
92
|
+
def is_multiline(cls) -> bool:
|
90
93
|
return False
|
91
94
|
|
92
95
|
@classmethod
|
@@ -94,17 +97,23 @@ class TodoElement(NotionBlockElement):
|
|
94
97
|
"""
|
95
98
|
Returns structured LLM prompt metadata for the todo element.
|
96
99
|
"""
|
97
|
-
return
|
98
|
-
|
99
|
-
|
100
|
+
return (
|
101
|
+
ElementPromptBuilder()
|
102
|
+
.with_description(
|
103
|
+
"Creates interactive to-do items with checkboxes that can be marked as complete."
|
104
|
+
)
|
105
|
+
.with_usage_guidelines(
|
100
106
|
"Use to-do items for task lists, checklists, or tracking progress on items that need to be completed. "
|
101
107
|
"Todo items are interactive in Notion and can be checked/unchecked directly."
|
102
|
-
)
|
103
|
-
"
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
108
|
+
)
|
109
|
+
.with_syntax("- [ ] Task to complete")
|
110
|
+
.with_examples(
|
111
|
+
[
|
112
|
+
"- [ ] Draft project proposal",
|
113
|
+
"- [x] Create initial timeline",
|
114
|
+
"* [ ] Review code changes",
|
115
|
+
"+ [x] Finalize handoff checklist",
|
116
|
+
]
|
117
|
+
)
|
118
|
+
.build()
|
119
|
+
)
|