markrender 1.0.7__tar.gz → 1.1.1__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 (67) hide show
  1. markrender-1.1.1/.gitignore +74 -0
  2. {markrender-1.0.7 → markrender-1.1.1}/LICENSE +21 -21
  3. markrender-1.1.1/MANIFEST.in +2 -0
  4. markrender-1.1.1/PKG-INFO +491 -0
  5. markrender-1.1.1/README.md +459 -0
  6. markrender-1.1.1/check_truecolor.py +30 -0
  7. markrender-1.1.1/examples/basic_usage.py +76 -0
  8. markrender-1.1.1/examples/complete_showcase.py +176 -0
  9. markrender-1.1.1/examples/definition_lists.py +82 -0
  10. markrender-1.1.1/examples/footnotes.py +83 -0
  11. markrender-1.1.1/examples/highlights.py +86 -0
  12. markrender-1.1.1/examples/link_highlighting.py +67 -0
  13. markrender-1.1.1/examples/mermaid_diagrams.py +91 -0
  14. markrender-1.1.1/examples/new_features_demo.py +188 -0
  15. markrender-1.1.1/examples/progress_bars.py +94 -0
  16. markrender-1.1.1/examples/streaming_demo.py +134 -0
  17. markrender-1.1.1/examples/theme_showcase.py +60 -0
  18. markrender-1.1.1/examples/v1_0_7_showcase.py +103 -0
  19. markrender-1.1.1/markrender/__init__.py +22 -0
  20. markrender-1.0.7/markrender/cli.py → markrender-1.1.1/markrender/__main__.py +75 -69
  21. markrender-1.1.1/markrender/_version.py +24 -0
  22. markrender-1.1.1/markrender/cli.py +11 -0
  23. markrender-1.1.1/markrender/colors.py +229 -0
  24. {markrender-1.0.7 → markrender-1.1.1}/markrender/config.py +11 -6
  25. markrender-1.1.1/markrender/formatters.py +339 -0
  26. markrender-1.1.1/markrender/parser.py +193 -0
  27. markrender-1.1.1/markrender/renderer.py +449 -0
  28. {markrender-1.0.7 → markrender-1.1.1}/markrender/themes.py +65 -70
  29. markrender-1.1.1/markrender.egg-info/PKG-INFO +491 -0
  30. markrender-1.1.1/markrender.egg-info/SOURCES.txt +45 -0
  31. markrender-1.1.1/markrender.egg-info/entry_points.txt +2 -0
  32. markrender-1.1.1/markrender.egg-info/requires.txt +9 -0
  33. markrender-1.1.1/markrender.egg-info/scm_file_list.json +44 -0
  34. {markrender-1.0.7 → markrender-1.1.1}/pyproject.toml +24 -10
  35. markrender-1.1.1/requirements.txt +3 -0
  36. {markrender-1.0.7 → markrender-1.1.1}/setup.cfg +4 -4
  37. markrender-1.1.1/setup.py +2 -0
  38. markrender-1.1.1/test.md +624 -0
  39. markrender-1.1.1/tests/test_colors.py +196 -0
  40. markrender-1.1.1/tests/test_dim_mode.py +119 -0
  41. markrender-1.1.1/tests/test_formatters.py +369 -0
  42. markrender-1.1.1/tests/test_parser.py +311 -0
  43. markrender-1.1.1/tests/test_regressions.py +308 -0
  44. markrender-1.1.1/tests/test_renderer.py +622 -0
  45. markrender-1.1.1/tests/test_versioning.py +119 -0
  46. markrender-1.0.7/PKG-INFO +0 -568
  47. markrender-1.0.7/README.md +0 -535
  48. markrender-1.0.7/markrender/__init__.py +0 -21
  49. markrender-1.0.7/markrender/colors.py +0 -195
  50. markrender-1.0.7/markrender/formatters.py +0 -1131
  51. markrender-1.0.7/markrender/parser.py +0 -921
  52. markrender-1.0.7/markrender/renderer.py +0 -640
  53. markrender-1.0.7/markrender.egg-info/PKG-INFO +0 -568
  54. markrender-1.0.7/markrender.egg-info/SOURCES.txt +0 -26
  55. markrender-1.0.7/markrender.egg-info/entry_points.txt +0 -2
  56. markrender-1.0.7/markrender.egg-info/requires.txt +0 -11
  57. markrender-1.0.7/tests/test_emoji_note.py +0 -27
  58. markrender-1.0.7/tests/test_enhancements.py +0 -100
  59. markrender-1.0.7/tests/test_formatters.py +0 -121
  60. markrender-1.0.7/tests/test_inline_formatting_contexts.py +0 -44
  61. markrender-1.0.7/tests/test_new_features.py +0 -365
  62. markrender-1.0.7/tests/test_parser.py +0 -116
  63. markrender-1.0.7/tests/test_renderer.py +0 -277
  64. markrender-1.0.7/tests/test_renderer_edge_cases.py +0 -137
  65. markrender-1.0.7/tests/test_v1_0_5_features.py +0 -233
  66. {markrender-1.0.7 → markrender-1.1.1}/markrender.egg-info/dependency_links.txt +0 -0
  67. {markrender-1.0.7 → markrender-1.1.1}/markrender.egg-info/top_level.txt +0 -0
