notionary 0.1.19__py3-none-any.whl → 0.1.21__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 (42) hide show
  1. notionary/__init__.py +2 -2
  2. notionary/database/notion_database.py +3 -1
  3. notionary/elements/audio_element.py +7 -11
  4. notionary/elements/bookmark_element.py +17 -29
  5. notionary/elements/bulleted_list_element.py +69 -0
  6. notionary/elements/callout_element.py +18 -80
  7. notionary/elements/code_block_element.py +15 -10
  8. notionary/elements/column_element.py +39 -26
  9. notionary/elements/divider_element.py +8 -25
  10. notionary/elements/embed_element.py +10 -18
  11. notionary/elements/heading_element.py +10 -12
  12. notionary/elements/image_element.py +9 -15
  13. notionary/elements/mention_element.py +6 -15
  14. notionary/elements/notion_block_element.py +12 -11
  15. notionary/elements/numbered_list_element.py +68 -0
  16. notionary/elements/paragraph_element.py +11 -7
  17. notionary/elements/prompts/element_prompt_content.py +20 -0
  18. notionary/elements/prompts/synthax_prompt_builder.py +92 -0
  19. notionary/elements/qoute_element.py +20 -89
  20. notionary/elements/registry/block_element_registry.py +90 -0
  21. notionary/elements/{block_element_registry_builder.py → registry/block_element_registry_builder.py} +15 -124
  22. notionary/elements/table_element.py +4 -16
  23. notionary/elements/text_inline_formatter.py +15 -78
  24. notionary/elements/todo_lists.py +14 -18
  25. notionary/elements/toggle_element.py +19 -1
  26. notionary/elements/video_element.py +10 -19
  27. notionary/notion_client.py +2 -2
  28. notionary/page/content/page_content_manager.py +2 -3
  29. notionary/page/markdown_to_notion_converter.py +3 -3
  30. notionary/page/notion_page.py +3 -3
  31. notionary/page/notion_to_markdown_converter.py +3 -3
  32. notionary/page/relations/notion_page_relation_manager.py +24 -24
  33. notionary/page/relations/notion_page_title_resolver.py +1 -2
  34. {notionary-0.1.19.dist-info → notionary-0.1.21.dist-info}/METADATA +3 -3
  35. notionary-0.1.21.dist-info/RECORD +58 -0
  36. {notionary-0.1.19.dist-info → notionary-0.1.21.dist-info}/WHEEL +1 -1
  37. notionary/elements/block_element_registry.py +0 -233
  38. notionary/elements/list_element.py +0 -130
  39. notionary/util/singleton_decorator.py +0 -20
  40. notionary-0.1.19.dist-info/RECORD +0 -56
  41. {notionary-0.1.19.dist-info → notionary-0.1.21.dist-info}/licenses/LICENSE +0 -0
  42. {notionary-0.1.19.dist-info → notionary-0.1.21.dist-info}/top_level.txt +0 -0
@@ -1,28 +1,11 @@
1
1
  import re
2
2
  from typing import Dict, Any, Optional, List, Tuple
3
- from typing_extensions import override
4
-
5
3
  from notionary.elements.notion_block_element import NotionBlockElement
4
+ from notionary.elements.prompts.element_prompt_content import ElementPromptContent
6
5
 
7
6
 
8
7
  class QuoteElement(NotionBlockElement):
9
- """Class for converting between Markdown blockquotes and Notion quote blocks with background color support."""
10
-
11
- # Mapping von Markdown-Farbnamen zu Notion-Farbnamen
12
- COLOR_MAPPING = {
13
- "gray": "gray_background",
14
- "brown": "brown_background",
15
- "orange": "orange_background",
16
- "yellow": "yellow_background",
17
- "green": "green_background",
18
- "blue": "blue_background",
19
- "purple": "purple_background",
20
- "pink": "pink_background",
21
- "red": "red_background",
22
- }
23
-
24
- # Umgekehrtes Mapping für die Rückkonvertierung
25
- REVERSE_COLOR_MAPPING = {v: k for k, v in COLOR_MAPPING.items()}
8
+ """Class for converting between Markdown blockquotes and Notion quote blocks."""
26
9
 
