hyperlist 1.2.0 → 1.2.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 +4 -4
- data/CHANGELOG.md +17 -0
- data/hyperlist +72 -14
- data/hyperlist.gemspec +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e1c9c82471f26ff3363e0d2f801b674798a0ed546f2677c78cb7a72c16e204ba
|
4
|
+
data.tar.gz: e92235369181f6a47ceeba5b01feb6815d4a747df38726a8dc3dcd9f3079b009
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8c282ad98e05174eb963429a36eca1a430b75f2be77d04bd07bb0ed7abf5b68a372c4b84697ae69bcc7f25f4236763ed72909983b9bb8819ec331d3518050bf
|
7
|
+
data.tar.gz: e8ad2e4f881b4082dfe593df2cd23c4ee7a54a9f277b143d013112b0f5c79386a8581812453ce700959a642c689fd2c057e9739f5f3e9578b95ff743a0bb058e
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,23 @@
|
|
2
2
|
|
3
3
|
All notable changes to the HyperList Ruby TUI will be documented in this file.
|
4
4
|
|
5
|
+
## [1.2.2] - 2025-08-20
|
6
|
+
|
7
|
+
### Fixed
|
8
|
+
- Fixed encoding compatibility error when decrypting files (UTF-8 vs ASCII-8BIT)
|
9
|
+
- Force UTF-8 encoding on decrypted content and text processing
|
10
|
+
|
11
|
+
### Added
|
12
|
+
- Auto-fold encrypted files on open for privacy (fold level 0)
|
13
|
+
- Display "folded for privacy" message when opening encrypted files
|
14
|
+
|
15
|
+
## [1.2.1] - 2025-08-20
|
16
|
+
|
17
|
+
### Fixed
|
18
|
+
- Fixed crash when opening encrypted dot files (footer not initialized)
|
19
|
+
- Added password confirmation when encrypting files for the first time
|
20
|
+
- Improved initialization order to ensure UI components are ready before file loading
|
21
|
+
|
5
22
|
## [1.2.0] - 2025-08-20
|
6
23
|
|
7
24
|
### Added
|
data/hyperlist
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
# Check for help/version BEFORE loading any libraries
|
8
8
|
if ARGV[0] == '-h' || ARGV[0] == '--help'
|
9
9
|
puts <<~HELP
|
10
|
-
HyperList v1.2.
|
10
|
+
HyperList v1.2.2 - Terminal User Interface for HyperList files
|
11
11
|
|
12
12
|
USAGE
|
13
13
|
hyperlist [OPTIONS] [FILE]
|
@@ -52,7 +52,7 @@ if ARGV[0] == '-h' || ARGV[0] == '--help'
|
|
52
52
|
HELP
|
53
53
|
exit 0
|
54
54
|
elsif ARGV[0] == '-v' || ARGV[0] == '--version'
|
55
|
-
puts "HyperList v1.2.
|
55
|
+
puts "HyperList v1.2.2"
|
56
56
|
exit 0
|
57
57
|
end
|
58
58
|
|
@@ -72,7 +72,7 @@ class HyperListApp
|
|
72
72
|
include Rcurses::Input
|
73
73
|
include Rcurses::Cursor
|
74
74
|
|
75
|
-
VERSION = "1.2.
|
75
|
+
VERSION = "1.2.2"
|
76
76
|
|
77
77
|
def initialize(filename = nil)
|
78
78
|
@filename = filename ? File.expand_path(filename) : nil
|
@@ -128,15 +128,16 @@ class HyperListApp
|
|
128
128
|
# Debug: uncomment to see terminal size
|
129
129
|
# puts "Terminal size: #{@rows}x#{@cols}"
|
130
130
|
|
131
|
-
#
|
131
|
+
# Setup UI first (to initialize @footer) before loading file
|
132
|
+
setup_ui
|
133
|
+
|
134
|
+
# Load file if provided (after UI is set up)
|
132
135
|
if @filename && File.exist?(@filename)
|
133
136
|
load_file(@filename)
|
134
137
|
else
|
135
138
|
# Start with empty list
|
136
139
|
@items = [{"text" => "New HyperList", "level" => 0, "fold" => false}]
|
137
140
|
end
|
138
|
-
|
139
|
-
setup_ui
|
140
141
|
end
|
141
142
|
|
142
143
|
def setup_ui
|
@@ -197,6 +198,7 @@ class HyperListApp
|
|
197
198
|
@redo_position = []
|
198
199
|
|
199
200
|
# Check if file is encrypted (dot file or encrypted content)
|
201
|
+
is_encrypted = false
|
200
202
|
if is_encrypted_file?(file)
|
201
203
|
if content.start_with?("ENC:")
|
202
204
|
# Whole file is encrypted
|
@@ -207,7 +209,8 @@ class HyperListApp
|
|
207
209
|
return
|
208
210
|
end
|
209
211
|
lines = decrypted_content.split("\n")
|
210
|
-
@message = "File decrypted successfully"
|
212
|
+
@message = "File decrypted successfully (folded for privacy)"
|
213
|
+
is_encrypted = true
|
211
214
|
else
|
212
215
|
# Dot file but not encrypted yet - just load normally
|
213
216
|
lines = content.split("\n")
|
@@ -247,6 +250,17 @@ class HyperListApp
|
|
247
250
|
|
248
251
|
@items = [{"text" => "Empty file", "level" => 0, "fold" => false}] if @items.empty?
|
249
252
|
|
253
|
+
# Auto-fold for privacy/security on encrypted files
|
254
|
+
if is_encrypted
|
255
|
+
@fold_level = 0 # Set fold level to 0 (everything folded)
|
256
|
+
# Fold all items that have children
|
257
|
+
@items.each_with_index do |item, idx|
|
258
|
+
if has_children?(idx, @items)
|
259
|
+
item["fold"] = true
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
250
264
|
# Auto-fold deep levels for large files
|
251
265
|
if large_file
|
252
266
|
auto_fold_deep_levels(3) # Auto-fold everything deeper than level 3
|
@@ -845,6 +859,9 @@ class HyperListApp
|
|
845
859
|
|
846
860
|
# Helper method to safely apply regexes without corrupting ANSI sequences
|
847
861
|
def safe_regex_replace(text, pattern, &block)
|
862
|
+
# Ensure text is UTF-8 encoded
|
863
|
+
text = text.to_s.force_encoding('UTF-8')
|
864
|
+
|
848
865
|
# Find all ANSI sequences and replace with placeholders
|
849
866
|
ansi_sequences = []
|
850
867
|
placeholder_text = text.gsub(/\e\[[0-9;]*m/) do |match|
|
@@ -3107,8 +3124,24 @@ class HyperListApp
|
|
3107
3124
|
end
|
3108
3125
|
|
3109
3126
|
def encrypt_string(text, password = nil)
|
3110
|
-
password
|
3111
|
-
|
3127
|
+
if password.nil? && @encryption_key.nil?
|
3128
|
+
# First time encrypting - ask for password twice
|
3129
|
+
password = prompt_password("Enter encryption password: ")
|
3130
|
+
return nil unless password
|
3131
|
+
|
3132
|
+
confirm = prompt_password("Confirm encryption password: ")
|
3133
|
+
return nil unless confirm
|
3134
|
+
|
3135
|
+
if password != confirm
|
3136
|
+
@message = "Passwords do not match - encryption cancelled"
|
3137
|
+
return nil
|
3138
|
+
end
|
3139
|
+
|
3140
|
+
@encryption_key = password
|
3141
|
+
else
|
3142
|
+
password ||= @encryption_key || prompt_password("Enter encryption password: ")
|
3143
|
+
return nil unless password
|
3144
|
+
end
|
3112
3145
|
|
3113
3146
|
# Store key for session if not already stored
|
3114
3147
|
@encryption_key ||= password
|
@@ -3151,7 +3184,10 @@ class HyperListApp
|
|
3151
3184
|
cipher.key = key
|
3152
3185
|
cipher.iv = iv
|
3153
3186
|
|
3154
|
-
cipher.update(encrypted) + cipher.final
|
3187
|
+
decrypted = cipher.update(encrypted) + cipher.final
|
3188
|
+
# Force UTF-8 encoding on decrypted content
|
3189
|
+
decrypted.force_encoding('UTF-8')
|
3190
|
+
decrypted
|
3155
3191
|
rescue => e
|
3156
3192
|
@message = "Decryption failed. Wrong password?"
|
3157
3193
|
nil
|
@@ -3174,8 +3210,24 @@ class HyperListApp
|
|
3174
3210
|
end
|
3175
3211
|
|
3176
3212
|
def encrypt_file(content, password = nil)
|
3177
|
-
password
|
3178
|
-
|
3213
|
+
if password.nil? && @encryption_key.nil?
|
3214
|
+
# First time encrypting - ask for password twice
|
3215
|
+
password = prompt_password("Enter encryption password: ")
|
3216
|
+
return nil unless password
|
3217
|
+
|
3218
|
+
confirm = prompt_password("Confirm encryption password: ")
|
3219
|
+
return nil unless confirm
|
3220
|
+
|
3221
|
+
if password != confirm
|
3222
|
+
@message = "Passwords do not match - encryption cancelled"
|
3223
|
+
return nil
|
3224
|
+
end
|
3225
|
+
|
3226
|
+
@encryption_key = password
|
3227
|
+
else
|
3228
|
+
password ||= @encryption_key || prompt_password("Enter file encryption password: ")
|
3229
|
+
return nil unless password
|
3230
|
+
end
|
3179
3231
|
|
3180
3232
|
encrypt_string(content, password)
|
3181
3233
|
end
|
@@ -3184,6 +3236,9 @@ class HyperListApp
|
|
3184
3236
|
password ||= @encryption_key || prompt_password("Enter file decryption password: ")
|
3185
3237
|
return nil unless password
|
3186
3238
|
|
3239
|
+
# Store the key for the session so line encryption can use it
|
3240
|
+
@encryption_key = password
|
3241
|
+
|
3187
3242
|
decrypt_string(encrypted_content, password)
|
3188
3243
|
end
|
3189
3244
|
|
@@ -3208,13 +3263,16 @@ class HyperListApp
|
|
3208
3263
|
end
|
3209
3264
|
else
|
3210
3265
|
# Encrypt the line
|
3211
|
-
|
3266
|
+
# Use the existing encryption key if available (from file decryption)
|
3267
|
+
encrypted = encrypt_string(current_text, @encryption_key)
|
3212
3268
|
if encrypted
|
3213
3269
|
save_undo_state
|
3214
3270
|
item["text"] = encrypted
|
3215
3271
|
@encrypted_lines[@current] = true
|
3216
3272
|
@modified = true
|
3217
|
-
@message = "Line encrypted"
|
3273
|
+
@message = "Line encrypted (🔒 indicator shown)"
|
3274
|
+
# Clear the processed cache to force re-rendering
|
3275
|
+
@processed_cache = {}
|
3218
3276
|
else
|
3219
3277
|
@message = "Encryption cancelled"
|
3220
3278
|
end
|
data/hyperlist.gemspec
CHANGED