notionary 0.2.14__tar.gz → 0.2.16__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.16/PKG-INFO +224 -0
- notionary-0.2.16/README.md +201 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/base_notion_client.py +1 -1
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/registry/block_registry.py +27 -3
- {notionary-0.2.14 → notionary-0.2.16}/notionary/database/notion_database.py +44 -30
- {notionary-0.2.14 → notionary-0.2.16}/notionary/database/notion_database_provider.py +6 -10
- {notionary-0.2.14 → notionary-0.2.16}/notionary/page/notion_page.py +1 -3
- notionary-0.2.16/notionary/telemetry/__init__.py +19 -0
- notionary-0.2.16/notionary/telemetry/service.py +136 -0
- notionary-0.2.16/notionary/telemetry/views.py +64 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/util/__init__.py +2 -0
- notionary-0.2.16/pyproject.toml +29 -0
- notionary-0.2.14/PKG-INFO +0 -276
- notionary-0.2.14/README.md +0 -245
- notionary-0.2.14/notionary/cli/main.py +0 -376
- notionary-0.2.14/notionary/cli/onboarding.py +0 -117
- notionary-0.2.14/notionary.egg-info/PKG-INFO +0 -276
- notionary-0.2.14/notionary.egg-info/SOURCES.txt +0 -75
- notionary-0.2.14/notionary.egg-info/dependency_links.txt +0 -1
- notionary-0.2.14/notionary.egg-info/entry_points.txt +0 -2
- notionary-0.2.14/notionary.egg-info/requires.txt +0 -8
- notionary-0.2.14/notionary.egg-info/top_level.txt +0 -1
- notionary-0.2.14/setup.cfg +0 -4
- notionary-0.2.14/setup.py +0 -33
- {notionary-0.2.14 → notionary-0.2.16}/LICENSE +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/__init__.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/__init__.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/audio_element.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/bookmark_element.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/bulleted_list_element.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/callout_element.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/code_block_element.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/column_element.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/divider_element.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/embed_element.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/heading_element.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/image_element.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/mention_element.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/notion_block_client.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/notion_block_element.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/numbered_list_element.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/paragraph_element.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/prompts/element_prompt_builder.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/prompts/element_prompt_content.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/qoute_element.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/registry/block_registry_builder.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/table_element.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/text_inline_formatter.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/todo_element.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/toggle_element.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/toggleable_heading_element.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/blocks/video_element.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/database/__init__.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/database/client.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/database/database_exceptions.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/database/factory.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/database/filter_builder.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/database/models/page_result.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/elements/__init__.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/models/notion_block_response.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/models/notion_database_response.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/models/notion_page_response.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/models/search_response.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/page/__init__.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/page/client.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/page/content/notion_page_content_chunker.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/page/content/page_content_retriever.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/page/content/page_content_writer.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/page/formatting/markdown_to_notion_converter.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/page/formatting/spacer_rules.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/page/markdown_syntax_prompt_generator.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/page/notion_to_markdown_converter.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/page/properites/property_value_extractor.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/page/property_formatter.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/page/search_filter_builder.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/page/utils.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/util/factory_decorator.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/util/fuzzy_matcher.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/util/logging_mixin.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/util/page_id_utils.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/util/singleton_decorator.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/util/singleton_metaclass.py +0 -0
- {notionary-0.2.14 → notionary-0.2.16}/notionary/workspace.py +0 -0
@@ -0,0 +1,224 @@
|
|
1
|
+
Metadata-Version: 2.3
|
2
|
+
Name: notionary
|
3
|
+
Version: 0.2.16
|
4
|
+
Summary: Python library for programmatic Notion workspace management - databases, pages, and content with advanced Markdown support
|
5
|
+
License: MIT
|
6
|
+
Author: Mathis Arends
|
7
|
+
Author-email: mathisarends27@gmail.com
|
8
|
+
Requires-Python: >=3.9
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
11
|
+
Classifier: Programming Language :: Python :: 3.9
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
16
|
+
Requires-Dist: httpx (>=0.28.0)
|
17
|
+
Requires-Dist: posthog (>=6.3.1,<7.0.0)
|
18
|
+
Requires-Dist: pydantic (>=2.11.4)
|
19
|
+
Requires-Dist: python-dotenv (>=1.1.0)
|
20
|
+
Project-URL: Homepage, https://github.com/mathisarends/notionary
|
21
|
+
Description-Content-Type: text/markdown
|
22
|
+
|
23
|
+
<picture>
|
24
|
+
<source media="(prefers-color-scheme: dark)" srcset="./static/notionary-dark.png">
|
25
|
+
<source media="(prefers-color-scheme: light)" srcset="./static/notionary-light.png">
|
26
|
+
<img alt="Notionary logo: dark mode shows a white logo, light mode shows a black logo." src="./static/browser-use.png" width="full">
|
27
|
+
</picture>
|
28
|
+
|
29
|
+
<h1 align="center">Notion API simplified for Python developers 🐍</h1>
|
30
|
+
|
31
|
+
[](https://www.python.org/downloads/)
|
32
|
+
[](LICENSE)
|
33
|
+
|
34
|
+
- **Object-Oriented Design**: Clean, intuitive classes for Pages, Databases, and Workspaces with full CRUD operations
|
35
|
+
- **Rich Markdown to Notion**: Convert extended Markdown (callouts, toggles, columns) directly into beautiful Notion blocks
|
36
|
+
- **Smart Discovery**: Find pages and databases by name with fuzzy matching - no more hunting for URLs
|
37
|
+
- **Async-First Architecture**: Built for modern Python with full async/await support and high performance
|
38
|
+
- **AI-Ready Integration**: Generate LLM system prompts and let AI agents create Notion content seamlessly
|
39
|
+
|
40
|
+
---
|
41
|
+
|
42
|
+
# Quick start
|
43
|
+
```bash
|
44
|
+
pip install notionary
|
45
|
+
```
|
46
|
+
|
47
|
+
- Set up your Notion integration (notion.so/profile/integrations)
|
48
|
+
- Add your integration key in your `.env` file.
|
49
|
+
|
50
|
+
```bash
|
51
|
+
NOTION_SECRET=YOUR_INTEGRATION_KEY
|
52
|
+
```
|
53
|
+
|
54
|
+
### Creating and Managing Pages 🚀
|
55
|
+
```python
|
56
|
+
from notionary import NotionPage
|
57
|
+
|
58
|
+
async def main():
|
59
|
+
# Simpy find an existing page by its title
|
60
|
+
page = await NotionPage.from_page_name("My Test Page")
|
61
|
+
|
62
|
+
# Add rich content with custom Markdown
|
63
|
+
content = """
|
64
|
+
# 🚀 Generated with Notionary
|
65
|
+
|
66
|
+
!> [💡] This page was created programmatically!
|
67
|
+
|
68
|
+
## Features
|
69
|
+
- **Rich** Markdown support
|
70
|
+
- Database integration
|
71
|
+
- AI-ready content generation
|
72
|
+
|
73
|
+
+++ Click to see more details
|
74
|
+
| Notionary makes it easy to create beautiful Notion pages
|
75
|
+
| directly from Python code with intuitive Markdown syntax.
|
76
|
+
"""
|
77
|
+
|
78
|
+
await page.replace_content(content)
|
79
|
+
print(f"✅ Page updated: {page.url}")
|
80
|
+
|
81
|
+
asyncio.run(main())
|
82
|
+
```
|
83
|
+
|
84
|
+
---
|
85
|
+
|
86
|
+
### Working with Databases 🔥
|
87
|
+
|
88
|
+
```python
|
89
|
+
import asyncio
|
90
|
+
from notionary import NotionDatabase
|
91
|
+
|
92
|
+
async def main():
|
93
|
+
# Connect to database by name (fuzzy matching)
|
94
|
+
db = await NotionDatabase.from_database_name("Projects")
|
95
|
+
|
96
|
+
# Create a new page with properties
|
97
|
+
page = await db.create_blank_page()
|
98
|
+
await page.set_title("🆕 New Project Entry")
|
99
|
+
await page.set_property_value_by_name("Status", "In Progress")
|
100
|
+
await page.set_property_value_by_name("Priority", "High")
|
101
|
+
|
102
|
+
# find pages created in the last 7 days
|
103
|
+
count = 0
|
104
|
+
async for page in db.iter_pages_with_filter(
|
105
|
+
db.create_filter().with_created_last_n_days(7)
|
106
|
+
):
|
107
|
+
count += 1
|
108
|
+
print(f"{count:2d}. {page.emoji_icon or '📄'} {page.title}")
|
109
|
+
|
110
|
+
asyncio.run(main())
|
111
|
+
```
|
112
|
+
|
113
|
+
## Custom Markdown Syntax
|
114
|
+
|
115
|
+
Notionary extends standard Markdown with special syntax to support Notion-specific features:
|
116
|
+
|
117
|
+
### Text Formatting
|
118
|
+
|
119
|
+
- Standard: `**bold**`, `*italic*`, `~~strikethrough~~`, `` `code` ``
|
120
|
+
- Links: `[text](url)`
|
121
|
+
- Quotes: `> This is a quote`
|
122
|
+
- Divider: `---`
|
123
|
+
|
124
|
+
### Callouts
|
125
|
+
|
126
|
+
```markdown
|
127
|
+
!> [💡] This is a default callout with the light bulb emoji
|
128
|
+
!> [🔔] This is a notification with a bell emoji
|
129
|
+
!> [⚠️] Warning: This is an important note
|
130
|
+
```
|
131
|
+
|
132
|
+
### Toggles
|
133
|
+
|
134
|
+
```markdown
|
135
|
+
+++ How to use Notionary
|
136
|
+
| 1. Initialize with NotionPage
|
137
|
+
| 2. Update metadata with set_title(), set_emoji_icon(), etc.
|
138
|
+
| 3. Add content with replace_content() or append_markdown()
|
139
|
+
```
|
140
|
+
|
141
|
+
### Multi-Column Layout
|
142
|
+
|
143
|
+
```markdown
|
144
|
+
::: columns
|
145
|
+
::: column
|
146
|
+
|
147
|
+
## Left Column
|
148
|
+
|
149
|
+
- Item 1
|
150
|
+
- Item 2
|
151
|
+
- Item 3
|
152
|
+
:::
|
153
|
+
::: column
|
154
|
+
|
155
|
+
## Right Column
|
156
|
+
|
157
|
+
This text appears in the second column. Multi-column layouts are perfect for:
|
158
|
+
|
159
|
+
- Comparing features
|
160
|
+
- Creating side-by-side content
|
161
|
+
- Improving readability of wide content
|
162
|
+
:::
|
163
|
+
:::
|
164
|
+
```
|
165
|
+
|
166
|
+
### Code Blocks
|
167
|
+
|
168
|
+
```python
|
169
|
+
def hello_world():
|
170
|
+
print("Hello from Notionary!")
|
171
|
+
```
|
172
|
+
|
173
|
+
### To-do Lists
|
174
|
+
|
175
|
+
```markdown
|
176
|
+
- [ ] Define project scope
|
177
|
+
- [x] Create timeline
|
178
|
+
- [ ] Assign resources
|
179
|
+
```
|
180
|
+
|
181
|
+
### Tables
|
182
|
+
|
183
|
+
```markdown
|
184
|
+
| Feature | Status | Priority |
|
185
|
+
| --------------- | ----------- | -------- |
|
186
|
+
| API Integration | Complete | High |
|
187
|
+
| Documentation | In Progress | Medium |
|
188
|
+
```
|
189
|
+
|
190
|
+
### More Elements
|
191
|
+
|
192
|
+
```markdown
|
193
|
+

|
194
|
+
@[Caption](https://youtube.com/watch?v=...)
|
195
|
+
[bookmark](https://example.com "Title" "Description")
|
196
|
+
```
|
197
|
+
|
198
|
+
## Examples
|
199
|
+
|
200
|
+
Explore the `examples/` directory for comprehensive guides:
|
201
|
+
|
202
|
+
### 🚀 Core Examples
|
203
|
+
- [**Page Management**](examples/page_example.py) - Create, update, and manage Notion pages
|
204
|
+
- [**Page Operations**](examples/page.py) - Advanced page manipulation and content handling
|
205
|
+
- [**Database Operations**](examples/database.py) - Connect to and manage Notion databases
|
206
|
+
- [**Database Iteration**](examples/database_iteration.py) - Query and filter database entries
|
207
|
+
- [**Workspace Discovery**](examples/workspace_discovery.py) - Explore and discover your Notion workspace
|
208
|
+
|
209
|
+
### 📝 Markdown Examples
|
210
|
+
- [**Basic Formatting**](examples/markdown/basic.py) - Text formatting, lists, and basic elements
|
211
|
+
- [**Callouts**](examples/markdown/callout.py) - Create beautiful callout blocks with icons
|
212
|
+
- [**Toggles**](examples/markdown/toggle.py) - Collapsible content sections
|
213
|
+
- [**Multi-Column Layouts**](examples/markdown/columns.py) - Side-by-side content arrangement
|
214
|
+
- [**Code Blocks**](examples/markdown/code.py) - Syntax-highlighted code examples
|
215
|
+
- [**Tables**](examples/markdown/table.py) - Structured data presentation
|
216
|
+
- [**Media Embeds**](examples/markdown/embed.py) - Images, videos, and rich media
|
217
|
+
- [**Audio Content**](examples/markdown/audio.py) - Audio file integration
|
218
|
+
|
219
|
+
Each example is self-contained and demonstrates specific features with practical use cases.
|
220
|
+
|
221
|
+
## Contributing
|
222
|
+
|
223
|
+
Contributions welcome — feel free to submit a pull request!
|
224
|
+
|
@@ -0,0 +1,201 @@
|
|
1
|
+
<picture>
|
2
|
+
<source media="(prefers-color-scheme: dark)" srcset="./static/notionary-dark.png">
|
3
|
+
<source media="(prefers-color-scheme: light)" srcset="./static/notionary-light.png">
|
4
|
+
<img alt="Notionary logo: dark mode shows a white logo, light mode shows a black logo." src="./static/browser-use.png" width="full">
|
5
|
+
</picture>
|
6
|
+
|
7
|
+
<h1 align="center">Notion API simplified for Python developers 🐍</h1>
|
8
|
+
|
9
|
+
[](https://www.python.org/downloads/)
|
10
|
+
[](LICENSE)
|
11
|
+
|
12
|
+
- **Object-Oriented Design**: Clean, intuitive classes for Pages, Databases, and Workspaces with full CRUD operations
|
13
|
+
- **Rich Markdown to Notion**: Convert extended Markdown (callouts, toggles, columns) directly into beautiful Notion blocks
|
14
|
+
- **Smart Discovery**: Find pages and databases by name with fuzzy matching - no more hunting for URLs
|
15
|
+
- **Async-First Architecture**: Built for modern Python with full async/await support and high performance
|
16
|
+
- **AI-Ready Integration**: Generate LLM system prompts and let AI agents create Notion content seamlessly
|
17
|
+
|
18
|
+
---
|
19
|
+
|
20
|
+
# Quick start
|
21
|
+
```bash
|
22
|
+
pip install notionary
|
23
|
+
```
|
24
|
+
|
25
|
+
- Set up your Notion integration (notion.so/profile/integrations)
|
26
|
+
- Add your integration key in your `.env` file.
|
27
|
+
|
28
|
+
```bash
|
29
|
+
NOTION_SECRET=YOUR_INTEGRATION_KEY
|
30
|
+
```
|
31
|
+
|
32
|
+
### Creating and Managing Pages 🚀
|
33
|
+
```python
|
34
|
+
from notionary import NotionPage
|
35
|
+
|
36
|
+
async def main():
|
37
|
+
# Simpy find an existing page by its title
|
38
|
+
page = await NotionPage.from_page_name("My Test Page")
|
39
|
+
|
40
|
+
# Add rich content with custom Markdown
|
41
|
+
content = """
|
42
|
+
# 🚀 Generated with Notionary
|
43
|
+
|
44
|
+
!> [💡] This page was created programmatically!
|
45
|
+
|
46
|
+
## Features
|
47
|
+
- **Rich** Markdown support
|
48
|
+
- Database integration
|
49
|
+
- AI-ready content generation
|
50
|
+
|
51
|
+
+++ Click to see more details
|
52
|
+
| Notionary makes it easy to create beautiful Notion pages
|
53
|
+
| directly from Python code with intuitive Markdown syntax.
|
54
|
+
"""
|
55
|
+
|
56
|
+
await page.replace_content(content)
|
57
|
+
print(f"✅ Page updated: {page.url}")
|
58
|
+
|
59
|
+
asyncio.run(main())
|
60
|
+
```
|
61
|
+
|
62
|
+
---
|
63
|
+
|
64
|
+
### Working with Databases 🔥
|
65
|
+
|
66
|
+
```python
|
67
|
+
import asyncio
|
68
|
+
from notionary import NotionDatabase
|
69
|
+
|
70
|
+
async def main():
|
71
|
+
# Connect to database by name (fuzzy matching)
|
72
|
+
db = await NotionDatabase.from_database_name("Projects")
|
73
|
+
|
74
|
+
# Create a new page with properties
|
75
|
+
page = await db.create_blank_page()
|
76
|
+
await page.set_title("🆕 New Project Entry")
|
77
|
+
await page.set_property_value_by_name("Status", "In Progress")
|
78
|
+
await page.set_property_value_by_name("Priority", "High")
|
79
|
+
|
80
|
+
# find pages created in the last 7 days
|
81
|
+
count = 0
|
82
|
+
async for page in db.iter_pages_with_filter(
|
83
|
+
db.create_filter().with_created_last_n_days(7)
|
84
|
+
):
|
85
|
+
count += 1
|
86
|
+
print(f"{count:2d}. {page.emoji_icon or '📄'} {page.title}")
|
87
|
+
|
88
|
+
asyncio.run(main())
|
89
|
+
```
|
90
|
+
|
91
|
+
## Custom Markdown Syntax
|
92
|
+
|
93
|
+
Notionary extends standard Markdown with special syntax to support Notion-specific features:
|
94
|
+
|
95
|
+
### Text Formatting
|
96
|
+
|
97
|
+
- Standard: `**bold**`, `*italic*`, `~~strikethrough~~`, `` `code` ``
|
98
|
+
- Links: `[text](url)`
|
99
|
+
- Quotes: `> This is a quote`
|
100
|
+
- Divider: `---`
|
101
|
+
|
102
|
+
### Callouts
|
103
|
+
|
104
|
+
```markdown
|
105
|
+
!> [💡] This is a default callout with the light bulb emoji
|
106
|
+
!> [🔔] This is a notification with a bell emoji
|
107
|
+
!> [⚠️] Warning: This is an important note
|
108
|
+
```
|
109
|
+
|
110
|
+
### Toggles
|
111
|
+
|
112
|
+
```markdown
|
113
|
+
+++ How to use Notionary
|
114
|
+
| 1. Initialize with NotionPage
|
115
|
+
| 2. Update metadata with set_title(), set_emoji_icon(), etc.
|
116
|
+
| 3. Add content with replace_content() or append_markdown()
|
117
|
+
```
|
118
|
+
|
119
|
+
### Multi-Column Layout
|
120
|
+
|
121
|
+
```markdown
|
122
|
+
::: columns
|
123
|
+
::: column
|
124
|
+
|
125
|
+
## Left Column
|
126
|
+
|
127
|
+
- Item 1
|
128
|
+
- Item 2
|
129
|
+
- Item 3
|
130
|
+
:::
|
131
|
+
::: column
|
132
|
+
|
133
|
+
## Right Column
|
134
|
+
|
135
|
+
This text appears in the second column. Multi-column layouts are perfect for:
|
136
|
+
|
137
|
+
- Comparing features
|
138
|
+
- Creating side-by-side content
|
139
|
+
- Improving readability of wide content
|
140
|
+
:::
|
141
|
+
:::
|
142
|
+
```
|
143
|
+
|
144
|
+
### Code Blocks
|
145
|
+
|
146
|
+
```python
|
147
|
+
def hello_world():
|
148
|
+
print("Hello from Notionary!")
|
149
|
+
```
|
150
|
+
|
151
|
+
### To-do Lists
|
152
|
+
|
153
|
+
```markdown
|
154
|
+
- [ ] Define project scope
|
155
|
+
- [x] Create timeline
|
156
|
+
- [ ] Assign resources
|
157
|
+
```
|
158
|
+
|
159
|
+
### Tables
|
160
|
+
|
161
|
+
```markdown
|
162
|
+
| Feature | Status | Priority |
|
163
|
+
| --------------- | ----------- | -------- |
|
164
|
+
| API Integration | Complete | High |
|
165
|
+
| Documentation | In Progress | Medium |
|
166
|
+
```
|
167
|
+
|
168
|
+
### More Elements
|
169
|
+
|
170
|
+
```markdown
|
171
|
+

|
172
|
+
@[Caption](https://youtube.com/watch?v=...)
|
173
|
+
[bookmark](https://example.com "Title" "Description")
|
174
|
+
```
|
175
|
+
|
176
|
+
## Examples
|
177
|
+
|
178
|
+
Explore the `examples/` directory for comprehensive guides:
|
179
|
+
|
180
|
+
### 🚀 Core Examples
|
181
|
+
- [**Page Management**](examples/page_example.py) - Create, update, and manage Notion pages
|
182
|
+
- [**Page Operations**](examples/page.py) - Advanced page manipulation and content handling
|
183
|
+
- [**Database Operations**](examples/database.py) - Connect to and manage Notion databases
|
184
|
+
- [**Database Iteration**](examples/database_iteration.py) - Query and filter database entries
|
185
|
+
- [**Workspace Discovery**](examples/workspace_discovery.py) - Explore and discover your Notion workspace
|
186
|
+
|
187
|
+
### 📝 Markdown Examples
|
188
|
+
- [**Basic Formatting**](examples/markdown/basic.py) - Text formatting, lists, and basic elements
|
189
|
+
- [**Callouts**](examples/markdown/callout.py) - Create beautiful callout blocks with icons
|
190
|
+
- [**Toggles**](examples/markdown/toggle.py) - Collapsible content sections
|
191
|
+
- [**Multi-Column Layouts**](examples/markdown/columns.py) - Side-by-side content arrangement
|
192
|
+
- [**Code Blocks**](examples/markdown/code.py) - Syntax-highlighted code examples
|
193
|
+
- [**Tables**](examples/markdown/table.py) - Structured data presentation
|
194
|
+
- [**Media Embeds**](examples/markdown/embed.py) - Images, videos, and rich media
|
195
|
+
- [**Audio Content**](examples/markdown/audio.py) - Audio file integration
|
196
|
+
|
197
|
+
Each example is self-contained and demonstrates specific features with practical use cases.
|
198
|
+
|
199
|
+
## Contributing
|
200
|
+
|
201
|
+
Contributions welcome — feel free to submit a pull request!
|
@@ -194,7 +194,7 @@ class BaseNotionClient(LoggingMixin, ABC):
|
|
194
194
|
token = next(
|
195
195
|
(
|
196
196
|
os.getenv(var)
|
197
|
-
for var in ("NOTION_SECRET", "
|
197
|
+
for var in ("NOTION_SECRET", "NOTION_INTEGRATION_KEY", "NOTION_TOKEN")
|
198
198
|
if os.getenv(var)
|
199
199
|
),
|
200
200
|
None,
|
@@ -8,6 +8,12 @@ from notionary.page.markdown_syntax_prompt_generator import (
|
|
8
8
|
from notionary.blocks.text_inline_formatter import TextInlineFormatter
|
9
9
|
|
10
10
|
from notionary.blocks import NotionBlockElement
|
11
|
+
from notionary.telemetry import (
|
12
|
+
ProductTelemetry,
|
13
|
+
NotionMarkdownSyntaxPromptEvent,
|
14
|
+
MarkdownToNotionConversionEvent,
|
15
|
+
NotionToMarkdownConversionEvent,
|
16
|
+
)
|
11
17
|
|
12
18
|
|
13
19
|
class BlockRegistry:
|
@@ -28,6 +34,8 @@ class BlockRegistry:
|
|
28
34
|
for element in elements:
|
29
35
|
self.register(element)
|
30
36
|
|
37
|
+
self.telemetry = ProductTelemetry()
|
38
|
+
|
31
39
|
def register(self, element_class: Type[NotionBlockElement]) -> bool:
|
32
40
|
"""
|
33
41
|
Register an element class.
|
@@ -57,13 +65,13 @@ class BlockRegistry:
|
|
57
65
|
|
58
66
|
def contains(self, element_class: Type[NotionBlockElement]) -> bool:
|
59
67
|
"""
|
60
|
-
|
68
|
+
Checks if a specific element is contained in the registry.
|
61
69
|
|
62
70
|
Args:
|
63
|
-
element_class:
|
71
|
+
element_class: The element class to check.
|
64
72
|
|
65
73
|
Returns:
|
66
|
-
bool: True
|
74
|
+
bool: True if the element is contained, otherwise False.
|
67
75
|
"""
|
68
76
|
return element_class in self._elements
|
69
77
|
|
@@ -77,14 +85,28 @@ class BlockRegistry:
|
|
77
85
|
def markdown_to_notion(self, text: str) -> Optional[Dict[str, Any]]:
|
78
86
|
"""Convert markdown to Notion block using registered elements."""
|
79
87
|
handler = self.find_markdown_handler(text)
|
88
|
+
|
80
89
|
if handler:
|
90
|
+
self.telemetry.capture(
|
91
|
+
MarkdownToNotionConversionEvent(
|
92
|
+
handler_element_name=handler.__name__,
|
93
|
+
)
|
94
|
+
)
|
95
|
+
|
81
96
|
return handler.markdown_to_notion(text)
|
82
97
|
return None
|
83
98
|
|
84
99
|
def notion_to_markdown(self, block: Dict[str, Any]) -> Optional[str]:
|
85
100
|
"""Convert Notion block to markdown using registered elements."""
|
86
101
|
handler = self._find_notion_handler(block)
|
102
|
+
|
87
103
|
if handler:
|
104
|
+
self.telemetry.capture(
|
105
|
+
NotionToMarkdownConversionEvent(
|
106
|
+
handler_element_name=handler.__name__,
|
107
|
+
)
|
108
|
+
)
|
109
|
+
|
88
110
|
return handler.notion_to_markdown(block)
|
89
111
|
return None
|
90
112
|
|
@@ -106,6 +128,8 @@ class BlockRegistry:
|
|
106
128
|
if "TextInlineFormatter" not in formatter_names:
|
107
129
|
element_classes = element_classes + [TextInlineFormatter]
|
108
130
|
|
131
|
+
self.telemetry.capture(NotionMarkdownSyntaxPromptEvent())
|
132
|
+
|
109
133
|
return MarkdownSyntaxPromptGenerator.generate_system_prompt(element_classes)
|
110
134
|
|
111
135
|
def _find_notion_handler(
|