27
10
  @staticmethod
28
11
  def find_matches(text: str) -> List[Tuple[int, int, Dict[str, Any]]]:
@@ -87,10 +70,9 @@ class QuoteElement(NotionBlockElement):
87
70
 
88
71
  return matches
89
72
 
90
- @override
91
73
  @staticmethod
92
74
  def markdown_to_notion(text: str) -> Optional[Dict[str, Any]]:
93
- """Convert markdown blockquote to Notion block with background color support."""
75
+ """Convert markdown blockquote to Notion block."""
94
76
  if not text:
95
77
  return None
96
78
 
@@ -103,40 +85,12 @@ class QuoteElement(NotionBlockElement):
103
85
  # Extract quote content
104
86
  lines = text.split("\n")
105
87
  quote_lines = []
106
- color = "default" # Standardfarbe
107
88
 
108
- # Überprüfen, ob der erste Nicht-Leerzeichen-Inhalt eine Farbangabe ist
109
- first_line = None
110
- for line in lines:
111
- quote_match = quote_pattern.match(line)
112
- if quote_match and quote_match.group(1).strip():
113
- first_line = quote_match.group(1).strip()
114
- break
115
-
116
- # Farbangabe in eckigen Klammern prüfen
117
- if first_line:
118
- color_match = re.match(r"^\[background:(\w+)\]\s*(.*)", first_line)
119
- if color_match:
120
- potential_color = color_match.group(1).lower()
121
- if potential_color in QuoteElement.COLOR_MAPPING:
122
- color = QuoteElement.COLOR_MAPPING[potential_color]
123
- # Erste Zeile ohne Farbangabe neu hinzufügen
124
- first_line = color_match.group(2)
125
-
126
- # Inhalte extrahieren
127
- processing_first_color_line = True
89
+ # Extract content from each line
128
90
  for line in lines:
129
91
  quote_match = quote_pattern.match(line)
130
92
  if quote_match:
131
93
  content = quote_match.group(1)
132
- # Farbangabe in der ersten Zeile entfernen
133
- if (
134
- processing_first_color_line
135
- and content.strip()
136
- and re.match(r"^\[background:(\w+)\]", content.strip())
137
- ):
138
- content = re.sub(r"^\[background:(\w+)\]\s*", "", content)
139
- processing_first_color_line = False
140
94
  quote_lines.append(content)
141
95
  elif not line.strip() and quote_lines:
142
96
  # Allow empty lines within the quote
@@ -147,20 +101,17 @@ class QuoteElement(NotionBlockElement):
147
101
 
148
102
  quote_content = "\n".join(quote_lines).strip()
149
103
 
150
- # Create rich_text elements directly
151
104
  rich_text = [{"type": "text", "text": {"content": quote_content}}]
152
105
 
153
- return {"type": "quote", "quote": {"rich_text": rich_text, "color": color}}
106
+ return {"type": "quote", "quote": {"rich_text": rich_text, "color": "default"}}
154
107
 
155
- @override
156
108
  @staticmethod
157
109
  def notion_to_markdown(block: Dict[str, Any]) -> Optional[str]:
158
- """Convert Notion quote block to markdown with background color support."""
110
+ """Convert Notion quote block to markdown."""
159
111
  if block.get("type") != "quote":
160
112
  return None
161
113
 
162
114
  rich_text = block.get("quote", {}).get("rich_text", [])
163
- color = block.get("quote", {}).get("color", "default")
164
115
 
165
116
  # Extract the text content
166
117
  content = QuoteElement._extract_text_content(rich_text)
@@ -169,33 +120,23 @@ class QuoteElement(NotionBlockElement):
169
120
  lines = content.split("\n")
170
121
  formatted_lines = []
171
122
 