@@ -0,0 +1,74 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ pip-wheel-metadata/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+
30
+ # PyInstaller
31
+ *.manifest
32
+ *.spec
33
+
34
+ # Unit test / coverage reports
35
+ htmlcov/
36
+ .tox/
37
+ .nox/
38
+ .coverage
39
+ .coverage.*
40
+ .cache
41
+ nosetests.xml
42
+ coverage.xml
43
+ *.cover
44
+ *.py,cover
45
+ .hypothesis/
46
+ .pytest_cache/
47
+
48
+ # Virtual environments
49
+ venv/
50
+ ENV/
51
+ env/
52
+ .venv
53
+
54
+ # IDEs
55
+ .vscode/
56
+ .idea/
57
+ *.swp
58
+ *.swo
59
+ *~
60
+
61
+ # OS
62
+ .DS_Store
63
+ Thumbs.db
64
+
65
+ # Project specific
66
+ *.log
67
+ .ruff_cache/
68
+ markrender/_version.py
69
+
70
+
71
+ # test files
72
+ test_all_fixes.py
73
+ test_emoji.py
74
+ test_simple.py
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Praneeth Gandodi
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Praneeth Gandodi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ # CI configuration is not needed in the source distribution.
2
+ prune .github
@@ -0,0 +1,491 @@
1
+ Metadata-Version: 2.4
2
+ Name: markrender
3
+ Version: 1.1.1
4
+ Summary: Professional terminal markdown renderer for streaming LLM responses
5
+ Author: Praneeth Gandodi
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/Praneeth-Gandodi/markrender
8
+ Project-URL: Documentation, https://github.com/Praneeth-Gandodi/markrender#readme
9
+ Project-URL: Repository, https://github.com/Praneeth-Gandodi/markrender
10
+ Project-URL: Bug Tracker, https://github.com/Praneeth-Gandodi/markrender/issues
11
+ Keywords: markdown,terminal,rendering,streaming,llm,cli
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.7
17
+ Classifier: Programming Language :: Python :: 3.8
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Requires-Python: >=3.7
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: pygments>=2.7.0
26
+ Requires-Dist: emoji>=2.8.0
27
+ Requires-Dist: tomli>=2.0.0; python_version < "3.11"
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest>=6.0.0; extra == "dev"
30
+ Requires-Dist: pytest-cov>=2.10.0; extra == "dev"
31
+ Dynamic: license-file
32
+
33
+ # MarkRender
34
+
35
+ **Professional Terminal Markdown Renderer for Streaming LLM Responses**
36
+
37
+ MarkRender renders markdown in the terminal. It is built for streaming output, so you can hand it a complete string or feed it chunks from an LLM as they arrive. Syntax highlighting, themes, tables, and the rest work the same either way, without reprinting content that is already on screen.
38
+
39
+ ## Features
40
+
41
+ - **Streaming Support** - Designed for chunk-by-chunk LLM response rendering
42
+ - **7 Themes** - github-dark, monokai, dracula, nord, one-dark, solarized-dark, solarized-light
43
+ - **Syntax Highlighting** - Powered by Pygments with 500+ languages
44
+ - **Dim Mode** - Render "thinking" content in a single muted gray
45
+ - **Theme Preview** - Preview all themes with sample content via CLI
46
+ - **Line Numbers** - Optional line numbers in code blocks
47
+ - **Tables** - Table rendering with borders and overflow truncation
48
+ - **Checkboxes** - Task list support
49
+ - **Emoji Support** - Converts `:emoji_name:` to actual emojis
50
+ - **Links** - Styled hyperlinks with URLs
51
+ - **Full Markdown** - Headings, lists, blockquotes, horizontal rules, alerts, and more
52
+ - **Force Color** - Force color output even in non-tty terminals
53
+ - **Customizable** - Custom colors, backgrounds, and formatting options
54
+ - **Python 3.7+** - Compatible with Python 3.7 and above
55
+
56
+ ## Installation
57
+
58
+ MarkRender is on PyPI:
59
+
60
+ ```bash
61
+ pip install markrender
62
+ ```
63
+
64
+ That installs the library and the `markrender` command. Check that it worked:
65
+
66
+ ```bash
67
+ markrender --version
68
+ ```
69
+
70
+ Upgrade an existing install with:
71
+
72
+ ```bash
73
+ pip install --upgrade markrender
74
+ ```
75
+
76
+ If you want to work on MarkRender itself, clone the repo and install it in editable mode instead:
77
+
78
+ ```bash
79
+ git clone https://github.com/Praneeth-Gandodi/markrender.git
80
+ cd markrender
81
+ pip install -e ".[dev]"
82
+ ```
83
+
84
+ ## Command Line
85
+
86
+ Render a file:
87
+
88
+ ```bash
89
+ markrender README.md
90
+ ```
91
+
92
+ Read markdown from stdin:
93
+
94
+ ```bash
95
+ cat notes.md | markrender
96
+ ```
97
+
98
+ On PowerShell:
99
+
100
+ ```powershell
101
+ Get-Content notes.md -Raw | markrender
102
+ ```
103
+
104
+ Pick a theme:
105
+
106
+ ```bash
107
+ markrender --theme dracula notes.md
108
+ ```
109
+
110
+ Adjust code blocks:
111
+
112
+ ```bash
113
+ markrender --no-line-numbers notes.md
114
+ markrender --code-background notes.md
115
+ markrender --no-stream-code notes.md
116
+ ```
117
+
118
+ Set a fixed width when the terminal reports the wrong size, or when the output goes somewhere else:
119
+
120
+ ```bash
121
+ markrender --width 80 notes.md
122
+ ```
123
+
124
+ Force color when piping into another program, a log file, or CI:
125
+
126
+ ```bash
127
+ markrender --force-color notes.md | less -R
128
+ ```
129
+
130
+ List the theme names:
131
+
132
+ ```bash
133
+ markrender --list-themes
134
+ ```
135
+
136
+ Preview every theme with sample content:
137
+
138
+ ```bash
139
+ markrender --preview-themes
140
+ ```
141
+
142
+ Running `markrender` with no file and nothing piped in prints an error and exits.
143
+
144
+ ### Options
145
+
146
+ | Option | Description |
147
+ |--------|-------------|
148
+ | `--theme NAME` | Color theme (default: `github-dark`) |
149
+ | `--no-line-numbers` | Hide line numbers in code blocks |
150
+ | `--code-background` | Show a background behind code blocks |
151
+ | `--width N` | Wrap at a fixed width instead of the terminal width |
152
+ | `--no-stream-code` | Render code blocks in one pass instead of line by line |
153
+ | `--force-color` | Emit colors even when the output is not a terminal |
154
+ | `--list-themes` | Print available themes and exit |
155
+ | `--preview-themes` | Render sample markdown in every theme and exit |
156
+ | `-v`, `--version` | Print the version and exit |
157
+
158
+ CLI flags override values from a config file. See [Configuration](#configuration).
159
+
160
+ ## Python API
161
+
162
+ ### Render a string
163
+
164
+ ````python
165
+ from markrender import MarkdownRenderer
166
+
167
+ renderer = MarkdownRenderer()
168
+
169
+ markdown = """
170
+ # Hello
171
+
172
+ Some **bold** text, some *italic* text, and `inline code`.
173
+
174
+ ```python
175
+ def hello():
176
+ print("Hello from MarkRender!")
177
+ ```
178
+
179
+ - A list item
180
+ - [x] A finished task
181
+ - [ ] A pending task
182
+ """
183
+
184
+ renderer.render(markdown)
185
+ renderer.finalize()
186
+ ````
187
+
188
+ `render()` writes output as it parses, and `finalize()` flushes whatever is still buffered. For a string you already have, call them one after the other.
189
+
190
+ ### Streaming LLM responses
191
+
192
+ ```python
193
+ from markrender import MarkdownRenderer
194
+ from openai import OpenAI
195
+
196
+ client = OpenAI()
197
+ renderer = MarkdownRenderer(theme="github-dark")
198
+
199
+ stream = client.chat.completions.create(
200
+ model="gpt-4o",
201
+ messages=[{"role": "user", "content": "Explain quantum computing"}],
202
+ stream=True,
203
+ )
204
+
205
+ for chunk in stream:
206
+ text = chunk.choices[0].delta.content
207
+ if text:
208
+ renderer.render(text)
209
+
210
+ renderer.finalize()
211
+ ```
212
+
213
+ The renderer keeps partial lines and open blocks in an internal buffer, so chunks can split anywhere: mid-word, mid-table, or in the middle of a code fence. Feed every chunk and call `finalize()` once when the stream ends.
214
+
215
+ ### Dim mode
216
+
217
+ `render()` takes a `dim_mode` argument, which draws that chunk as plain muted gray. Formatting colors, bold, and syntax highlighting are dropped so the whole block reads like thinking text instead of competing with the answer:
218
+
219
+ ```python
220
+ renderer.render("Let me think about this...", dim_mode=True)
221
+ renderer.render("Here is the answer.", dim_mode=False)
222
+ ```
223
+
224
+ Dim mode applies per call, so you can turn it on and off while streaming.
225
+
226
+ ### Custom output
227
+
228
+ By default output goes to stdout. Pass any text stream with `output`:
229
+
230
+ ```python
231
+ from markrender import MarkdownRenderer
232
+
233
+ with open("rendered.txt", "w", encoding="utf-8") as log:
234
+ renderer = MarkdownRenderer(output=log, force_color=True)
235
+ renderer.render("# Saved to a file\n")
236
+ renderer.finalize()
237
+ ```
238
+
239
+ Color detection still looks at stdout, so set `force_color=True` if you want ANSI colors in the file.
240
+
241
+ ### Constructor options
242
+
243
+ | Parameter | Default | Description |
244
+ |-----------|---------|-------------|
245
+ | `theme` | `"github-dark"` | Theme name |
246
+ | `code_background` | `False` | Draw a background behind code blocks |
247
+ | `line_numbers` | `True` | Show line numbers in code blocks |
248
+ | `inline_code_color` | theme default | ANSI color code for inline code |
249
+ | `width` | auto-detect | Wrap width in characters |
250
+ | `force_color` | `False` | Emit color even when the output is not a TTY |
251
+ | `stream_code` | `True` | Render code lines as they arrive |
252
+ | `output` | `sys.stdout` | Stream to write to |
253
+ | `use_config` | `True` | Load a config file if one is found |
254
+ | `config` | `None` | Pass a `RendererConfig` directly |
255
+
256
+ Custom inline code color uses the `rgb` helper:
257
+
258
+ ```python
259
+ from markrender import MarkdownRenderer
260
+ from markrender.colors import rgb
261
+
262
+ renderer = MarkdownRenderer(
263
+ theme="monokai",
264
+ inline_code_color=rgb(255, 100, 200),
265
+ width=100,
266
+ )
267
+ ```
268
+
269
+ ## Configuration
270
+
271
+ MarkRender reads a TOML config file if one exists. It checks these locations in order and uses the first match:
272
+
273
+ 1. `.markrender.toml` in the current directory
274
+ 2. `~/.markrender/config.toml`
275
+ 3. `~/.config/markrender/config.toml`
276
+
277
+ Example `.markrender.toml`:
278
+
279
+ ```toml
280
+ [theme]
281
+ name = "dracula"
282
+
283
+ [rendering]
284
+ code_background = true
285
+ line_numbers = false
286
+
287
+ [output]
288
+ width = 100
289
+ force_color = false
290
+
291
+ [features]
292
+ stream_code = false
293
+ ```
294
+
295
+ Values are applied in this order, from highest to lowest priority:
296
+
297
+ 1. Arguments passed to `MarkdownRenderer(...)`
298
+ 2. The config file
299
+ 3. Built-in defaults
300
+
301
+ Only non-`None` arguments override the config, so `MarkdownRenderer()` picks up your file settings. Pass `use_config=False` to ignore config files entirely.
302
+
303
+ ## Themes
304
+
305
+ | Theme | Notes |
306
+ |-------|-------|
307
+ | `github-dark` | GitHub's dark theme (default) |
308
+ | `monokai` | Classic Monokai palette |
309
+ | `dracula` | Dracula palette |
310
+ | `nord` | Nord palette |
311
+ | `one-dark` | Atom One Dark |
312
+ | `solarized-dark` | Solarized Dark |
313
+ | `solarized-light` | Solarized Light |
314
+
315
+ ```python
316
+ renderer = MarkdownRenderer(theme="dracula")
317
+ ```
318
+
319
+ See the names from the CLI with `markrender --list-themes`, or render a sample in each theme with `markrender --preview-themes`.
320
+
321
+ ## Supported Markdown Features
322
+
323
+ ### Headings
324
+ ```markdown
325
+ # H1 Heading
326
+ ## H2 Heading
327
+ ### H3 Heading
328
+ #### H4 Heading
329
+ ##### H5 Heading
330
+ ###### H6 Heading
331
+ ```
332
+
333
+ ### Code Blocks
334
+ ````markdown
335
+ ```python
336
+ def example():
337
+ return "Syntax highlighted!"
338
+ ```
339
+ ````
340
+
341
+ ### Inline Code
342
+ ```markdown
343
+ Use `inline code` for short snippets.
344
+ ```
345
+
346
+ ### Tables
347
+ ```markdown
348
+ | Feature | Supported |
349
+ |---------|-----------|
350
+ | Tables | Yes |
351
+ | Borders | Yes |
352
+ ```
353
+
354
+ ### Lists
355
+ ```markdown
356
+ - Unordered item 1
357
+ - Unordered item 2
358
+ - Nested item
359
+
360
+ 1. Ordered item 1
361
+ 2. Ordered item 2
362
+ ```
363
+
364
+ ### Checkboxes
365
+ ```markdown
366
+ - [x] Completed task
367
+ - [ ] Pending task
368
+ ```
369
+
370
+ ### Blockquotes
371
+ ```markdown
372
+ > This is a blockquote
373
+ > It can span multiple lines
374
+ ```
375
+
376
+ ### Alerts (GitHub-flavored)
377
+ ```markdown
378
+ > [!NOTE]
379
+ > Useful information users should know
380
+
381
+ > [!TIP]
382
+ > Helpful advice
383
+
384
+ > [!IMPORTANT]
385
+ > Key information
386
+
387
+ > [!WARNING]
388
+ > Urgent information
389
+
390
+ > [!CAUTION]
391
+ > Potential negative consequences
392
+ ```
393
+
394
+ ### Links
395
+ ```markdown
396
+ [Link text](https://example.com)
397
+ ```
398
+
399
+ ### Text Formatting
400
+ ```markdown
401
+ **Bold text**
402
+ *Italic text*
403
+ ***Bold and italic***
404
+ ~~Strikethrough~~
405
+ ```
406
+
407
+ ### Emojis
408
+ ```markdown
409
+ Hello :wave: Let's :rocket: go!
410
+ ```
411
+
412
+ ### Horizontal Rules
413
+ ```markdown
414
+ ---
415
+ ```
416
+
417
+ ## Use Cases
418
+
419
+ - **AI Chat Applications** - Render LLM responses in CLI tools
420
+ - **Documentation Viewers** - Display markdown documentation in terminal
421
+ - **Code Review Tools** - Show code diffs and comments
422
+ - **Note-Taking Apps** - Terminal-based markdown note viewers
423
+ - **Log Viewers** - Render structured logs with markdown
424
+
425
+ ## Development
426
+
427
+ ### Setup Development Environment
428
+
429
+ ```bash
430
+ git clone https://github.com/Praneeth-Gandodi/markrender.git
431
+ cd markrender
432
+ python -m venv venv
433
+ source venv/bin/activate # On Windows: venv\Scripts\activate
434
+ pip install -e ".[dev]"
435
+ ```
436
+
437
+ ### Run Tests
438
+
439
+ ```bash
440
+ pytest tests/ -v
441
+ pytest tests/ --cov=markrender --cov-report=html --cov-report=term
442
+ ```
443
+
444
+ ### Run Examples
445
+
446
+ ```bash
447
+ python examples/basic_usage.py
448
+ python examples/streaming_demo.py
449
+ python examples/theme_showcase.py
450
+ ```
451
+
452
+ ### Releasing
453
+
454
+ The package version is derived from git tags by `setuptools_scm`, so there is
455
+ no version number to edit by hand.
456
+
457
+ 1. Open **Actions → Publish → Run workflow**.
458
+ 2. Choose `auto` (recommended) or an explicit `patch`, `minor`, or `major` bump.
459
+ 3. The workflow runs the tests, creates the next `vX.Y.Z` tag, builds the
460
+ sdist and wheel, publishes to PyPI, and creates a GitHub release.
461
+
462
+ With `auto`, commit messages since the last tag decide the bump:
463
+
464
+ - `feat!:` or a `BREAKING CHANGE:` footer → major
465
+ - `feat:` → minor
466
+ - everything else → patch
467
+
468
+ Publishing uses PyPI Trusted Publishing (OIDC), so no API token is stored in
469
+ the repository. Configure it once:
470
+
471
+ - **PyPI:** project `markrender` → Publishing → add a trusted publisher with
472
+ owner `Praneeth-Gandodi`, repository `markrender`, workflow `publish.yml`,
473
+ environment `pypi`.
474
+ - **GitHub:** Settings → Environments → create an environment named `pypi`.
475
+
476
+ The repository default workflow permission can stay read-only; the workflow
477
+ requests `contents: write` only for the jobs that create the tag and release.
478
+
479
+ You can also publish an existing tag directly:
480
+
481
+ ```bash
482
+ git tag v1.1.0
483
+ git push origin v1.1.0
484
+ ```
485
+
486
+ To publish automatically after every merge to `main`, uncomment the `branches:
487
+ [main]` trigger in `.github/workflows/publish.yml`.
488
+
489
+ ## License
490
+
491
+ MIT License - see [LICENSE](LICENSE) file for details.