streamdown 0.14.0__py3-none-any.whl → 0.16.0__py3-none-any.whl
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.
- streamdown/sd.py +10 -5
- {streamdown-0.14.0.dist-info → streamdown-0.16.0.dist-info}/METADATA +28 -28
- {streamdown-0.14.0.dist-info → streamdown-0.16.0.dist-info}/RECORD +6 -6
- {streamdown-0.14.0.dist-info → streamdown-0.16.0.dist-info}/WHEEL +0 -0
- {streamdown-0.14.0.dist-info → streamdown-0.16.0.dist-info}/entry_points.txt +0 -0
- {streamdown-0.14.0.dist-info → streamdown-0.16.0.dist-info}/licenses/LICENSE.MIT +0 -0
streamdown/sd.py
CHANGED
|
@@ -22,10 +22,10 @@ import subprocess
|
|
|
22
22
|
import traceback
|
|
23
23
|
import colorsys
|
|
24
24
|
import base64
|
|
25
|
-
import importlib
|
|
26
25
|
from io import BytesIO
|
|
27
26
|
from term_image.image import from_file, from_url
|
|
28
27
|
import pygments.util
|
|
28
|
+
from functools import reduce
|
|
29
29
|
from argparse import ArgumentParser
|
|
30
30
|
from pygments import highlight
|
|
31
31
|
from pygments.lexers import get_lexer_by_name
|
|
@@ -91,8 +91,8 @@ KEYCODE_RE = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
|
|
|
91
91
|
|
|
92
92
|
visible = lambda x: re.sub(ANSIESCAPE, "", x)
|
|
93
93
|
visible_length = lambda x: len(visible(x))
|
|
94
|
-
|
|
95
94
|
extract_ansi_codes = lambda text: re.findall(ESCAPE, text)
|
|
95
|
+
remove_ansi = lambda line, codeList: reduce(lambda line, code: line.replace(code, ''), codeList, line)
|
|
96
96
|
|
|
97
97
|
def debug_write(text):
|
|
98
98
|
if state.Logging:
|
|
@@ -271,6 +271,7 @@ def code_wrap(text_in):
|
|
|
271
271
|
|
|
272
272
|
return (indent, res)
|
|
273
273
|
|
|
274
|
+
|
|
274
275
|
# This marvelously obscure code "compacts" long lines of repetitive ANSI format strings by
|
|
275
276
|
# removing duplicates. Here's how it works
|
|
276
277
|
def ansi_collapse(codelist, inp):
|
|
@@ -567,9 +568,10 @@ def parse(stream):
|
|
|
567
568
|
# <code><pre>
|
|
568
569
|
#
|
|
569
570
|
if not state.in_code:
|
|
570
|
-
code_match = re.match(r"
|
|
571
|
+
code_match = re.match(r"^\s*```\s*([^\s]+|$)\s*$", line)
|
|
571
572
|
if code_match:
|
|
572
573
|
state.in_code = Code.Backtick
|
|
574
|
+
state.code_indent = len(line) - len(line.lstrip())
|
|
573
575
|
state.code_language = code_match.group(1) or 'Bash'
|
|
574
576
|
|
|
575
577
|
elif state.CodeSpaces and last_line_empty_cache and not state.in_list:
|
|
@@ -594,6 +596,7 @@ def parse(stream):
|
|
|
594
596
|
|
|
595
597
|
if state.in_code:
|
|
596
598
|
try:
|
|
599
|
+
# This is turning it OFF
|
|
597
600
|
if not state.code_first_line and (
|
|
598
601
|
( state.in_code == Code.Backtick and line.strip() == "```" ) or
|
|
599
602
|
(state.CodeSpaces and state.in_code == Code.Spaces and not line.startswith(' '))
|
|
@@ -623,9 +626,7 @@ def parse(stream):
|
|
|
623
626
|
state.emit_flush = True
|
|
624
627
|
yield RESET
|
|
625
628
|
|
|
626
|
-
|
|
627
629
|
if code_type == Code.Backtick:
|
|
628
|
-
state.code_indent = len(line) - len(line.lstrip())
|
|
629
630
|
continue
|
|
630
631
|
else:
|
|
631
632
|
# otherwise we don't want to consume
|
|
@@ -665,6 +666,10 @@ def parse(stream):
|
|
|
665
666
|
# then naively search back until our visible_lengths() match. This is not fast and there's certainly smarter
|
|
666
667
|
# ways of doing it but this thing is way trickery than you think
|
|
667
668
|
highlighted_code = highlight(state.code_buffer + tline, lexer, formatter)
|
|
669
|
+
|
|
670
|
+
# Sometimes the highlighter will do things like a full reset or a background reset.
|
|
671
|
+
# This is not what we want
|
|
672
|
+
highlighted_code = re.sub(r"\033\[39(;00|)m", '', highlighted_code)
|
|
668
673
|
|
|
669
674
|
# Since we are streaming we ignore the resets and newlines at the end
|
|
670
675
|
if highlighted_code.endswith(FGRESET + "\n"):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: streamdown
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.16.0
|
|
4
4
|
Summary: A streaming markdown renderer for modern terminals with syntax highlighting
|
|
5
5
|
Project-URL: Homepage, https://github.com/kristopolous/Streamdown
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/kristopolous/Streamdown/issues
|
|
@@ -23,47 +23,49 @@ Requires-Python: >=3.8
|
|
|
23
23
|
Requires-Dist: appdirs
|
|
24
24
|
Requires-Dist: pygments
|
|
25
25
|
Requires-Dist: pylatexenc
|
|
26
|
+
Requires-Dist: term-image
|
|
26
27
|
Requires-Dist: toml
|
|
27
28
|
Description-Content-Type: text/markdown
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
<p align="center">
|
|
31
|
+
<img src=https://github.com/user-attachments/assets/0468eac0-2a00-4e98-82ca-09e6ac679357/>
|
|
32
|
+
<br/>
|
|
33
|
+
<a href=https://pypi.org/project/streamdown><img src=https://badge.fury.io/py/streamdown.svg/></a>
|
|
34
|
+
</p>
|
|
30
35
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
This will work with [simonw's llm](https://github.com/simonw/llm) unlike with [richify.py](https://github.com/gianlucatruda/richify) which rerenders the whole buffer and blocks with an elipses or [glow](https://github.com/charmbracelet/glow) which buffers everything, this streams and does exactly what it says.
|
|
38
|
-
|
|
39
|
-
## Some Features
|
|
36
|
+
The streaming markdown renderer for the terminal that rocks!
|
|
37
|
+
Streamdown works with [simonw's llm](https://github.com/simonw/llm) along with any other streaming markdown. You even get full readline and keyboard navigation support.
|
|
38
|
+
```bash
|
|
39
|
+
$ pip install streamdown
|
|
40
|
+
```
|
|
41
|
+

|
|
40
42
|
|
|
41
|
-
### Provides clean copyable code for long code
|
|
42
|
-
!
|
|
43
|
+
### Provides clean copyable code for long code lines
|
|
44
|
+
You may have noticed *inferior* renderers inject line breaks when copying code that wraps around. We're better and now you are too!
|
|
45
|
+

|
|
43
46
|
|
|
44
|
-
### Supports images
|
|
47
|
+
### Supports images
|
|
45
48
|
Here's kitty and alacritty. Try to do that in glow...
|
|
46
|
-

|
|
47
50
|
|
|
48
|
-
###
|
|
51
|
+
### Supports hyperlinks (OSC 8) and clipboard (OSC 52)
|
|
49
52
|
[links.webm](https://github.com/user-attachments/assets/a5f71791-7c58-4183-ad3b-309f470c08a3)
|
|
50
53
|
|
|
51
|
-
###
|
|
52
|
-

|
|
53
|
-
|
|
54
|
-
### Tables are carefully supported
|
|
54
|
+
### Supports tables
|
|
55
55
|

|
|
56
56
|
|
|
57
|
+
As well as everything else...
|
|
58
|
+

|
|
59
|
+
|
|
57
60
|
### Colors are highly (and quickly) configurable for people who care a lot, or just a little.
|
|
58
|
-

|
|
59
62
|
|
|
60
63
|
### Has a [Plugin](https://github.com/kristopolous/Streamdown/tree/main/streamdown/plugins) system to extend the parser and renderer.
|
|
61
64
|
For instance, here is the [latex plugin](https://github.com/kristopolous/Streamdown/blob/main/streamdown/plugins/latex.py) doing math inside a table:
|
|
62
65
|

|
|
63
66
|
|
|
64
67
|
|
|
65
|
-
## Configuration
|
|
66
|
-
|
|
68
|
+
## TOML Configuration
|
|
67
69
|
|
|
68
70
|
Streamdown uses a TOML configuration file located at `~/.config/streamdown/config.toml` (following the XDG Base Directory Specification). If this file does not exist upon first run, it will be created with default values.
|
|
69
71
|
|
|
@@ -84,7 +86,7 @@ Defines the base Hue (H), Saturation (S), and Value (V) from which all other pal
|
|
|
84
86
|
* `Width` (integer, default: `0`): Along with the `Margin`, `Width` specifies the base width of the content, which when set to 0, means use the terminal width. See [#6](https://github.com/kristopolous/Streamdown/issues/6) for more details
|
|
85
87
|
* `PrettyPad` (boolean, default: `false`): Uses a unicode vertical pad trick to add a half height background to code blocks. This makes copy/paste have artifacts. See [#2](https://github.com/kristopolous/Streamdown/issues/2). I like it on. But that's just me
|
|
86
88
|
* `ListIndent` (integer, default: `2`): This is the recursive indent for the list styles.
|
|
87
|
-
* `Syntax` (string, default `monokai`): This the syntax [highlighting theme which come via pygments](https://pygments.org/styles/).
|
|
89
|
+
* `Syntax` (string, default `monokai`): This is the syntax [highlighting theme which come via pygments](https://pygments.org/styles/).
|
|
88
90
|
|
|
89
91
|
Example:
|
|
90
92
|
```toml
|
|
@@ -113,7 +115,7 @@ Width = 120
|
|
|
113
115
|
Timeout = 1.0
|
|
114
116
|
```
|
|
115
117
|
|
|
116
|
-
##
|
|
118
|
+
## Command Line
|
|
117
119
|
The most exciting feature here is `--exec` with it you can do full readline support like this:
|
|
118
120
|
|
|
119
121
|
$ sd --exec "llm chat"
|
|
@@ -143,10 +145,8 @@ Do this
|
|
|
143
145
|
|
|
144
146
|
$ ./streamdown/sd.py tests/*md
|
|
145
147
|
|
|
146
|
-
Certainly room for improvement and I'll probably continue to make them
|
|
147
|
-
|
|
148
148
|
## Install from source
|
|
149
|
-
|
|
149
|
+
After the git clone least one of these should work, hopefully. it's using the modern uv pip tool.
|
|
150
150
|
|
|
151
151
|
$ pipx install -e .
|
|
152
152
|
$ pip install -e .
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
streamdown/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
streamdown/sd.py,sha256=
|
|
2
|
+
streamdown/sd.py,sha256=0Ug2grAsf_RWVMyDMOc0j_ZTmL8N6dOPpk24LKBPkhA,35641
|
|
3
3
|
streamdown/tt.mds,sha256=srDldQ9KnMJd5P8GdTXTJl4mjTowwV9y58ZIaBVbtFY,359
|
|
4
4
|
streamdown/plugins/README.md,sha256=KWqYELs9WkKJmuDzYv3cvPlZMkArsNCBUe4XDoTLjLA,1143
|
|
5
5
|
streamdown/plugins/latex.py,sha256=xZMGMdx_Sw4X1piZejXFHfEG9qazU4fGeceiMI0h13Y,648
|
|
6
6
|
streamdown/scrape/file_0.py,sha256=OiFxFGGHu2C2iO9LVnhXKCybqCsnw0bu8MmI2E0vs_s,610
|
|
7
7
|
streamdown/scrape/file_1.js,sha256=JnXSvlsk9UmU5LsGOfXkP3sGId8VNEJRJo8-uRohRCM,569
|
|
8
8
|
streamdown/scrape/file_2.cpp,sha256=4hbT9TJzDNmrU7BVwaIuCMlI2BvUEVeTKoH6wUJRkrI,397
|
|
9
|
-
streamdown-0.
|
|
10
|
-
streamdown-0.
|
|
11
|
-
streamdown-0.
|
|
12
|
-
streamdown-0.
|
|
13
|
-
streamdown-0.
|
|
9
|
+
streamdown-0.16.0.dist-info/METADATA,sha256=sq6eIyimqRI8cZHKkNbDdP3OoYpEPYCU-v5LFhBgYfQ,7968
|
|
10
|
+
streamdown-0.16.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
11
|
+
streamdown-0.16.0.dist-info/entry_points.txt,sha256=HroKFsFMGf_h9PRTE96NjvjJQWupMW5TGP5RGUr1O_Q,74
|
|
12
|
+
streamdown-0.16.0.dist-info/licenses/LICENSE.MIT,sha256=SnY46EPirUsF20dZDR8HpyVgS2_4Tjxuc6f-4OdqO7U,1070
|
|
13
|
+
streamdown-0.16.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|