172
- # Füge die Farbinformation zur ersten Zeile hinzu, falls nicht default
173
- if color != "default" and color in QuoteElement.REVERSE_COLOR_MAPPING:
174
- markdown_color = QuoteElement.REVERSE_COLOR_MAPPING.get(color)
175
- first_line = lines[0] if lines else ""
176
- formatted_lines.append(f"> [background:{markdown_color}] {first_line}")
177
- lines = lines[1:] if len(lines) > 1 else []
178
-
179
- # Füge die restlichen Zeilen hinzu
123
+ # Add each line with blockquote prefix
180
124
  for line in lines:
181
125
  formatted_lines.append(f"> {line}")
182
126
 
183
127
  return "\n".join(formatted_lines)
184
128
 
185
- @override
186
129
  @staticmethod
187
130
  def match_markdown(text: str) -> bool:
188
131
  """Check if this element can handle the given markdown text."""
189
132
  quote_pattern = re.compile(r"^\s*>\s?(.*)", re.MULTILINE)
190
133
  return bool(quote_pattern.search(text))
191
134
 
192
- @override
193
135
  @staticmethod
194
136
  def match_notion(block: Dict[str, Any]) -> bool:
195
137
  """Check if this element can handle the given Notion block."""
196
138
  return block.get("type") == "quote"
197
139
 
198
- @override
199
140
  @staticmethod
200
141
  def is_multiline() -> bool:
201
142
  """Blockquotes can span multiple lines."""
@@ -212,31 +153,21 @@ class QuoteElement(NotionBlockElement):
212
153
  result += text_obj.get("plain_text", "")
213
154
  return result
214
155
 
215
- @override
216
156
  @classmethod
217
- def get_llm_prompt_content(cls) -> dict:
218
- """Returns information for LLM prompts about this element."""
157
+ def get_llm_prompt_content(cls) -> ElementPromptContent:
158
+ """
159
+ Returns structured LLM prompt metadata for the quote element.
160
+ """
219
161
  return {
220
- "description": "Creates blockquotes that visually distinguish quoted text with optional background colors.",
221
- "when_to_use": "Use blockquotes for quoting external sources, highlighting important statements, or creating visual emphasis for key information.",
222
- "syntax": [
223
- "> Text - Simple blockquote",
224
- "> [background:color] Text - Blockquote with colored background",
225
- ],
226
- "color_options": [
227
- "gray",
228
- "brown",
229
- "orange",
230
- "yellow",
231
- "green",
232
- "blue",
233
- "purple",
234
- "pink",
235
- "red",
236
- ],
162
+ "description": "Creates blockquotes that visually distinguish quoted text.",
163
+ "when_to_use": (
164
+ "Use blockquotes for quoting external sources, highlighting important statements, "
165
+ "or creating visual emphasis for key information."
166
+ ),
167
+ "syntax": "> Quoted text",
237
168
  "examples": [
238
- "> This is a simple blockquote without any color",
239
- "> [background:blue] This is a blockquote with blue background",
240
- "> Multi-line quotes\n> continue like this\n> across several lines",
169
+ "> This is a simple blockquote",
170
+ "> This is a multi-line quote\n> that continues on the next line",
171
+ "> Important note:\n> This quote spans\n> multiple lines.",
241
172
  ],
242
173
  }
