streamdown 0.25.0__py3-none-any.whl → 0.27.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 +66 -34
- streamdown/ss +1 -0
- streamdown/ss1 +42 -0
- {streamdown-0.25.0.dist-info → streamdown-0.27.0.dist-info}/METADATA +1 -5
- streamdown-0.27.0.dist-info/RECORD +11 -0
- streamdown-0.25.0.dist-info/RECORD +0 -9
- {streamdown-0.25.0.dist-info → streamdown-0.27.0.dist-info}/WHEEL +0 -0
- {streamdown-0.25.0.dist-info → streamdown-0.27.0.dist-info}/entry_points.txt +0 -0
- {streamdown-0.25.0.dist-info → streamdown-0.27.0.dist-info}/licenses/LICENSE.MIT +0 -0
streamdown/sd.py
CHANGED
|
@@ -206,7 +206,8 @@ class ParseState:
|
|
|
206
206
|
return offset + (state.current_width(listwidth = True) if Style.PrettyBroken else self.WidthFull)
|
|
207
207
|
|
|
208
208
|
def current_width(self, listwidth = False):
|
|
209
|
-
|
|
209
|
+
# this will double count the left margin
|
|
210
|
+
return self.Width - (len(visible(self.space_left(listwidth)))) + Style.Margin
|
|
210
211
|
|
|
211
212
|
def space_left(self, listwidth = False):
|
|
212
213
|
pre = ' ' * (len(state.list_item_stack)) * Style.ListIndent if listwidth else ''
|
|
@@ -235,7 +236,7 @@ def format_table(rowList):
|
|
|
235
236
|
|
|
236
237
|
# Calculate max width per column (integer division)
|
|
237
238
|
# Subtract num_cols + 1 for the vertical borders '│'
|
|
238
|
-
available_width = state.current_width() - (num_cols
|
|
239
|
+
available_width = state.current_width() - (num_cols * 2)
|
|
239
240
|
|
|
240
241
|
width_base = available_width // num_cols
|
|
241
242
|
width_mod = available_width % num_cols
|
|
@@ -285,17 +286,23 @@ def format_table(rowList):
|
|
|
285
286
|
|
|
286
287
|
def emit_h(level, text):
|
|
287
288
|
text = line_format(text)
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
289
|
+
lineList = text_wrap(text)
|
|
290
|
+
res = []
|
|
291
|
+
for text in lineList:
|
|
292
|
+
spaces_to_center = (state.current_width() - visible_length(text)) / 2
|
|
293
|
+
if level == 1: #
|
|
294
|
+
res.append(f"{state.space_left()}\n{state.space_left()}{BOLD[1]}{' ' * math.floor(spaces_to_center)}{text}{BOLD[1]}")
|
|
295
|
+
elif level == 2: ##
|
|
296
|
+
res.append(f"{state.space_left()}\n{state.space_left()}{BOLD[0]}{FG}{Style.Bright}{' ' * math.floor(spaces_to_center)}{text}{' ' * math.ceil(spaces_to_center)}{BOLD[1]}{FGRESET}")
|
|
297
|
+
elif level == 3: ###
|
|
298
|
+
res.append(f"{state.space_left()}{FG}{Style.Head}{BOLD[0]}{text}{RESET}")
|
|
299
|
+
elif level == 4: ####
|
|
300
|
+
res.append(f"{state.space_left()}{FG}{Style.Symbol}{text}{RESET}")
|
|
301
|
+
elif level == 5: #####
|
|
302
|
+
res.append(f"{state.space_left()}{text}{RESET}")
|
|
303
|
+
else:
|
|
304
|
+
res.append(f"{state.space_left()}{FG}{Style.Grey}{text}{RESET}")
|
|
305
|
+
return "\n".join(res)
|
|
299
306
|
|
|
300
307
|
def code_wrap(text_in):
|
|
301
308
|
if not Style.PrettyBroken and state.WidthWrap and len(text_in) > state.full_width():
|
|
@@ -379,9 +386,7 @@ def text_wrap(text, width = -1, indent = 0, first_line_prefix="", subsequent_lin
|
|
|
379
386
|
|
|
380
387
|
# The empty word clears the buffer at the end.
|
|
381
388
|
formatted = line_format(text)
|
|
382
|
-
#print(bytes(formatted, 'utf-8'), formatted)
|
|
383
389
|
words = split_text(formatted) + [""]
|
|
384
|
-
#print([bytes(i, 'utf-8') for i in words])
|
|
385
390
|
|
|
386
391
|
lines = []
|
|
387
392
|
current_line = ""
|
|
@@ -432,11 +437,15 @@ def text_wrap(text, width = -1, indent = 0, first_line_prefix="", subsequent_lin
|
|
|
432
437
|
if len(lines) < 1:
|
|
433
438
|
return []
|
|
434
439
|
|
|
440
|
+
if len(lines) == 1:
|
|
441
|
+
lines[0] = lines[0].rstrip()
|
|
442
|
+
|
|
435
443
|
return lines
|
|
436
444
|
|
|
437
445
|
def dbl_count(s):
|
|
438
446
|
dbl_re = re.compile(
|
|
439
447
|
r'[\u2e80-\u2eff\u3000-\u303f\u3400-\u4dbf'
|
|
448
|
+
r'\uFF00-\uFFEF' # CJK Compatibility Punctuation
|
|
440
449
|
r'\U00004e00-\U00009fff\U0001f300-\U0001f6ff'
|
|
441
450
|
r'\U0001f900-\U0001f9ff\U0001fa70-\U0001faff]',
|
|
442
451
|
re.UNICODE
|
|
@@ -448,7 +457,7 @@ def cjk_count(s):
|
|
|
448
457
|
r'[\u4E00-\u9FFF' # CJK Unified Ideographs
|
|
449
458
|
r'\u3400-\u4DBF' # CJK Unified Ideographs Extension A
|
|
450
459
|
r'\uF900-\uFAFF' # CJK Compatibility Ideographs
|
|
451
|
-
|
|
460
|
+
r'\uFF00-\uFFEF' # CJK Compatibility Punctuation
|
|
452
461
|
r'\u3000-\u303F' # CJK Symbols and Punctuation
|
|
453
462
|
r'\U0002F800-\U0002FA1F]' # CJK Compatibility Ideographs Supplement
|
|
454
463
|
)
|
|
@@ -456,7 +465,7 @@ def cjk_count(s):
|
|
|
456
465
|
return len(cjk_re.findall(visible(s)))
|
|
457
466
|
|
|
458
467
|
def line_format(line):
|
|
459
|
-
not_text = lambda token: not (token.isalnum() or token
|
|
468
|
+
not_text = lambda token: not (token.isalnum() or token in ['\\','"']) or cjk_count(token)
|
|
460
469
|
footnotes = lambda match: ''.join([chr(SUPER[int(i)]) for i in match.group(1)])
|
|
461
470
|
|
|
462
471
|
def process_images(match):
|
|
@@ -686,7 +695,7 @@ def parse(stream):
|
|
|
686
695
|
|
|
687
696
|
# <code><pre>
|
|
688
697
|
if not state.in_code:
|
|
689
|
-
code_match = re.match(r"^\s
|
|
698
|
+
code_match = re.match(r"^\s*(```|<pre>)\s*([^\s]+|$)\s*$", line)
|
|
690
699
|
if code_match:
|
|
691
700
|
state.in_code = Code.Backtick
|
|
692
701
|
state.code_indent = len(line) - len(line.lstrip())
|
|
@@ -720,10 +729,8 @@ def parse(stream):
|
|
|
720
729
|
if state.in_code:
|
|
721
730
|
try:
|
|
722
731
|
# This is turning it OFF
|
|
723
|
-
if
|
|
724
|
-
|
|
725
|
-
(state.CodeSpaces and state.in_code == Code.Spaces and not line.startswith(' '))
|
|
726
|
-
):
|
|
732
|
+
if ( ( state.in_code == Code.Backtick and line.strip() in ["</pre>", "```"] ) or
|
|
733
|
+
(state.CodeSpaces and state.in_code == Code.Spaces and not line.startswith(' ')) ):
|
|
727
734
|
if state.scrape:
|
|
728
735
|
ext = "sh"
|
|
729
736
|
try:
|
|
@@ -914,7 +921,7 @@ def parse(stream):
|
|
|
914
921
|
# a weird thing
|
|
915
922
|
if state.in_list:
|
|
916
923
|
indent = (len(state.list_item_stack) - 1) * Style.ListIndent #+ (len(bullet) - 1)
|
|
917
|
-
wrap_width = state.current_width(
|
|
924
|
+
wrap_width = state.current_width(listwidth = True) - Style.ListIndent
|
|
918
925
|
|
|
919
926
|
wrapped_lineList = text_wrap(content, wrap_width, Style.ListIndent,
|
|
920
927
|
first_line_prefix = f"{(' ' * indent)}{FG}{Style.Symbol}{bullet}{RESET} ",
|
|
@@ -946,6 +953,11 @@ def parse(stream):
|
|
|
946
953
|
continue
|
|
947
954
|
|
|
948
955
|
state.where_from = "emit_normal"
|
|
956
|
+
|
|
957
|
+
# if we've gotten to an emit normal then we can assert that our list stack should
|
|
958
|
+
# be empty. This is a hack.
|
|
959
|
+
state.list_item_stack = []
|
|
960
|
+
|
|
949
961
|
if len(line) == 0: yield ""
|
|
950
962
|
if len(line) < state.Width:
|
|
951
963
|
# we want to prevent word wrap
|
|
@@ -1010,19 +1022,23 @@ def apply_multipliers(style, name, H, S, V):
|
|
|
1010
1022
|
return ';'.join([str(int(x * 256)) for x in [r, g, b]]) + "m"
|
|
1011
1023
|
|
|
1012
1024
|
def width_calc():
|
|
1013
|
-
if
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1025
|
+
if state.WidthArg:
|
|
1026
|
+
width = state.WidthArg
|
|
1027
|
+
else:
|
|
1028
|
+
try:
|
|
1029
|
+
width = shutil.get_terminal_size().columns
|
|
1030
|
+
state.WidthWrap = True
|
|
1031
|
+
except (AttributeError, OSError):
|
|
1032
|
+
width = 80
|
|
1033
|
+
pass
|
|
1018
1034
|
|
|
1019
|
-
try:
|
|
1020
|
-
width = shutil.get_terminal_size().columns
|
|
1021
|
-
state.WidthWrap = True
|
|
1022
|
-
except (AttributeError, OSError):
|
|
1023
|
-
pass
|
|
1024
1035
|
|
|
1025
|
-
|
|
1036
|
+
# This can't be done because our list item stack can change as well so
|
|
1037
|
+
# unless we want to track that too, we're SOL
|
|
1038
|
+
#if state.WidthFull == width:
|
|
1039
|
+
# return
|
|
1040
|
+
|
|
1041
|
+
state.WidthFull = width
|
|
1026
1042
|
|
|
1027
1043
|
state.Width = state.WidthFull - 2 * Style.Margin
|
|
1028
1044
|
pre = state.space_left(listwidth=True) if Style.PrettyBroken else ''
|
|
@@ -1041,8 +1057,24 @@ def main():
|
|
|
1041
1057
|
parser.add_argument("-w", "--width", default="0", help="Set the width WIDTH")
|
|
1042
1058
|
parser.add_argument("-e", "--exec", help="Wrap a program EXEC for more 'proper' i/o handling")
|
|
1043
1059
|
parser.add_argument("-s", "--scrape", help="Scrape code snippets to a directory SCRAPE")
|
|
1060
|
+
parser.add_argument("-v", "--version", action="store_true", help="Show version information")
|
|
1044
1061
|
args = parser.parse_args()
|
|
1045
1062
|
|
|
1063
|
+
if args.version:
|
|
1064
|
+
try:
|
|
1065
|
+
import importlib.metadata
|
|
1066
|
+
print(importlib.metadata.version("streamdown"))
|
|
1067
|
+
except importlib.metadata.PackageNotFoundError:
|
|
1068
|
+
import subprocess
|
|
1069
|
+
print(subprocess.run(
|
|
1070
|
+
['git', 'describe', '--always', '--dirty', '--tags'],
|
|
1071
|
+
cwd=os.path.dirname(os.path.abspath(__file__)),
|
|
1072
|
+
stdout=subprocess.PIPE,
|
|
1073
|
+
text=True
|
|
1074
|
+
).stdout.strip())
|
|
1075
|
+
|
|
1076
|
+
sys.exit(0)
|
|
1077
|
+
|
|
1046
1078
|
config_toml_path, config_toml_content = ensure_config_file(args.config)
|
|
1047
1079
|
config = toml.loads(config_toml_content)
|
|
1048
1080
|
style = toml.loads(default_toml).get('style') | config.get("style", {})
|
streamdown/ss
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* **Model Card:** Always read the model card on the Hugging Face Hub ([https://huggingface.co/microsoft/bitnet-b1.58-2B-4T](https://huggingface.co/microsoft/bitnet-b1.58-2B-4T)) for important information about the model, its intended use, limitations, and potential biases.
|
streamdown/ss1
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
* `model.safetensors`: The name of the file you want to download. You'll need to know the exact filename. You can find the files in the model repository on the Hugging Face Hub website ([https://huggingface.co/microsoft/bitnet-b1.58-2B-4T](https://huggingface.co/microsoft/bitnet-b1.58-2B-4T)). Look under the "Files and versions" tab. `safetensors` is the preferred format for model weights now. If it's a `.bin` file, you can download that instead.
|
|
2
|
+
* `--local-dir ./bitnet-b1.58-2B-4T`: The directory to save the file to.
|
|
3
|
+
|
|
4
|
+
* **Download using `transformers` library (recommended for most use cases):**
|
|
5
|
+
|
|
6
|
+
The `transformers` library provides a convenient way to download and cache models. This is often the easiest approach if you're using the model with `transformers`. You don't *directly* use the `huggingface-cli` for this, but it's worth knowing.
|
|
7
|
+
|
|
8
|
+
```python
|
|
9
|
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
|
10
|
+
|
|
11
|
+
model_name = "microsoft/bitnet-b1.58-2B-4T"
|
|
12
|
+
|
|
13
|
+
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
|
14
|
+
model = AutoModelForCausalLM.from_pretrained(model_name)
|
|
15
|
+
|
|
16
|
+
# The model and tokenizer will be downloaded and cached in your
|
|
17
|
+
# transformers cache directory (usually ~/.cache/huggingface/transformers).
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
This approach automatically handles downloading the necessary files and caching them for future use. It also handles the correct file formats and configurations.
|
|
21
|
+
|
|
22
|
+
**4. Checking the Download**
|
|
23
|
+
|
|
24
|
+
After the download completes, verify that the files are in the specified directory. You can use `ls` (Linux/macOS) or `dir` (Windows) to list the contents of the directory.
|
|
25
|
+
|
|
26
|
+
**Important Considerations:**
|
|
27
|
+
|
|
28
|
+
* **Disk Space:** The `bitnet-b1.58-2B-4T` model is quite large (several gigabytes). Make sure you have enough free disk space before downloading.
|
|
29
|
+
* **Network Connection:** A stable and fast internet connection is essential for a smooth download.
|
|
30
|
+
* **Caching:** The Hugging Face Hub and `transformers` library use caching to avoid re-downloading models unnecessarily. The default cache directory is usually `~/.cache/huggingface/transformers`.
|
|
31
|
+
* **File Formats:** Models are often stored in `safetensors` or `.bin` formats. `safetensors` is generally preferred for security and performance.
|
|
32
|
+
* **Model Card:** Always read the model card on the Hugging Face Hub ([https://huggingface.co/microsoft/bitnet-b1.58-2B-4T](https://huggingface.co/microsoft/bitnet-b1.58-2B-4T)) for important information about the model, its intended use, limitations, and potential biases.
|
|
33
|
+
* **Gated Models:** Some models require you to accept terms of use before you can download them. The `huggingface-cli login` command will guide you through this process if necessary.
|
|
34
|
+
|
|
35
|
+
**Example Workflow (Recommended):**
|
|
36
|
+
|
|
37
|
+
1. `huggingface-cli login` (if not already logged in)
|
|
38
|
+
2. Use the `transformers` library in a Python script to download and load the model (as shown in the example above). This is the most convenient and reliable method for most use cases.
|
|
39
|
+
|
|
40
|
+
Let me know if you have any other questions or if you'd like help with a specific task related to this model!
|
|
41
|
+
|
|
42
|
+
>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: streamdown
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.27.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
|
|
@@ -188,7 +188,3 @@ After the git clone least one of these should work, hopefully. it's using the mo
|
|
|
188
188
|
$ pip install -e .
|
|
189
189
|
$ uv pip install -e .
|
|
190
190
|
|
|
191
|
-
### Future work
|
|
192
|
-
|
|
193
|
-
#### Glow styles
|
|
194
|
-
I'm going to try to be compatible with other popular markdown styles to help for a smoother transition. Glow compatible json sheets is on my radar. There's also mdless and frogmouth. Might be others
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
streamdown/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
streamdown/sd.py,sha256=hk9h-gZz9OJw88iHowC6mWk0-ETRMmKmdr3063c8e74,43469
|
|
3
|
+
streamdown/ss,sha256=sel_phpaecrw6WGIHRLROsD7BFShf0rSDHheflwdUn8,277
|
|
4
|
+
streamdown/ss1,sha256=CUVf86_2zeAle2oQCeTfWYqtHBrAFR_UgvptuYMQzFU,3151
|
|
5
|
+
streamdown/plugins/README.md,sha256=KWqYELs9WkKJmuDzYv3cvPlZMkArsNCBUe4XDoTLjLA,1143
|
|
6
|
+
streamdown/plugins/latex.py,sha256=xZMGMdx_Sw4X1piZejXFHfEG9qazU4fGeceiMI0h13Y,648
|
|
7
|
+
streamdown-0.27.0.dist-info/METADATA,sha256=_5zd5q0T0LSEk9kJK2CZitv7HfboKIhLrEsWjUfdmx8,9425
|
|
8
|
+
streamdown-0.27.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
9
|
+
streamdown-0.27.0.dist-info/entry_points.txt,sha256=HroKFsFMGf_h9PRTE96NjvjJQWupMW5TGP5RGUr1O_Q,74
|
|
10
|
+
streamdown-0.27.0.dist-info/licenses/LICENSE.MIT,sha256=SnY46EPirUsF20dZDR8HpyVgS2_4Tjxuc6f-4OdqO7U,1070
|
|
11
|
+
streamdown-0.27.0.dist-info/RECORD,,
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
streamdown/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
streamdown/sd.py,sha256=ffr_xygYCNseJ_jkvie88Omiz9aaOhY32_-dDj1LdUY,42326
|
|
3
|
-
streamdown/plugins/README.md,sha256=KWqYELs9WkKJmuDzYv3cvPlZMkArsNCBUe4XDoTLjLA,1143
|
|
4
|
-
streamdown/plugins/latex.py,sha256=xZMGMdx_Sw4X1piZejXFHfEG9qazU4fGeceiMI0h13Y,648
|
|
5
|
-
streamdown-0.25.0.dist-info/METADATA,sha256=H9-T77e6Rs7fN-lJGG07So4uxqv6utRZrN98B8lLPH4,9658
|
|
6
|
-
streamdown-0.25.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
7
|
-
streamdown-0.25.0.dist-info/entry_points.txt,sha256=HroKFsFMGf_h9PRTE96NjvjJQWupMW5TGP5RGUr1O_Q,74
|
|
8
|
-
streamdown-0.25.0.dist-info/licenses/LICENSE.MIT,sha256=SnY46EPirUsF20dZDR8HpyVgS2_4Tjxuc6f-4OdqO7U,1070
|
|
9
|
-
streamdown-0.25.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|