Zettelkasten(title: str, n_type: str, url: Optional[str] = None, tags: Optional[list] = None, aliases: Optional[list] = None, **kwargs)
Bases: MarkdownDocument
Zettelkasten note with mandatory front matter (title, type, tags, and related fields).
Supported type values are fleeting, literature, permanent, and atom.
Examples:
>>> note = Zettelkasten(title="Cache eviction", n_type="atom", tags=["memory"])
>>> note.title
'Cache eviction'
>>> note.type
'atom'
Initialize a Zettelkasten object.
Parameters:
-
title
(str)
–
-
n_type
(str)
–
The type of the note, only support 'fleeting', 'literature', 'permanent' and 'atom'.
-
url
(str, default:
None
)
–
-
tags
(list, default:
None
)
–
-
aliases
(list, default:
None
)
–
Alternate titles for the note.
Examples:
>>> note = Zettelkasten(title="Cache eviction", n_type="permanent")
>>> note.tags
[]
Source code in ures/markdown/zettelkasten.py
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 | def __init__(
self,
title: str,
n_type: str,
url: Optional[str] = None,
tags: Optional[list] = None,
aliases: Optional[list] = None,
**kwargs,
):
"""
Initialize a Zettelkasten object.
Args:
title (str): The title of the note.
n_type (str): The type of the note, only support 'fleeting', 'literature', 'permanent' and 'atom'.
url (str): The url of the note.
tags (list): The tags of the note.
aliases (list): Alternate titles for the note.
Examples:
>>> note = Zettelkasten(title="Cache eviction", n_type="permanent")
>>> note.tags
[]
"""
if not isinstance(title, str) or not title.strip():
raise ValueError("Title must be a non-empty string.")
if n_type not in self.ALLOWED_TYPES:
raise ValueError(
f"Invalid type '{n_type}'. Allowed types are: {', '.join(self.ALLOWED_TYPES)}."
)
if url is not None and not isinstance(url, str):
raise ValueError("URL must be a string.")
if tags is not None and not isinstance(tags, list):
raise ValueError("Tags must be a list.")
if aliases is not None and not isinstance(aliases, list):
raise ValueError("Aliases must be a list.")
_metadata = {
"title": title,
"type": n_type,
"url": url or "",
"tags": tags or [],
"aliases": aliases or [],
"id": zettelkasten_id(),
"create": time_now(),
}
if len(kwargs) > 0:
_metadata.update(kwargs)
super().__init__(metadata=_metadata)
|
from_file
classmethod
from_file(file_path: str) -> Union[MarkdownDocument, Zettelkasten]
Creates a MarkdownDocument instance by loading a Markdown file.
Parameters:
-
file_path
(str)
–
The path to the Markdown file.
Returns:
Raises:
-
FileNotFoundError
–
If the specified file does not exist.
-
InvalidFrontMatterError
–
If the front matter is malformed.
Source code in ures/markdown/zettelkasten.py
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113 | @classmethod
def from_file(cls, file_path: str) -> Union["MarkdownDocument", "Zettelkasten"]:
"""
Creates a MarkdownDocument instance by loading a Markdown file.
Args:
file_path (str): The path to the Markdown file.
Returns:
MarkdownDocument: An instance representing the loaded Markdown file.
Raises:
FileNotFoundError: If the specified file does not exist.
frontmatter.InvalidFrontMatterError: If the front matter is malformed.
"""
if not os.path.isfile(file_path):
raise FileNotFoundError(f"The file '{file_path}' does not exist.")
with open(file_path, "r", encoding="utf-8") as f:
post = frontmatter.load(f)
_params = dict(post.metadata)
n_type = _params.get("type", None)
if n_type is not None:
del _params["type"]
_params["n_type"] = n_type
keywords = ["title", "n_type", "url", "tags", "aliases"]
for keyword in keywords:
if keyword not in _params.keys():
_params[keyword] = None
zk = cls(
**_params,
)
# zk.metadata["id"] = post.metadata.get("id", zk.metadata["id"])
# zk.metadata["create"] = post.metadata.get("create", zk.metadata["create"])
zk.add_content(post.content)
return zk
|
to_llm_friendly_content
to_llm_friendly_content(prop_ignores: Optional[list] = None, context: Optional[Content] = None) -> Content
Generates an LLM-friendly representation of the note, filtering metadata and merging context.
This method creates a structured content object designed for LLM consumption. It first
adds a 'Metadata' section (filtering out specified keys), then appends the note's
main body, and finally merges any external context provided.
Parameters:
-
prop_ignores
(Optional[List[str]], default:
None
)
–
A list of metadata keys to exclude from the output.
Defaults to None. The keys "aliases", "url", "id", and "title" are always ignored
by default.
-
context
(Optional[Content], default:
None
)
–
Additional contextual content to append to the note.
Defaults to None.
Returns:
-
Content ( Content
) –
A new Content object organized into 'Metadata', 'Main Content', and
-
Content
–
optionally 'Context' sections.
Source code in ures/markdown/zettelkasten.py
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249 | def to_llm_friendly_content(
self, prop_ignores: Optional[list] = None, context: Optional[Content] = None
) -> Content:
"""Generates an LLM-friendly representation of the note, filtering metadata and merging context.
This method creates a structured content object designed for LLM consumption. It first
adds a 'Metadata' section (filtering out specified keys), then appends the note's
main body, and finally merges any external context provided.
Args:
prop_ignores (Optional[List[str]]): A list of metadata keys to exclude from the output.
Defaults to None. The keys "aliases", "url", "id", and "title" are always ignored
by default.
context (Optional[Content]): Additional contextual content to append to the note.
Defaults to None.
Returns:
Content: A new Content object organized into 'Metadata', 'Main Content', and
optionally 'Context' sections.
"""
properties = self.metadata
content = Content()
# Create a new section for metadata
properties_ignore_list = ["aliases", "url", "id", "title"]
if prop_ignores:
properties_ignore_list.extend(prop_ignores)
for key, value in properties.items():
if key not in properties_ignore_list:
if isinstance(value, list):
value = ", ".join(value)
else:
value = str(value)
content.add_content(
content=f"**{key}**: {value}",
section_title="Metadata",
section_level=1,
)
# Merge all existing sections into the main body
body_title = "Main Content"
body_level = 1
for key, value in self.parse_content().sections.items():
content.add_content(
content=f"**{key}**:",
section_title=body_title,
section_level=body_level,
)
content.add_content(
content=value.content,
section_title=body_title,
section_level=body_level,
)
# If context is provided, merge it
if context:
context_title = "Context"
context_level = 2
for key, value in context.sections.items():
content.add_content(
content=f"**{key}**:",
section_title=context_title,
section_level=context_level,
)
content.add_content(
content=value.content,
section_title=context_title,
section_level=context_level,
)
return content
|