@@ -0,0 +1,90 @@
1
+ from typing import Dict, Any, Optional, List, Type
2
+
3
+ from notionary.elements.notion_block_element import NotionBlockElement
4
+ from notionary.elements.prompts.synthax_prompt_builder import (
5
+ MarkdownSyntaxPromptBuilder,
6
+ )
7
+ from notionary.elements.text_inline_formatter import TextInlineFormatter
8
+
9
+
10
+ class BlockElementRegistry:
11
+ """Registry of elements that can convert between Markdown and Notion."""
12
+
13
+ def __init__(self, elements=None):
14
+ """
15
+ Initialize a new registry instance.
16
+ """
17
+ self._elements = []
18
+
19
+ if elements:
20
+ for element in elements:
21
+ self.register(element)
22
+
23
+ def register(self, element_class: Type[NotionBlockElement]):
24
+ """Register an element class."""
25
+ self._elements.append(element_class)
26
+ return self
27
+
28
+ def deregister(self, element_class: Type[NotionBlockElement]) -> bool:
29
+ """
30
+ Deregister an element class.
31
+ """
32
+ if element_class in self._elements:
33
+ self._elements.remove(element_class)
34
+ return True
35
+ return False
36
+
37
+ def clear(self):
38
+ """Clear the registry completely."""
39
+ self._elements.clear()
40
+ return self
41
+
42
+ def find_markdown_handler(self, text: str) -> Optional[Type[NotionBlockElement]]:
43
+ """Find an element that can handle the given markdown text."""
44
+ for element in self._elements:
45
+ if element.match_markdown(text):
46
+ return element
47
+ return None
48
+
49
+ def find_notion_handler(
50
+ self, block: Dict[str, Any]
51
+ ) -> Optional[Type[NotionBlockElement]]:
52
+ """Find an element that can handle the given Notion block."""
53
+ for element in self._elements:
54
+ if element.match_notion(block):
55
+ return element
56
+ return None
57
+
58
+ def markdown_to_notion(self, text: str) -> Optional[Dict[str, Any]]:
59
+ """Convert markdown to Notion block using registered elements."""
60
+ handler = self.find_markdown_handler(text)
61
+ if handler:
62
+ return handler.markdown_to_notion(text)
63
+ return None
64
+
65
+ def notion_to_markdown(self, block: Dict[str, Any]) -> Optional[str]:
66
+ """Convert Notion block to markdown using registered elements."""
67
+ handler = self.find_notion_handler(block)
68
+ if handler:
69
+ return handler.notion_to_markdown(block)
70
+ return None
71
+
72
+ def get_multiline_elements(self) -> List[Type[NotionBlockElement]]:
73
+ """Get all registered multiline elements."""
74
+ return [element for element in self._elements if element.is_multiline()]
75
+
76
+ def get_elements(self) -> List[Type[NotionBlockElement]]:
77
+ """Get all registered elements."""
78
+ return self._elements.copy()
79
+
80
+ def generate_llm_prompt(self) -> str:
81
+ """
82
+ Generates an LLM system prompt that describes the Markdown syntax of all registered elements.
83
+ """
84
+ element_classes = self._elements.copy()
85
+
86
+ formatter_names = [e.__name__ for e in element_classes]
87
+ if "TextInlineFormatter" not in formatter_names:
88
+ element_classes = [TextInlineFormatter] + element_classes
89
+
90
+ return MarkdownSyntaxPromptBuilder.generate_system_prompt(element_classes)
@@ -3,10 +3,12 @@ from typing import List, Type
3
3
  from collections import OrderedDict
4
4
 
5
5
  from notionary.elements.audio_element import AudioElement
6
+ from notionary.elements.bulleted_list_element import BulletedListElement
6
7
  from notionary.elements.embed_element import EmbedElement
7
8
  from notionary.elements.mention_element import MentionElement
8
9
  from notionary.elements.notion_block_element import NotionBlockElement
