marvi 0.4.1 → 0.4.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 519a600dd8ba2e4c6934cf57f37914337ce252ced2a51d6b05dff2ab2c1dda4b
4
- data.tar.gz: '02669ac614cde421459555a5068429e1371036dd90eb549f5a90d6f3e3aea90c'
3
+ metadata.gz: d5ff0488e214dd427a028dabe9d240bee43e48ac27cef895e7f8584b41695435
4
+ data.tar.gz: 71dcd3de576d8926b90cae6ec4b79732be3627b85922351585b624b064eafb94
5
5
  SHA512:
6
- metadata.gz: 37a67589e93f21f02d2c7cec09130e2a63ce83e88ebe21c61cf643b4810506ff4ece12ca39d8c36a40cbccaca35ecf8984e1c8276f953b0e17bf2b9caf4f98de
7
- data.tar.gz: 12fa9234e6fb3dd1b13b72b5008a239acea242b049ae4086d6e2a8565435b4727fd5850c5766d79f05bbc48332719f7a2b97609725c8834ca1f6083d4a7acf02
6
+ metadata.gz: 1f90d2999b6336d1fa26f8ef441c8e51e551f4f7d229633053acc9ab8418fe115bcd6ea3f8fa3b67ce678781b29198acc33fd1ed69f591611a47bc97b456901c
7
+ data.tar.gz: 82bcdfbe5166bcd2f48d2367da468df0290c89e831d16fa06dced445dba98a2ba0846c659a87e9f69a1dd2e68c900f9cccdaaa57790bb0f35ddcb2c4b8d8dc0e
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.4.2] - 2026-05-31
4
+
5
+ - Add left/right padding in the curses pager so content no longer sits flush against the terminal edges. Padding scales with terminal width.
6
+ - Render every line of a multi-line blockquote with its `│ ` prefix.
7
+ - Stop emitting an empty `│ ` line at the end of blockquotes.
8
+ - Collapse consecutive blank lines so block-level elements are separated by a single blank line.
9
+
3
10
  ## [0.4.1] - 2026-05-26
4
11
 
