notionary 0.2.7__tar.gz → 0.2.9__tar.gz
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-0.2.7 → notionary-0.2.9}/PKG-INFO +28 -2
- {notionary-0.2.7 → notionary-0.2.9}/README.md +27 -1
- notionary-0.2.9/notionary/elements/column_element.py +360 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/divider_element.py +1 -1
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/heading_element.py +4 -1
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/registry/block_registry.py +1 -1
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/registry/block_registry_builder.py +3 -2
- notionary-0.2.9/notionary/page/content/page_content_writer.py +203 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/page/markdown_to_notion_converter.py +124 -23
- {notionary-0.2.7 → notionary-0.2.9}/notionary/prompting/element_prompt_content.py +0 -1
- {notionary-0.2.7 → notionary-0.2.9}/notionary/prompting/markdown_syntax_prompt_generator.py +2 -4
- {notionary-0.2.7 → notionary-0.2.9}/notionary.egg-info/PKG-INFO +28 -2
- {notionary-0.2.7 → notionary-0.2.9}/setup.py +1 -1
- notionary-0.2.7/notionary/elements/column_element.py +0 -204
- notionary-0.2.7/notionary/page/content/page_content_writer.py +0 -113
- {notionary-0.2.7 → notionary-0.2.9}/LICENSE +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/__init__.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/database/database_discovery.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/database/models/page_result.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/database/notion_database.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/database/notion_database_factory.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/audio_element.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/bookmark_element.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/bulleted_list_element.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/callout_element.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/code_block_element.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/embed_element.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/image_element.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/mention_element.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/notion_block_element.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/numbered_list_element.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/paragraph_element.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/qoute_element.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/table_element.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/text_inline_formatter.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/todo_element.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/toggle_element.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/toggleable_heading_element.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/elements/video_element.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/exceptions/database_exceptions.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/exceptions/page_creation_exception.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/models/notion_block_response.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/models/notion_database_response.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/models/notion_page_response.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/notion_client.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/page/content/notion_page_content_chunker.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/page/content/page_content_retriever.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/page/metadata/metadata_editor.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/page/metadata/notion_icon_manager.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/page/metadata/notion_page_cover_manager.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/page/notion_page.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/page/notion_page_factory.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/page/notion_to_markdown_converter.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/page/properites/database_property_service.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/page/properites/page_property_manager.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/page/properites/property_formatter.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/page/properites/property_value_extractor.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/page/relations/notion_page_relation_manager.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/page/relations/notion_page_title_resolver.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/page/relations/page_database_relation.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/util/logging_mixin.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/util/page_id_utils.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary/util/warn_direct_constructor_usage.py +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary.egg-info/SOURCES.txt +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary.egg-info/dependency_links.txt +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary.egg-info/requires.txt +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/notionary.egg-info/top_level.txt +0 -0
- {notionary-0.2.7 → notionary-0.2.9}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: notionary
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.9
|
4
4
|
Summary: A toolkit to convert between Markdown and Notion blocks
|
5
5
|
Home-page: https://github.com/mathisarends/notionary
|
6
6
|
Author: Mathis Arends
|
@@ -153,6 +153,31 @@ Notionary extends standard Markdown with special syntax to support Notion-specif
|
|
153
153
|
| 3. Add content with replace_content() or append_markdown()
|
154
154
|
```
|
155
155
|
|
156
|
+
### Multi-Column Layout
|
157
|
+
|
158
|
+
```markdown
|
159
|
+
::: columns
|
160
|
+
::: column
|
161
|
+
|
162
|
+
## Left Column
|
163
|
+
|
164
|
+
- Item 1
|
165
|
+
- Item 2
|
166
|
+
- Item 3
|
167
|
+
:::
|
168
|
+
::: column
|
169
|
+
|
170
|
+
## Right Column
|
171
|
+
|
172
|
+
This text appears in the second column. Multi-column layouts are perfect for:
|
173
|
+
|
174
|
+
- Comparing features
|
175
|
+
- Creating side-by-side content
|
176
|
+
- Improving readability of wide content
|
177
|
+
:::
|
178
|
+
:::
|
179
|
+
```
|
180
|
+
|
156
181
|
### Code Blocks
|
157
182
|
|
158
183
|
```python
|
@@ -196,6 +221,7 @@ custom_registry = (
|
|
196
221
|
.with_headings()
|
197
222
|
.with_callouts()
|
198
223
|
.with_toggles()
|
224
|
+
.with_columns() # Include multi-column support
|
199
225
|
.with_code()
|
200
226
|
.with_todos()
|
201
227
|
.with_paragraphs()
|
@@ -205,7 +231,7 @@ custom_registry = (
|
|
205
231
|
# Apply this registry to a page
|
206
232
|
page = NotionPage.from_url("https://www.notion.so/your-page-url")
|
207
233
|
page.block_registry = custom_registry
|
208
|
-
|
234
|
+
|
209
235
|
# Replace content using only supported elements
|
210
236
|
await page.replace_content("# Custom heading with selected elements only")
|
211
237
|
```
|
@@ -127,6 +127,31 @@ Notionary extends standard Markdown with special syntax to support Notion-specif
|
|
127
127
|
| 3. Add content with replace_content() or append_markdown()
|
128
128
|
```
|
129
129
|
|
130
|
+
### Multi-Column Layout
|
131
|
+
|
132
|
+
```markdown
|
133
|
+
::: columns
|
134
|
+
::: column
|
135
|
+
|
136
|
+
## Left Column
|
137
|
+
|
138
|
+
- Item 1
|
139
|
+
- Item 2
|
140
|
+
- Item 3
|
141
|
+
:::
|
142
|
+
::: column
|
143
|
+
|
144
|
+
## Right Column
|
145
|
+
|
146
|
+
This text appears in the second column. Multi-column layouts are perfect for:
|
147
|
+
|
148
|
+
- Comparing features
|
149
|
+
- Creating side-by-side content
|
150
|
+
- Improving readability of wide content
|
151
|
+
:::
|
152
|
+
:::
|
153
|
+
```
|
154
|
+
|
130
155
|
### Code Blocks
|
131
156
|
|
132
157
|
```python
|
@@ -170,6 +195,7 @@ custom_registry = (
|
|
170
195
|
.with_headings()
|
171
196
|
.with_callouts()
|
172
197
|
.with_toggles()
|
198
|
+
.with_columns() # Include multi-column support
|
173
199
|
.with_code()
|
174
200
|
.with_todos()
|
175
201
|
.with_paragraphs()
|
@@ -179,7 +205,7 @@ custom_registry = (
|
|
179
205
|
# Apply this registry to a page
|
180
206
|
page = NotionPage.from_url("https://www.notion.so/your-page-url")
|
181
207
|
page.block_registry = custom_registry
|
182
|
-
|
208
|
+
|
183
209
|
# Replace content using only supported elements
|
184
210
|
await page.replace_content("# Custom heading with selected elements only")
|
185
211
|
```
|
@@ -0,0 +1,360 @@
|
|
1
|
+
import re
|
2
|
+
from typing import Dict, Any, Optional, List, Tuple, Callable
|
3
|
+
|
4
|
+
from notionary.elements.notion_block_element import NotionBlockElement
|
5
|
+
from notionary.prompting.element_prompt_content import ElementPromptBuilder, ElementPromptContent
|
6
|
+
|
7
|
+
|
8
|
+
class ColumnElement(NotionBlockElement):
|
9
|
+
"""
|
10
|
+
Handles conversion between custom Markdown column syntax and Notion column blocks.
|
11
|
+
|
12
|
+
Markdown column syntax:
|
13
|
+
::: columns
|
14
|
+
::: column
|
15
|
+
Content for first column
|
16
|
+
:::
|
17
|
+
::: column
|
18
|
+
Content for second column
|
19
|
+
:::
|
20
|
+
:::
|
21
|
+
|
22
|
+
This creates a column layout in Notion with the specified content in each column.
|
23
|
+
"""
|
24
|
+
|
25
|
+
COLUMNS_START = re.compile(r"^:::\s*columns\s*$")
|
26
|
+
COLUMN_START = re.compile(r"^:::\s*column\s*$")
|
27
|
+
BLOCK_END = re.compile(r"^:::\s*$")
|
28
|
+
|
29
|
+
_converter_callback = None
|
30
|
+
|
31
|
+
@classmethod
|
32
|
+
def set_converter_callback(
|
33
|
+
cls, callback: Callable[[str], List[Dict[str, Any]]]
|
34
|
+
) -> None:
|
35
|
+
"""
|
36
|
+
Setze die Callback-Funktion, die zum Konvertieren von Markdown zu Notion-Blöcken verwendet wird.
|
37
|
+
|
38
|
+
Args:
|
39
|
+
callback: Funktion, die Markdown-Text annimmt und eine Liste von Notion-Blöcken zurückgibt
|
40
|
+
"""
|
41
|
+
cls._converter_callback = callback
|
42
|
+
|
43
|
+
@staticmethod
|
44
|
+
def match_markdown(text: str) -> bool:
|
45
|
+
"""Check if text starts a columns block."""
|
46
|
+
return bool(ColumnElement.COLUMNS_START.match(text.strip()))
|
47
|
+
|
48
|
+
@staticmethod
|
49
|
+
def match_notion(block: Dict[str, Any]) -> bool:
|
50
|
+
"""Check if block is a Notion column_list."""
|
51
|
+
return block.get("type") == "column_list"
|
52
|
+
|
53
|
+
@staticmethod
|
54
|
+
def markdown_to_notion(text: str) -> Optional[Dict[str, Any]]:
|
55
|
+
"""
|
56
|
+
Convert markdown column syntax to Notion column blocks.
|
57
|
+
|
58
|
+
Note: This only processes the first line (columns start).
|
59
|
+
The full column content needs to be processed separately.
|
60
|
+
"""
|
61
|
+
if not ColumnElement.COLUMNS_START.match(text.strip()):
|
62
|
+
return None
|
63
|
+
|
64
|
+
# Create an empty column_list block
|
65
|
+
# Child columns will be added by the column processor
|
66
|
+
return {"type": "column_list", "column_list": {"children": []}}
|
67
|
+
|
68
|
+
@staticmethod
|
69
|
+
def notion_to_markdown(block: Dict[str, Any]) -> Optional[str]:
|
70
|
+
"""Convert Notion column_list block to markdown column syntax."""
|
71
|
+
if block.get("type") != "column_list":
|
72
|
+
return None
|
73
|
+
|
74
|
+
column_children = block.get("column_list", {}).get("children", [])
|
75
|
+
|
76
|
+
# Start the columns block
|
77
|
+
result = ["::: columns"]
|
78
|
+
|
79
|
+
# Process each column
|
80
|
+
for column_block in column_children:
|
81
|
+
if column_block.get("type") == "column":
|
82
|
+
result.append("::: column")
|
83
|
+
|
84
|
+
for _ in column_block.get("column", {}).get("children", []):
|
85
|
+
result.append(" [Column content]") # Placeholder
|
86
|
+
|
87
|
+
result.append(":::")
|
88
|
+
|
89
|
+
# End the columns block
|
90
|
+
result.append(":::")
|
91
|
+
|
92
|
+
return "\n".join(result)
|
93
|
+
|
94
|
+
@staticmethod
|
95
|
+
def is_multiline() -> bool:
|
96
|
+
"""Column blocks span multiple lines."""
|
97
|
+
return True
|
98
|
+
|
99
|
+
@classmethod
|
100
|
+
def find_matches(
|
101
|
+
cls, text: str, converter_callback: Optional[Callable] = None
|
102
|
+
) -> List[Tuple[int, int, Dict[str, Any]]]:
|
103
|
+
"""
|
104
|
+
Find all column block matches in the text and return their positions and blocks.
|
105
|
+
|
106
|
+
Args:
|
107
|
+
text: The input markdown text
|
108
|
+
converter_callback: Optional callback to convert nested content
|
109
|
+
|
110
|
+
Returns:
|
111
|
+
List of tuples (start_pos, end_pos, block)
|
112
|
+
"""
|
113
|
+
# Wenn ein Callback übergeben wurde, nutze diesen, sonst die gespeicherte Referenz
|
114
|
+
converter = converter_callback or cls._converter_callback
|
115
|
+
if not converter:
|
116
|
+
raise ValueError(
|
117
|
+
"No converter callback provided for ColumnElement. Call set_converter_callback first or provide converter_callback parameter."
|
118
|
+
)
|
119
|
+
|
120
|
+
matches = []
|
121
|
+
lines = text.split("\n")
|
122
|
+
i = 0
|
123
|
+
|
124
|
+
while i < len(lines):
|
125
|
+
# Skip non-column lines
|
126
|
+
if not ColumnElement.COLUMNS_START.match(lines[i].strip()):
|
127
|
+
i += 1
|
128
|
+
continue
|
129
|
+
|
130
|
+
# Process a column block and add to matches
|
131
|
+
column_block_info = cls._process_column_block(
|
132
|
+
lines=lines, start_index=i, converter_callback=converter
|
133
|
+
)
|
134
|
+
matches.append(column_block_info)
|
135
|
+
|
136
|
+
# Skip to the end of the processed column block
|
137
|
+
i = column_block_info[3] # i is returned as the 4th element in the tuple
|
138
|
+
|
139
|
+
return [(start, end, block) for start, end, block, _ in matches]
|
140
|
+
|
141
|
+
@classmethod
|
142
|
+
def _process_column_block(
|
143
|
+
cls, lines: List[str], start_index: int, converter_callback: Callable
|
144
|
+
) -> Tuple[int, int, Dict[str, Any], int]:
|
145
|
+
"""
|
146
|
+
Process a complete column block structure from the given starting line.
|
147
|
+
|
148
|
+
Args:
|
149
|
+
lines: All lines of the text
|
150
|
+
start_index: Index of the column block start line
|
151
|
+
converter_callback: Callback function to convert markdown to notion blocks
|
152
|
+
|
153
|
+
Returns:
|
154
|
+
Tuple of (start_pos, end_pos, block, next_line_index)
|
155
|
+
"""
|
156
|
+
columns_start = start_index
|
157
|
+
columns_block = cls.markdown_to_notion(lines[start_index].strip())
|
158
|
+
columns_children = []
|
159
|
+
|
160
|
+
next_index = cls._collect_columns(
|
161
|
+
lines, start_index + 1, columns_children, converter_callback
|
162
|
+
)
|
163
|
+
|
164
|
+
# Add columns to the main block
|
165
|
+
if columns_children:
|
166
|
+
columns_block["column_list"]["children"] = columns_children
|
167
|
+
|
168
|
+
# Calculate positions
|
169
|
+
start_pos = sum(len(lines[j]) + 1 for j in range(columns_start))
|
170
|
+
end_pos = sum(len(lines[j]) + 1 for j in range(next_index))
|
171
|
+
|
172
|
+
return (start_pos, end_pos, columns_block, next_index)
|
173
|
+
|
174
|
+
@classmethod
|
175
|
+
def _collect_columns(
|
176
|
+
cls,
|
177
|
+
lines: List[str],
|
178
|
+
start_index: int,
|
179
|
+
columns_children: List[Dict[str, Any]],
|
180
|
+
converter_callback: Callable,
|
181
|
+
) -> int:
|
182
|
+
"""
|
183
|
+
Collect all columns within a column block structure.
|
184
|
+
|
185
|
+
Args:
|
186
|
+
lines: All lines of the text
|
187
|
+
start_index: Index to start collecting from
|
188
|
+
columns_children: List to append collected columns to
|
189
|
+
converter_callback: Callback function to convert column content
|
190
|
+
|
191
|
+
Returns:
|
192
|
+
Next line index after all columns have been processed
|
193
|
+
"""
|
194
|
+
i = start_index
|
195
|
+
in_column = False
|
196
|
+
column_content = []
|
197
|
+
|
198
|
+
while i < len(lines):
|
199
|
+
current_line = lines[i].strip()
|
200
|
+
|
201
|
+
if cls.COLUMNS_START.match(current_line):
|
202
|
+
break
|
203
|
+
|
204
|
+
if cls.COLUMN_START.match(current_line):
|
205
|
+
cls._finalize_column(
|
206
|
+
column_content, columns_children, in_column, converter_callback
|
207
|
+
)
|
208
|
+
column_content = []
|
209
|
+
in_column = True
|
210
|
+
i += 1
|
211
|
+
continue
|
212
|
+
|
213
|
+
if cls.BLOCK_END.match(current_line) and in_column:
|
214
|
+
cls._finalize_column(
|
215
|
+
column_content, columns_children, in_column, converter_callback
|
216
|
+
)
|
217
|
+
column_content = []
|
218
|
+
in_column = False
|
219
|
+
i += 1
|
220
|
+
continue
|
221
|
+
|
222
|
+
if cls.BLOCK_END.match(current_line) and not in_column:
|
223
|
+
i += 1
|
224
|
+
break
|
225
|
+
|
226
|
+
if in_column:
|
227
|
+
column_content.append(lines[i])
|
228
|
+
|
229
|
+
i += 1
|
230
|
+
|
231
|
+
cls._finalize_column(
|
232
|
+
column_content, columns_children, in_column, converter_callback
|
233
|
+
)
|
234
|
+
|
235
|
+
return i
|
236
|
+
|
237
|
+
@staticmethod
|
238
|
+
def _finalize_column(
|
239
|
+
column_content: List[str],
|
240
|
+
columns_children: List[Dict[str, Any]],
|
241
|
+
in_column: bool,
|
242
|
+
converter_callback: Callable,
|
243
|
+
) -> None:
|
244
|
+
"""
|
245
|
+
Finalize a column by processing its content and adding it to the columns_children list.
|
246
|
+
|
247
|
+
Args:
|
248
|
+
column_content: Content lines of the column
|
249
|
+
columns_children: List to append the column block to
|
250
|
+
in_column: Whether we're currently in a column (if False, does nothing)
|
251
|
+
converter_callback: Callback function to convert column content
|
252
|
+
"""
|
253
|
+
if not (in_column and column_content):
|
254
|
+
return
|
255
|
+
|
256
|
+
processed_content = ColumnElement._preprocess_column_content(column_content)
|
257
|
+
|
258
|
+
column_blocks = converter_callback("\n".join(processed_content))
|
259
|
+
|
260
|
+
# Create column block
|
261
|
+
column_block = {"type": "column", "column": {"children": column_blocks}}
|
262
|
+
columns_children.append(column_block)
|
263
|
+
|
264
|
+
@classmethod
|
265
|
+
def is_multiline(cls) -> bool:
|
266
|
+
"""Column blocks span multiple lines."""
|
267
|
+
return True
|
268
|
+
|
269
|
+
@staticmethod
|
270
|
+
def _preprocess_column_content(lines: List[str]) -> List[str]:
|
271
|
+
"""
|
272
|
+
Preprocess column content to handle special cases like first headings.
|
273
|
+
|
274
|
+
This removes any spacer markers that might have been added before the first
|
275
|
+
heading in a column, as each column should have its own heading context.
|
276
|
+
|
277
|
+
Args:
|
278
|
+
lines: The lines of content for the column
|
279
|
+
|
280
|
+
Returns:
|
281
|
+
Processed lines ready for conversion
|
282
|
+
"""
|
283
|
+
from notionary.page.markdown_to_notion_converter import MarkdownToNotionConverter
|
284
|
+
|
285
|
+
processed_lines = []
|
286
|
+
found_first_heading = False
|
287
|
+
spacer_marker = MarkdownToNotionConverter.SPACER_MARKER
|
288
|
+
|
289
|
+
i = 0
|
290
|
+
while i < len(lines):
|
291
|
+
line = lines[i]
|
292
|
+
|
293
|
+
# Check if this is a heading line
|
294
|
+
if re.match(r"^(#{1,6})\s+(.+)$", line.strip()):
|
295
|
+
# If it's the first heading, look ahead to check for spacer
|
296
|
+
if not found_first_heading and i > 0 and processed_lines and processed_lines[-1] == spacer_marker:
|
297
|
+
# Remove spacer before first heading in column
|
298
|
+
processed_lines.pop()
|
299
|
+
|
300
|
+
found_first_heading = True
|
301
|
+
|
302
|
+
processed_lines.append(line)
|
303
|
+
i += 1
|
304
|
+
|
305
|
+
return processed_lines
|
306
|
+
|
307
|
+
@classmethod
|
308
|
+
def get_llm_prompt_content(cls) -> ElementPromptContent:
|
309
|
+
"""
|
310
|
+
Returns structured LLM prompt metadata for the column layout element.
|
311
|
+
"""
|
312
|
+
return (
|
313
|
+
ElementPromptBuilder()
|
314
|
+
.with_description(
|
315
|
+
"Creates a multi-column layout that displays content side by side."
|
316
|
+
)
|
317
|
+
.with_usage_guidelines(
|
318
|
+
"Use columns sparingly, only for direct comparisons or when parallel presentation significantly improves readability. "
|
319
|
+
"Best for pros/cons lists, feature comparisons, or pairing images with descriptions."
|
320
|
+
)
|
321
|
+
.with_avoidance_guidelines(
|
322
|
+
"Avoid overusing as it can complicate document structure. Do not use for simple content that works better in linear format."
|
323
|
+
)
|
324
|
+
.with_syntax(
|
325
|
+
"::: columns\n"
|
326
|
+
"::: column\n"
|
327
|
+
"Content for first column\n"
|
328
|
+
":::\n"
|
329
|
+
"::: column\n"
|
330
|
+
"Content for second column\n"
|
331
|
+
":::\n"
|
332
|
+
":::"
|
333
|
+
)
|
334
|
+
.with_examples([
|
335
|
+
"::: columns\n"
|
336
|
+
"::: column\n"
|
337
|
+
"## Features\n"
|
338
|
+
"- Fast response time\n"
|
339
|
+
"- Intuitive interface\n"
|
340
|
+
"- Regular updates\n"
|
341
|
+
":::\n"
|
342
|
+
"::: column\n"
|
343
|
+
"## Benefits\n"
|
344
|
+
"- Increased productivity\n"
|
345
|
+
"- Better collaboration\n"
|
346
|
+
"- Simplified workflows\n"
|
347
|
+
":::\n"
|
348
|
+
":::",
|
349
|
+
|
350
|
+
"::: columns\n"
|
351
|
+
"::: column\n"
|
352
|
+
"\n"
|
353
|
+
":::\n"
|
354
|
+
"::: column\n"
|
355
|
+
"This text appears next to the image, creating a media-with-caption style layout.\n"
|
356
|
+
":::\n"
|
357
|
+
":::"
|
358
|
+
])
|
359
|
+
.build()
|
360
|
+
)
|
@@ -85,7 +85,10 @@ class HeadingElement(NotionBlockElement):
|
|
85
85
|
.with_usage_guidelines(
|
86
86
|
"Use to group content into sections and define a visual hierarchy."
|
87
87
|
)
|
88
|
+
.with_avoidance_guidelines(
|
89
|
+
"Only H1-H3 syntax is supported. H4 and deeper heading levels are not available."
|
90
|
+
)
|
88
91
|
.with_syntax("## Your Heading Text")
|
89
92
|
.with_standard_markdown()
|
90
93
|
.build()
|
91
|
-
)
|
94
|
+
)
|
@@ -126,7 +126,7 @@ class BlockRegistry:
|
|
126
126
|
|
127
127
|
formatter_names = [e.__name__ for e in element_classes]
|
128
128
|
if "TextInlineFormatter" not in formatter_names:
|
129
|
-
element_classes = element_classes +
|
129
|
+
element_classes = element_classes + [TextInlineFormatter]
|
130
130
|
|
131
131
|
return MarkdownSyntaxPromptGenerator.generate_system_prompt(element_classes)
|
132
132
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
2
2
|
from typing import List, Type
|
3
3
|
from collections import OrderedDict
|
4
4
|
|
5
|
+
from notionary.elements.column_element import ColumnElement
|
5
6
|
from notionary.elements.notion_block_element import NotionBlockElement
|
6
7
|
|
7
8
|
from notionary.elements.audio_element import AudioElement
|
@@ -27,7 +28,6 @@ from notionary.elements.toggleable_heading_element import ToggleableHeadingEleme
|
|
27
28
|
from notionary.elements.video_element import VideoElement
|
28
29
|
from notionary.elements.toggle_element import ToggleElement
|
29
30
|
from notionary.elements.bookmark_element import BookmarkElement
|
30
|
-
from notionary.elements.column_element import ColumnsElement
|
31
31
|
|
32
32
|
|
33
33
|
class BlockRegistryBuilder:
|
@@ -64,6 +64,7 @@ class BlockRegistryBuilder:
|
|
64
64
|
.with_videos()
|
65
65
|
.with_embeds()
|
66
66
|
.with_audio()
|
67
|
+
.with_columns()
|
67
68
|
.with_mention()
|
68
69
|
.with_paragraphs()
|
69
70
|
.with_toggleable_heading_element()
|
@@ -267,7 +268,7 @@ class BlockRegistryBuilder:
|
|
267
268
|
"""
|
268
269
|
Add support for column elements.
|
269
270
|
"""
|
270
|
-
return self.add_element(
|
271
|
+
return self.add_element(ColumnElement)
|
271
272
|
|
272
273
|
def build(self) -> BlockRegistry:
|
273
274
|
"""
|