convoviz 0.2.10__tar.gz → 0.2.12__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.
Files changed (61) hide show
  1. {convoviz-0.2.10 → convoviz-0.2.12}/PKG-INFO +5 -8
  2. {convoviz-0.2.10 → convoviz-0.2.12}/README.md +4 -7
  3. convoviz-0.2.12/convoviz/assets/stopwords.txt +1 -0
  4. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/renderers/markdown.py +62 -2
  5. {convoviz-0.2.10 → convoviz-0.2.12}/pyproject.toml +1 -1
  6. convoviz-0.2.10/convoviz/assets/stopwords.txt +0 -75
  7. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/__init__.py +0 -0
  8. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/__main__.py +0 -0
  9. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/analysis/__init__.py +0 -0
  10. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/analysis/graphs.py +0 -0
  11. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/analysis/wordcloud.py +0 -0
  12. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/colormaps.txt +0 -0
  13. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/AmaticSC-Regular.ttf +0 -0
  14. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/ArchitectsDaughter-Regular.ttf +0 -0
  15. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/BebasNeue-Regular.ttf +0 -0
  16. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/Borel-Regular.ttf +0 -0
  17. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/Courgette-Regular.ttf +0 -0
  18. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/CroissantOne-Regular.ttf +0 -0
  19. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/Handjet-Regular.ttf +0 -0
  20. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/IndieFlower-Regular.ttf +0 -0
  21. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/Kalam-Regular.ttf +0 -0
  22. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/Lobster-Regular.ttf +0 -0
  23. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/MartianMono-Regular.ttf +0 -0
  24. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/MartianMono-Thin.ttf +0 -0
  25. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/Montserrat-Regular.ttf +0 -0
  26. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/Mooli-Regular.ttf +0 -0
  27. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/Pacifico-Regular.ttf +0 -0
  28. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/PlayfairDisplay-Regular.ttf +0 -0
  29. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/Raleway-Regular.ttf +0 -0
  30. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/RobotoMono-Regular.ttf +0 -0
  31. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/RobotoMono-Thin.ttf +0 -0
  32. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/RobotoSlab-Regular.ttf +0 -0
  33. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/RobotoSlab-Thin.ttf +0 -0
  34. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/Ruwudu-Regular.ttf +0 -0
  35. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/Sacramento-Regular.ttf +0 -0
  36. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/SedgwickAveDisplay-Regular.ttf +0 -0
  37. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/ShadowsIntoLight-Regular.ttf +0 -0
  38. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/TitilliumWeb-Regular.ttf +0 -0
  39. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/Yellowtail-Regular.ttf +0 -0
  40. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/YsabeauOffice-Regular.ttf +0 -0
  41. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/YsabeauSC-Regular.ttf +0 -0
  42. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/YsabeauSC-Thin.ttf +0 -0
  43. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/assets/fonts/Zeyada-Regular.ttf +0 -0
  44. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/cli.py +0 -0
  45. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/config.py +0 -0
  46. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/exceptions.py +0 -0
  47. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/interactive.py +0 -0
  48. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/io/__init__.py +0 -0
  49. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/io/assets.py +0 -0
  50. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/io/loaders.py +0 -0
  51. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/io/writers.py +0 -0
  52. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/models/__init__.py +0 -0
  53. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/models/collection.py +0 -0
  54. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/models/conversation.py +0 -0
  55. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/models/message.py +0 -0
  56. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/models/node.py +0 -0
  57. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/pipeline.py +0 -0
  58. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/py.typed +0 -0
  59. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/renderers/__init__.py +0 -0
  60. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/renderers/yaml.py +0 -0
  61. {convoviz-0.2.10 → convoviz-0.2.12}/convoviz/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: convoviz
3
- Version: 0.2.10
3
+ Version: 0.2.12
4
4
  Summary: Get analytics and visualizations on your ChatGPT data!
5
5
  Keywords: markdown,chatgpt,openai,visualization,analytics,json,export,data-analysis,obsidian
6
6
  Author: Mohamed Cheikh Sidiya
@@ -124,7 +124,10 @@ And if you've had a great experience, consider giving the project a star ⭐. It
124
124
 
125
125
  ## Notes
126
126
 
