streamdown 0.24.0__py3-none-any.whl → 0.26.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 CHANGED
@@ -104,19 +104,22 @@ visible_length = lambda x: len(visible(x)) + dbl_count(x)
104
104
  extract_ansi_codes = lambda text: re.findall(ESCAPE, text)
105
105
  remove_ansi = lambda line, codeList: reduce(lambda line, code: line.replace(code, ''), codeList, line)
106
106
 
107
+ def gettmpdir():
108
+ tmp_dir_all = os.path.join(tempfile.gettempdir(), "sd")
109
+ os.makedirs(tmp_dir_all, mode=0o777, exist_ok=True)
110
+ tmp_dir = os.path.join(tmp_dir_all, str(os.getuid()))
111
+ os.makedirs(tmp_dir, exist_ok=True)
112
+ return tmp_dir
113
+
107
114
  def debug_write(text):
108
115
  if state.Logging:
109
116
  if state.Logging == True:
110
- tmp_dir = os.path.join(tempfile.gettempdir(), "sd")
111
- os.makedirs(tmp_dir, exist_ok=True)
112
- state.Logging = tempfile.NamedTemporaryFile(dir=tmp_dir, prefix="dbg", delete=False, mode="wb")
117
+ state.Logging = tempfile.NamedTemporaryFile(dir=gettmpdir(), prefix="dbg", delete=False, mode="wb")
113
118
  state.Logging.write(text)
114
119
 
115
120
  def savebrace():
116
121
  if state.Savebrace and state.code_buffer_raw:
117
- tmp_dir = os.path.join(tempfile.gettempdir(), "sd")
118
- os.makedirs(tmp_dir, exist_ok=True)
119
- path = os.path.join(tempfile.gettempdir(), "sd", 'savebrace')
122
+ path = os.path.join(gettmpdir(), 'savebrace')
120
123
  with open(path, "a") as f:
121
124
  f.write(state.code_buffer_raw + "\x00")
122
125
  f.flush()
@@ -282,17 +285,23 @@ def format_table(rowList):
282
285
 
283
286
  def emit_h(level, text):
284
287
  text = line_format(text)
285
- spaces_to_center = (state.current_width() - visible_length(text)) / 2
286
- if level == 1: #
287
- return f"{state.space_left()}\n{state.space_left()}{BOLD[1]}{' ' * math.floor(spaces_to_center)}{text}{BOLD[1]}"
288
- elif level == 2: ##
289
- return 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}"
290
- elif level == 3: ###
291
- return f"{state.space_left()}{FG}{Style.Head}{BOLD[0]}{text}{RESET}"
292
- elif level == 4: ####
293
- return f"{state.space_left()}{FG}{Style.Symbol}{text}{RESET}"
294
- else: # level 5 or 6
295
- return f"{state.space_left()}{text}{RESET}"
288
+ lineList = text_wrap(text)
289
+ res = []
290
+ for text in lineList:
291
+ spaces_to_center = (state.current_width() - visible_length(text)) / 2
292
+ if level == 1: #
293
+ res.append(f"{state.space_left()}\n{state.space_left()}{BOLD[1]}{' ' * math.floor(spaces_to_center)}{text}{BOLD[1]}")
294
+ elif level == 2: ##
295
+ 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}")
296
+ elif level == 3: ###
297
+ res.append(f"{state.space_left()}{FG}{Style.Head}{BOLD[0]}{text}{RESET}")
298
+ elif level == 4: ####
299
+ res.append(f"{state.space_left()}{FG}{Style.Symbol}{text}{RESET}")
300
+ elif level == 5: #####
301
+ res.append(f"{state.space_left()}{text}{RESET}")
302
+ else:
303
+ res.append(f"{state.space_left()}{FG}{Style.Grey}{text}{RESET}")
304
+ return "\n".join(res)
296
305
 
297
306
  def code_wrap(text_in):
298
307
  if not Style.PrettyBroken and state.WidthWrap and len(text_in) > state.full_width():
@@ -453,7 +462,7 @@ def cjk_count(s):
453
462
  return len(cjk_re.findall(visible(s)))
454
463
 
455
464
  def line_format(line):
456
- not_text = lambda token: not (token.isalnum() or token == '\\') or cjk_count(token)
465
+ not_text = lambda token: not (token.isalnum() or token in ['\\','"']) or cjk_count(token)
457
466
  footnotes = lambda match: ''.join([chr(SUPER[int(i)]) for i in match.group(1)])
458
467
 
459
468
  def process_images(match):
@@ -514,7 +523,6 @@ def line_format(line):
514
523
  state.code_buffer_raw += token
515
524
 
516
525
  elif token == '~~' and (state.in_strikeout or not_text(prev_token)):
517
- print("in strike")
518
526
  state.in_strikeout = not state.in_strikeout
519
527
  result += STRIKEOUT[0] if state.in_strikeout else STRIKEOUT[1]
520
528
 
@@ -718,10 +726,8 @@ def parse(stream):
718
726
  if state.in_code:
719
727
  try:
720
728
  # This is turning it OFF
721
- if not state.code_first_line and (
722
- ( state.in_code == Code.Backtick and line.strip() == "```" ) or
723
- (state.CodeSpaces and state.in_code == Code.Spaces and not line.startswith(' '))
724
- ):
729
+ if ( ( state.in_code == Code.Backtick and line.strip() == "```" ) or
730
+ (state.CodeSpaces and state.in_code == Code.Spaces and not line.startswith(' ')) ):
725
731
  if state.scrape:
726
732
  ext = "sh"
727
733
  try:
@@ -944,6 +950,11 @@ def parse(stream):
944
950
  continue
945
951
 
946
952
  state.where_from = "emit_normal"
953
+
954
+ # if we've gotten to an emit normal then we can assert that our list stack should
955
+ # be empty. This is a hack.
956
+ state.list_item_stack = []
957
+
947
958
  if len(line) == 0: yield ""
948
959
  if len(line) < state.Width:
949
960
  # we want to prevent word wrap
@@ -1010,7 +1021,7 @@ def apply_multipliers(style, name, H, S, V):
1010
1021
  def width_calc():
1011
1022
  if not state.WidthFull or not state.WidthArg:
1012
1023
  if state.WidthArg:
1013
- state.WidthFull = state.WidthArg
1024
+ width = state.WidthArg
1014
1025
  else:
1015
1026
  width = 80
1016
1027
 
@@ -1020,7 +1031,13 @@ def width_calc():
1020
1031
  except (AttributeError, OSError):
1021
1032
  pass
1022
1033
 
1023
- state.WidthFull = width
1034
+
1035
+ # This can't be done because our list item stack can change as well so
1036
+ # unless we want to track that too, we're SOL
1037
+ #if state.WidthFull == width:
1038
+ # return
1039
+
1040
+ state.WidthFull = width
1024
1041
 
1025
1042
  state.Width = state.WidthFull - 2 * Style.Margin
1026
1043
  pre = state.space_left(listwidth=True) if Style.PrettyBroken else ''
@@ -1039,8 +1056,20 @@ def main():
1039
1056
  parser.add_argument("-w", "--width", default="0", help="Set the width WIDTH")
1040
1057
  parser.add_argument("-e", "--exec", help="Wrap a program EXEC for more 'proper' i/o handling")
1041
1058
  parser.add_argument("-s", "--scrape", help="Scrape code snippets to a directory SCRAPE")
1059
+ parser.add_argument("-v", "--version", action="store_true", help="Show version information")
1042
1060
  args = parser.parse_args()
1043
1061
 
1062
+ if args.version:
1063
+ import importlib.metadata
1064
+
1065
+ try:
1066
+ version = importlib.metadata.version("streamdown")
1067
+ except importlib.metadata.PackageNotFoundError:
1068
+ version = "Unknown"
1069
+
1070
+ print(f"Streamdown - {version}")
1071
+ sys.exit(0)
1072
+
1044
1073
  config_toml_path, config_toml_content = ensure_config_file(args.config)
1045
1074
  config = toml.loads(config_toml_content)
1046
1075
  style = toml.loads(default_toml).get('style') | config.get("style", {})
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: streamdown
3
- Version: 0.24.0
3
+ Version: 0.26.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,9 @@
1
+ streamdown/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ streamdown/sd.py,sha256=n4nwjwz6Q62V-nd1p6EMkVsaFcPAa0IfhjFWEjLzF2s,43219
3
+ streamdown/plugins/README.md,sha256=KWqYELs9WkKJmuDzYv3cvPlZMkArsNCBUe4XDoTLjLA,1143
4
+ streamdown/plugins/latex.py,sha256=xZMGMdx_Sw4X1piZejXFHfEG9qazU4fGeceiMI0h13Y,648
5
+ streamdown-0.26.0.dist-info/METADATA,sha256=2VBP-b9B3tJ3DHjq6TfjsE2FJUMwOYPizBTjhlYXPIU,9425
6
+ streamdown-0.26.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
+ streamdown-0.26.0.dist-info/entry_points.txt,sha256=HroKFsFMGf_h9PRTE96NjvjJQWupMW5TGP5RGUr1O_Q,74
8
+ streamdown-0.26.0.dist-info/licenses/LICENSE.MIT,sha256=SnY46EPirUsF20dZDR8HpyVgS2_4Tjxuc6f-4OdqO7U,1070
9
+ streamdown-0.26.0.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- streamdown/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- streamdown/sd.py,sha256=WH56QV5hYGKGT3rEPDuuzDk0lMEsHuLhdVtKvEdvtxE,42334
3
- streamdown/plugins/README.md,sha256=KWqYELs9WkKJmuDzYv3cvPlZMkArsNCBUe4XDoTLjLA,1143
4
- streamdown/plugins/latex.py,sha256=xZMGMdx_Sw4X1piZejXFHfEG9qazU4fGeceiMI0h13Y,648
5
- streamdown-0.24.0.dist-info/METADATA,sha256=yaD-DJOsxp9opkPiVItCGGx4vz5kXG5HoL7T60WOU7E,9658
6
- streamdown-0.24.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
- streamdown-0.24.0.dist-info/entry_points.txt,sha256=HroKFsFMGf_h9PRTE96NjvjJQWupMW5TGP5RGUr1O_Q,74
8
- streamdown-0.24.0.dist-info/licenses/LICENSE.MIT,sha256=SnY46EPirUsF20dZDR8HpyVgS2_4Tjxuc6f-4OdqO7U,1070
9
- streamdown-0.24.0.dist-info/RECORD,,