9
- from notionary.elements.block_element_registry import (
10
+ from notionary.elements.numbered_list_element import NumberedListElement
11
+ from notionary.elements.registry.block_element_registry import (
10
12
  BlockElementRegistry,
11
13
  )
12
14
 
@@ -17,10 +19,6 @@ from notionary.elements.code_block_element import CodeBlockElement
17
19
  from notionary.elements.divider_element import DividerElement
18
20
  from notionary.elements.table_element import TableElement
19
21
  from notionary.elements.todo_lists import TodoElement
20
- from notionary.elements.list_element import (
21
- BulletedListElement,
22
- NumberedListElement,
23
- )
24
22
  from notionary.elements.qoute_element import QuoteElement
25
23
  from notionary.elements.image_element import ImageElement
26
24
  from notionary.elements.video_element import VideoElement
@@ -42,33 +40,9 @@ class BlockElementRegistryBuilder:
42
40
  self._elements = OrderedDict()
43
41
 
44
42
  @classmethod
45
- def start_empty(cls) -> BlockElementRegistryBuilder:
46
- """
47
- Start with a completely empty registry builder.
48
-
49
- Returns:
50
- A new builder instance with no elements
51
- """
52
- return cls()
53
-
54
- @classmethod
55
- def start_minimal(cls) -> BlockElementRegistryBuilder:
56
- """
57
- Start with a minimal set of essential elements.
58
-
59
- Returns:
60
- A new builder instance with basic elements
61
- """
62
- builder = cls()
63
- return builder.with_headings().with_lists().with_paragraphs()
64
-
65
- @classmethod
66
- def start_standard(cls) -> BlockElementRegistryBuilder:
43
+ def create_full_registry(cls) -> BlockElementRegistry:
67
44
  """
68
45
  Start with all standard elements in recommended order.
69
-
70
- Returns:
71
- A new builder instance with all standard elements
72
46
  """
73
47
  builder = cls()
74
48
  return (
@@ -78,7 +52,8 @@ class BlockElementRegistryBuilder:
78
52
  .with_dividers()
79
53
  .with_tables()
80
54
  .with_columns()
81
- .with_lists()
55
+ .with_bulleted_list()
56
+ .with_numbered_list()
82
57
  .with_toggles()
83
58
  .with_quotes()
84
59
  .with_todos()
@@ -89,9 +64,7 @@ class BlockElementRegistryBuilder:
89
64
  .with_audio()
90
65
  .with_mention()
91
66
  .with_paragraphs()
92
- )
93
-
94
- # Element manipulation methods
67
+ ).build()
95
68
 