127
- This is just a small thing I coded to help me see my convos in beautiful markdown. It was originally built with [Obsidian](https://obsidian.md/) (my go-to note-taking app) in mind, but the default output is standard Markdown (and you can choose an Obsidian-flavored mode in the interactive config if you want block IDs / navigation links).
127
+ This is just a small thing I coded to help me see my convos in beautiful markdown. It was originally built with [Obsidian](https://obsidian.md/) (my go-to note-taking app) in mind, but the default output is standard Markdown.
128
+
129
+ You can choose obsidian flavored md in the cli to get extra features like:
130
+ - model reasoning (`reasoning_recap`, `thoughts`) rendered as collapsible `> [!NOTE]-` callouts instead of being hidden.
128
131
 
129
132
  I wasn't a fan of the clunky, and sometimes paid, browser extensions.
130
133
 
@@ -136,12 +139,6 @@ It should(?) also work as library, so you can import and use the models and func
136
139
 
137
140
  Convoviz uses NLTK stopwords for word clouds. If you’re offline and NLTK data isn’t already installed, pre-download it once:
138
141
 
139
- ```bash
140
- python -c "import nltk; nltk.download('stopwords')"
141
- ```
142
-
143
- If you’re using `uv` without a global install, you can run:
144
-
145
142
  ```bash
146
143
  uv run python -c "import nltk; nltk.download('stopwords')"
147
144
  ```
@@ -98,7 +98,10 @@ And if you've had a great experience, consider giving the project a star ⭐. It
98
98
 
99
99
  ## Notes
100
100
 
101
- This is just a small thing I coded to help me see my convos in beautiful markdown. It was originally built with [Obsidian](https://obsidian.md/) (my go-to note-taking app) in mind, but the default output is standard Markdown (and you can choose an Obsidian-flavored mode in the interactive config if you want block IDs / navigation links).
101
+ This is just a small thing I coded to help me see my convos in beautiful markdown. It was originally built with [Obsidian](https://obsidian.md/) (my go-to note-taking app) in mind, but the default output is standard Markdown.
102
+
103
+ You can choose obsidian flavored md in the cli to get extra features like:
104
+ - model reasoning (`reasoning_recap`, `thoughts`) rendered as collapsible `> [!NOTE]-` callouts instead of being hidden.
102
105
 
103
106
  I wasn't a fan of the clunky, and sometimes paid, browser extensions.
104
107
 
@@ -110,12 +113,6 @@ It should(?) also work as library, so you can import and use the models and func
110
113
 
111
114
  Convoviz uses NLTK stopwords for word clouds. If you’re offline and NLTK data isn’t already installed, pre-download it once:
112
115
 
113
- ```bash
114
- python -c "import nltk; nltk.download('stopwords')"
115
- ```
116
-
117
- If you’re using `uv` without a global install, you can run:
118
-
119
116
  ```bash
120
117
  uv run python -c "import nltk; nltk.download('stopwords')"
121
118
  ```
@@ -62,6 +62,32 @@ def code_block(text: str, lang: str = "python") -> str:
62
62
  return f"```{lang}\n{text}\n```"
63
63
 
64
64
 
65
+ def render_obsidian_callout(
66
+ content: str,
67
+ title: str,
68
+ callout_type: str = "NOTE",
69
+ collapsed: bool = True,
70
+ ) -> str:
71
+ """Render content as an Obsidian collapsible callout.
72
+
73
+ Syntax: > [!TYPE]+/- Title
74
+ This is Obsidian-specific; on GitHub/standard markdown it renders as a blockquote.
75
+
76
+ Args:
77
+ content: The content to wrap
78
+ title: The callout title
79
+ callout_type: The callout type (NOTE, TIP, WARNING, etc.)
80
+ collapsed: Whether to default to collapsed (-) or expanded (+)
81
+
82
+ Returns:
83
+ Markdown callout string
84
+ """
85
+ fold = "-" if collapsed else "+"
86
+ lines = content.strip().split("\n")
87
+ quoted_lines = [f"> {line}" for line in lines]
88
+ return f"> [!{callout_type}]{fold} {title}\n" + "\n".join(quoted_lines)
89
+
90
+
65
91
  def render_message_header(role: str, headers: AuthorHeaders) -> str:
66
92
  """Get the markdown header for a message author.
67
93
 
@@ -97,11 +123,20 @@ def render_node_header(node: Node, headers: AuthorHeaders) -> str:
97
123
  return render_message_header(node.message.author.role, headers) + "\n"
98
124
 
99
125
 
126
+ # Content types that can be rendered as collapsible callouts in Obsidian
127
+ OBSIDIAN_COLLAPSIBLE_TYPES: dict[str, tuple[str, str]] = {
128
+ # content_type: (callout_type, title)
129
+ "reasoning_recap": ("NOTE", "🧠 AI Reasoning"),
130
+ "thoughts": ("NOTE", "💭 AI Thoughts"),
131
+ }
132
+
133
+
100
134
  def render_node(
101
135
  node: Node,
102
136
  headers: AuthorHeaders,
103
137
  use_dollar_latex: bool = False,
104
138
  asset_resolver: Callable[[str], str | None] | None = None,
139
+ flavor: str = "standard",
105
140
  ) -> str:
106
141
  """Render a complete node as markdown.
107
142
 
@@ -110,6 +145,7 @@ def render_node(
110
145
  headers: Configuration for author headers
111
146
  use_dollar_latex: Whether to convert LaTeX delimiters to dollars
112
147
  asset_resolver: Function to resolve asset IDs to paths
148
+ flavor: Markdown flavor ("standard" or "obsidian")
113
149
 
114
150
  Returns:
115
151
  Complete markdown string for the node
@@ -117,6 +153,26 @@ def render_node(
117
153
  if node.message is None:
118
154
  return ""
119
155
 
156
+ content_type = node.message.content.content_type
157
+
158
+ # For Obsidian flavor, render certain hidden types as collapsible callouts
159
+ # No separator (---) since these are visually distinct and may appear consecutively
160
+ if flavor == "obsidian" and content_type in OBSIDIAN_COLLAPSIBLE_TYPES:
161
+ try:
162
+ text = node.message.text
163
+ except MessageContentError:
164
+ text = ""
165
+
166
+ if text.strip():
167
+ callout_type, title = OBSIDIAN_COLLAPSIBLE_TYPES[content_type]
168
+ callout = render_obsidian_callout(
169
+ content=text,
170
+ title=title,
171
+ callout_type=callout_type,
172
+ collapsed=True,
173
+ )
174
+ return f"\n{callout}\n"
175
+
120
176
  if node.message.is_hidden:
121
177
  return ""
122
178
 
@@ -194,7 +250,7 @@ def render_conversation(
194
250
  Complete markdown document string
195
251
  """
196
252
  use_dollar_latex = config.markdown.latex_delimiters == "dollars"
197
- # Note: config.markdown.flavor is available for future obsidian-specific features
253
+ flavor = config.markdown.flavor
198
254
 
199
255
  # Start with YAML header
200
256
  markdown = render_yaml_header(conversation, config.yaml)
@@ -203,7 +259,11 @@ def render_conversation(
203
259
  for node in _ordered_nodes(conversation):
204
260
  if node.message:
205
261
  markdown += render_node(
206
- node, headers, use_dollar_latex, asset_resolver=asset_resolver
262
+ node,
263
+ headers,
264
+ use_dollar_latex,
265
+ asset_resolver=asset_resolver,
266
+ flavor=flavor,
207
267
  )
208
268
 
209
269
  return markdown
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "convoviz"
3
- version = "0.2.10"
3
+ version = "0.2.12"
4
4
  description = "Get analytics and visualizations on your ChatGPT data!"
5
5
  license = "MIT"
6
6
  keywords = [
@@ -1,75 +0,0 @@
1
- # Python
2
- def
3
- class
4
- import
5
- from
6
- as
7
- elif
8
- finally
9
- yield
10
- pass
11
- lambda
12
- async
13
- await
14
- nonlocal
15
- assert
16
- self
17
- cls
18
- # JavaScript / TypeScript
19
- const
20
- let
21
- var
22
- function
23
- export
24
- default
25
- extends
26
- implements
27
- static
28
- # Java / C#
29
- final
30
- abstract
31
- new
32
- super
33
- package
34
- throws
35
- synchronized
36
- volatile
37
- transient
38
- native
39
- strictfp
40
- override
41
- # C / C++
42
- unsigned
43
- signed
44
- typedef
45
- sizeof
46
- extern
47
- register
48
- restrict
49
- inline
50
- template
51
- typename
52
- virtual
53
- friend
54
- mutable
55
- explicit
56
- operator
57
- typeid
58
- # Rust
59
- mut
60
- fn
61
- pub
62
- mod
63
- trait
64
- impl
65
- where
66
- loop
67
- unsafe
68
- crate
69
- dyn
70
- # Go
71
- func
72
- chan
73
- defer
74
- fallthrough
75
- goto
File without changes
File without changes
File without changes
File without changes