5
12
  - Wrap long text in bulleted/ordered lists, paragraphs, headers, and blockquotes so it no longer overflows the terminal width. List items and headers use a hanging indent for continuation lines. (#1)
@@ -16,7 +16,7 @@ module Marvi
16
16
  doc = Kramdown::Document.new(markdown, input: "GFM")
17
17
  lines = render_block(doc.root)
18
18
  lines.pop while lines.last&.plain_text&.empty?
19
- lines
19
+ collapse_consecutive_blanks(lines)
20
20
  end
21
21
 
22
22
  private
@@ -131,9 +131,26 @@ module Marvi
131
131
  @max_width = [saved_width - prefix_width, MIN_COL_WIDTH].max
132
132
  inner = el.children.flat_map { |child| render_block(child) }
133
133
  @max_width = saved_width
134
+ # Trim trailing blanks and collapse runs of blanks so the │ prefix doesn't produce
135
+ # dangling/duplicated "│ " lines (kramdown emits both :p trailing blanks and explicit
136
+ # :blank elements between siblings).
137
+ inner.pop while inner.last&.plain_text&.empty?
138
+ inner = collapse_consecutive_blanks(inner)
134
139
  inner.map { |line| RichLine.new([prefix] + line.spans, source_line: line.source_line) } + [RichLine.blank]
135
140
  end
136
141
 
142
+ def collapse_consecutive_blanks(lines)
143
+ out = []
144
+ prev_blank = false
145
+ lines.each do |line|
146
+ is_blank = line.plain_text.empty?
147
+ next if is_blank && prev_blank
148
+ out << line
149
+ prev_blank = is_blank
150
+ end
151
+ out
152
+ end
153
+
137
154
  def render_table(el)
138
155
  src = el.options[:location]
139
156
  rows = el.children.flat_map(&:children)
@@ -210,34 +227,43 @@ module Marvi
210
227
  lines = [[]]
211
228
  current_width = 0
212
229
  spans.each do |span|
213
- text = span.text.dup
214
- until text.empty?
215
- remaining = width - current_width
216
- if remaining <= 0
230
+ # Split on \n so embedded hard line breaks become separate RichLines downstream,
231
+ # otherwise Curses.addstr resets the cursor to column 0 and bypasses padding/prefix.
232
+ parts = span.text.split("\n", -1)
233
+ parts.each_with_index do |part, idx|
234
+ if idx > 0 && !lines.last.empty?
217
235
  lines << []
218
236
  current_width = 0
219
- remaining = width
220
- end
221
- taken = 0
222
- chunk_width = 0
223
- text.each_char do |c|
224
- cw = Unicode::DisplayWidth.of(c)
225
- break if chunk_width + cw > remaining
226
- chunk_width += cw
227
- taken += c.bytesize
228
- end
229
- if taken.zero?
230
- first_char = text.each_char.first
231
- taken = first_char.bytesize
232
- chunk_width = Unicode::DisplayWidth.of(first_char)
233
237
  end
234
- chunk = text.byteslice(0, taken)
235
- text = text.byteslice(taken..) || ""
236
- lines.last << Span.new(text: chunk, bold: span.bold, italic: span.italic, color: span.color, bg_color: span.bg_color)
237
- current_width += chunk_width
238
- unless text.empty?
239
- lines << []
240
- current_width = 0
238
+ text = part.dup
239
+ until text.empty?
240
+ remaining = width - current_width
241
+ if remaining <= 0
242
+ lines << []
243
+ current_width = 0
244
+ remaining = width
245
+ end
246
+ taken = 0
247
+ chunk_width = 0
248
+ text.each_char do |c|
249
+ cw = Unicode::DisplayWidth.of(c)
250
+ break if chunk_width + cw > remaining
251
+ chunk_width += cw
252
+ taken += c.bytesize
253
+ end
254
+ if taken.zero?
255
+ first_char = text.each_char.first
256
+ taken = first_char.bytesize
257
+ chunk_width = Unicode::DisplayWidth.of(first_char)
258
+ end
259
+ chunk = text.byteslice(0, taken)
260
+ text = text.byteslice(taken..) || ""
261
+ lines.last << Span.new(text: chunk, bold: span.bold, italic: span.italic, color: span.color, bg_color: span.bg_color)
262
+ current_width += chunk_width
263
+ unless text.empty?
264
+ lines << []
265
+ current_width = 0
266
+ end
241
267
  end
242
268
  end
243
269
  end
@@ -23,6 +23,9 @@ module Marvi
23
23
  CTRL_D = 4
24
24
  CTRL_U = 21
25
25
 
26
+ MIN_HORIZONTAL_PADDING = 2
27
+ HORIZONTAL_PADDING_DIVISOR = 12
28
+
26
29
  def render(markdown, file: nil)
27
30
  @file = file
28
31
  @markdown = markdown
@@ -127,7 +130,17 @@ module Marvi
127
130
  end
128
131
 
129
132
  def rewalk
130
- @lines = ASTWalker.new.walk(@markdown, max_width: ::Curses.cols)
133
+ @lines = ASTWalker.new.walk(@markdown, max_width: content_width)
134
+ end
135
+
136
+ def horizontal_padding
137
+ cols = ::Curses.cols
138
+ return 0 if cols <= MIN_HORIZONTAL_PADDING * 2
139
+ [MIN_HORIZONTAL_PADDING, cols / HORIZONTAL_PADDING_DIVISOR].max
140
+ end
141
+
142
+ def content_width
143
+ [::Curses.cols - horizontal_padding * 2, 1].max
131
144
  end
132
145
 
133
146
  def reload_from_key
@@ -214,8 +227,9 @@ module Marvi
214
227
 
215
228
  def draw
216
229
  ::Curses.clear
230
+ padding = horizontal_padding
217
231
  visible_lines.each_with_index do |line, row|
218
- ::Curses.setpos(row, 0)
232
+ ::Curses.setpos(row, padding)
219
233
  render_line(line)
220
234
  end
221
235
  draw_status_bar
data/lib/marvi/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Marvi
4
- VERSION = "0.4.1"
4
+ VERSION = "0.4.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marvi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mitsutaka Mimura