96
69
  def add_element(
97
70
  self, element_class: Type[NotionBlockElement]
@@ -168,153 +141,108 @@ class BlockElementRegistryBuilder:
168
141
  def with_paragraphs(self) -> BlockElementRegistryBuilder:
169
142
  """
170
143
  Add support for paragraph elements.
171
-
172
- Returns:
173
- Self for method chaining
174
144
  """
175
145
  return self.add_element(ParagraphElement)
176
146
 
177
147
  def with_headings(self) -> BlockElementRegistryBuilder:
178
148
  """
179
149
  Add support for heading elements.
180
-
181
- Returns:
182
- Self for method chaining
183
150
  """
184
151
  return self.add_element(HeadingElement)
185
152
 
186
153
  def with_callouts(self) -> BlockElementRegistryBuilder:
187
154
  """
188
155
  Add support for callout elements.
189
-
190
- Returns:
191
- Self for method chaining
192
156
  """
193
157
  return self.add_element(CalloutElement)
194
158
 
195
159
  def with_code(self) -> BlockElementRegistryBuilder:
196
160
  """
197
161
  Add support for code blocks.
198
-
199
- Returns:
200
- Self for method chaining
201
162
  """
202
163
  return self.add_element(CodeBlockElement)
203
164
 
204
165
  def with_dividers(self) -> BlockElementRegistryBuilder:
205
166
  """
206
167
  Add support for divider elements.
207
-
208
- Returns:
209
- Self for method chaining
210
168
  """
211
169
  return self.add_element(DividerElement)
212
170
 
213
171
  def with_tables(self) -> BlockElementRegistryBuilder:
214
172
  """
215
173
  Add support for tables.
216
-
217
- Returns:
218
- Self for method chaining
219
174
  """
220
175
  return self.add_element(TableElement)
221
176
 
222
177
  def with_columns(self) -> BlockElementRegistryBuilder:
223
178
  """
224
179
  Add support for column elements.
225
-
226
- Returns:
227
- Self for method chaining
228
180
  """
229
181
  return self.add_element(ColumnElement)
230
182
 
231
- def with_lists(self) -> BlockElementRegistryBuilder:
183
+ def with_bulleted_list(self) -> BlockElementRegistryBuilder:
184
+ """
185
+ Add support for bulleted list elements (unordered lists).
232
186
  """
233
- Add support for list elements.
187
+ return self.add_element(BulletedListElement)
234
188
 
235
- Returns:
236
- Self for method chaining
189
+ def with_numbered_list(self) -> BlockElementRegistryBuilder:
190
+ """
191
+ Add support for numbered list elements (ordered lists).
237
192
  """
238
- return self.add_element(BulletedListElement).add_element(NumberedListElement)
193
+ return self.add_element(NumberedListElement)
239
194
 
240
195
  def with_toggles(self) -> BlockElementRegistryBuilder:
241
196
  """
242
197
  Add support for toggle elements.
243
-
244
- Returns:
245
- Self for method chaining
246
198
  """
247
199
  return self.add_element(ToggleElement)
248
200
 
249
201
  def with_quotes(self) -> BlockElementRegistryBuilder:
250
202
  """
251
203
  Add support for quote elements.
252
-
253
- Returns:
254
- Self for method chaining
255
204
  """
256
205
  return self.add_element(QuoteElement)
257
206
 
258
207
  def with_todos(self) -> BlockElementRegistryBuilder:
259
208
  """
260
209
  Add support for todo elements.
261
-
262
- Returns:
263
- Self for method chaining
264
210
  """
265
211
  return self.add_element(TodoElement)
266
212
 
267
213
  def with_bookmarks(self) -> BlockElementRegistryBuilder:
268
214
  """
269
215
  Add support for bookmark elements.
270
-
271
- Returns:
272
- Self for method chaining
273
216
  """
274
217
  return self.add_element(BookmarkElement)
275
218
 
276
219
  def with_images(self) -> BlockElementRegistryBuilder:
277
220
  """
278
221
  Add support for image elements.
279
-
280
- Returns:
281
- Self for method chaining
282
222
  """
283
223
  return self.add_element(ImageElement)
284
224
 
285
225
  def with_videos(self) -> BlockElementRegistryBuilder:
286
226
  """
287
227
  Add support for video elements.
288
-
289
- Returns:
290
- Self for method chaining
291
228
  """
292
229
  return self.add_element(VideoElement)
293
230
 
294
231
  def with_embeds(self) -> BlockElementRegistryBuilder:
295
232
  """
296
233
  Add support for embed elements.
297
-
298
- Returns:
299
- Self for method chaining
300
234
  """
301
235
  return self.add_element(EmbedElement)
302
236
 
303
237
  def with_audio(self) -> BlockElementRegistryBuilder:
304
238
  """
305
239
  Add support for audio elements.
306
-
307
- Returns:
308
- Self for method chaining
309
240
  """
310
241
  return self.add_element(AudioElement)
311
242
 
312
243
  def with_media_support(self) -> BlockElementRegistryBuilder:
313
244
  """
314
245
  Add support for media elements (images, videos, audio).
315
-
316
- Returns:
317
- Self for method chaining
318
246
  """
319
247
  return self.with_images().with_videos().with_audio()
320
248
 
@@ -333,10 +261,8 @@ class BlockElementRegistryBuilder:
333
261
  A configured BlockElementRegistry instance
334
262
  """
335
263
  if ParagraphElement.__name__ not in self._elements:
336
- # Add paragraph as fallback if not present
337
264
  self.add_element(ParagraphElement)
338
265
  else:
339
- # Ensure it's at the end
340
266
  self._ensure_paragraph_at_end()
341
267
 
342
268
  registry = BlockElementRegistry()
@@ -346,38 +272,3 @@ class BlockElementRegistryBuilder:
346
272
  registry.register(element_class)
347
273
 
348
274
  return registry
349
-
350
- @classmethod
351
- def create_standard_registry(cls) -> BlockElementRegistry:
352
- """
353
- Factory method to directly create a standard registry.
354
-
355
- Returns:
356
- A fully configured registry instance
357
- """
358
- return cls.start_standard().build()
359
-
360
- @classmethod
361
- def create_minimal_registry(cls) -> BlockElementRegistry:
362
- """
363
- Factory method to directly create a minimal registry.
364
-
365
- Returns:
366
- A minimal registry instance
367
- """
368
- return cls.start_minimal().build()
369
-
370
- @classmethod
371
- def create_custom_registry(
372
- cls, element_classes: List[Type[NotionBlockElement]]
373
- ) -> BlockElementRegistry:
374
- """
375
- Factory method to directly create a custom registry.
376
-
377
- Args:
378
- element_classes: List of element classes to register
379
-
380
- Returns:
381
- A custom configured registry instance
382
- """
383
- return cls().add_elements(element_classes).build()
@@ -1,10 +1,8 @@
1
- # File: elements/tables.py
2
-
3
- from typing import Dict, Any, Optional, List, Tuple
4
- from typing_extensions import override
5
1
  import re
2
+ from typing import Dict, Any, Optional, List, Tuple
6
3
  from notionary.elements.notion_block_element import NotionBlockElement
7
4
  from notionary.elements.text_inline_formatter import TextInlineFormatter
5
+ from notionary.elements.prompts.element_prompt_content import ElementPromptContent
8
6
 
9
7
 
10
8
  class TableElement(NotionBlockElement):
@@ -20,11 +18,9 @@ class TableElement(NotionBlockElement):
20
18
  The second line with dashes and optional colons defines column alignment.
21
19
  """
22
20
 
23
- # Patterns for detecting Markdown tables
24
21
  ROW_PATTERN = re.compile(r"^\s*\|(.+)\|\s*$")
25
22
  SEPARATOR_PATTERN = re.compile(r"^\s*\|([\s\-:|]+)\|\s*$")
26
23
 
27
- @override
28
24
  @staticmethod
29
25
  def match_markdown(text: str) -> bool:
30
26
  """Check if text contains a markdown table."""
@@ -43,13 +39,11 @@ class TableElement(NotionBlockElement):
43
39
 
44
40
  return False
45
41
 
46
- @override
47
42
  @staticmethod
48
43
  def match_notion(block: Dict[str, Any]) -> bool:
49
44
  """Check if block is a Notion table."""
50
45
  return block.get("type") == "table"
51
46
 
52
- @override
53
47
  @staticmethod
54
48
  def markdown_to_notion(text: str) -> Optional[Dict[str, Any]]:
55
49
  """Convert markdown table to Notion table block."""
@@ -82,7 +76,6 @@ class TableElement(NotionBlockElement):
82
76
  },
83
77
  }
84
78
 
85
- @override
86
79
  @staticmethod
87
80
  def notion_to_markdown(block: Dict[str, Any]) -> Optional[str]:
88
81
  """Convert Notion table block to markdown table."""
@@ -145,7 +138,6 @@ class TableElement(NotionBlockElement):
145
138
 
146
139
  return "\n".join(table_rows)
147
140
 
148
- @override
149
141
  @staticmethod
150
142
  def is_multiline() -> bool:
151
143
  """Indicates if this element handles content that spans multiple lines."""
@@ -289,16 +281,12 @@ class TableElement(NotionBlockElement):
289
281
  return position
290
282
 
291
283
  @classmethod
292
- def get_llm_prompt_content(cls) -> dict:
284
+ def get_llm_prompt_content(cls) -> ElementPromptContent:
293
285
  """Returns information for LLM prompts about this element."""
294
286
  return {
295
287
  "description": "Creates formatted tables with rows and columns for structured data.",
296
288
  "when_to_use": "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.",
297
- "notes": [
298
- "The header row is required and will be displayed differently in Notion",
299
- "The separator row with dashes is required to define the table structure",
300
- "Table cells support inline formatting such as **bold** and *italic*",
301
- ],
289
+ "syntax": "| Header 1 | Header 2 | Header 3 |\n| -------- | -------- | -------- |\n| Cell 1 | Cell 2 | Cell 3 |",
302
290
  "examples": [
303
291
  "| Product | Price | Stock |\n| ------- | ----- | ----- |\n| Widget A | $10.99 | 42 |\n| Widget B | $14.99 | 27 |",
304
292
  "| Name | Role | Department |\n| ---- | ---- | ---------- |\n| John Smith | Manager | Marketing |\n| Jane Doe | Director | Sales |",