markdown-run 0.1.6 → 0.1.7
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 +4 -0
- data/README.md +20 -0
- data/exe/markdown-run +47 -5
- data/lib/markdown/run/version.rb +1 -1
- data/test_markdown_exec.rb +70 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c11a9addb3e251e9830fe2126d2d752dc8c04c879b607d1ee0ad80998d51b294
|
4
|
+
data.tar.gz: '014954e8178d28729dfa86350a9e92aa91010892e6d177a5f7616dfd0e9ad72b'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a26f680f607d52d7ceb0b0f31cca84af2a811ed2a70f6f73f9ab6ae3f9032f9135943c9e765df4d9714cbbd766179de14bab8006148e1d65d27a26388dd935c
|
7
|
+
data.tar.gz: 3ed109437211b62afd2dcdf1469e3103db9bd36a13be207f0ea636d67163c269e4a199e9a4b901ed4f7756319b5aa9c20f00e7613106be463c5139965f209fbf
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -8,6 +8,15 @@ Do not rerun code blocks if result block is present.
|
|
8
8
|
|
9
9
|
Meant to be used from the terminal or from an editor with a keybinding.
|
10
10
|
|
11
|
+
Supported languages:
|
12
|
+
|
13
|
+
- Javascript
|
14
|
+
- Ruby
|
15
|
+
- sqlite3
|
16
|
+
- postgresql
|
17
|
+
- bash
|
18
|
+
- zsh
|
19
|
+
|
11
20
|
## Installation
|
12
21
|
|
13
22
|
`gem install markdown-run`
|
@@ -43,9 +52,20 @@ example vscode keybinding
|
|
43
52
|
},
|
44
53
|
```
|
45
54
|
|
55
|
+
### Code block options
|
56
|
+
|
57
|
+
- `rerun=true` or `rerun=false` for a code block to rerun or skip execution. `rerun=true` is the default if not specified
|
58
|
+
|
59
|
+
example:
|
60
|
+
|
61
|
+
```js rerun=false
|
62
|
+
console.log("hello world");
|
63
|
+
```
|
64
|
+
|
46
65
|
## Frontmatter
|
47
66
|
|
48
67
|
You can add a yaml frontmatter to redefine code block behavior.
|
68
|
+
|
49
69
|
For example sql blocks run by default against sqlite
|
50
70
|
To have them run with postgres you can add at the top of your markdown file:
|
51
71
|
|
data/exe/markdown-run
CHANGED
@@ -88,6 +88,7 @@ class MarkdownProcessor
|
|
88
88
|
@state = :outside_code_block
|
89
89
|
@current_block_lang = ""
|
90
90
|
@current_code_content = ""
|
91
|
+
@current_block_rerun = false
|
91
92
|
@aliases = {}
|
92
93
|
end
|
93
94
|
|
@@ -193,6 +194,16 @@ class MarkdownProcessor
|
|
193
194
|
line && line.strip == ""
|
194
195
|
end
|
195
196
|
|
197
|
+
def parse_rerun_option(options_string)
|
198
|
+
return false unless options_string
|
199
|
+
|
200
|
+
# Match rerun=true or rerun=false
|
201
|
+
match = options_string.match(/rerun\s*=\s*(true|false)/i)
|
202
|
+
return false unless match
|
203
|
+
|
204
|
+
match[1].downcase == "true"
|
205
|
+
end
|
206
|
+
|
196
207
|
def safe_enum_operation(file_enum, operation)
|
197
208
|
file_enum.send(operation)
|
198
209
|
rescue StopIteration
|
@@ -221,11 +232,12 @@ class MarkdownProcessor
|
|
221
232
|
def handle_outside_code_block(current_line, file_enum)
|
222
233
|
if current_line.match?(/^```ruby\s+RESULT$/i)
|
223
234
|
handle_existing_ruby_result_block(current_line, file_enum)
|
224
|
-
elsif (match_data = current_line.match(/^```(\w+)
|
235
|
+
elsif (match_data = current_line.match(/^```(\w+)(?:\s+(.*))?$/i))
|
225
236
|
lang = match_data[1].downcase
|
237
|
+
options_string = match_data[2]
|
226
238
|
resolved_lang = resolve_language(lang)
|
227
239
|
if SUPPORTED_LANGUAGES.key?(resolved_lang)
|
228
|
-
start_code_block(current_line, lang)
|
240
|
+
start_code_block(current_line, lang, options_string)
|
229
241
|
else
|
230
242
|
@output_lines << current_line
|
231
243
|
end
|
@@ -255,9 +267,10 @@ class MarkdownProcessor
|
|
255
267
|
@state = :inside_result_block
|
256
268
|
end
|
257
269
|
|
258
|
-
def start_code_block(current_line, lang)
|
270
|
+
def start_code_block(current_line, lang, options_string = nil)
|
259
271
|
@output_lines << current_line
|
260
272
|
@current_block_lang = resolve_language(lang)
|
273
|
+
@current_block_rerun = parse_rerun_option(options_string)
|
261
274
|
@state = :inside_code_block
|
262
275
|
@current_code_content = ""
|
263
276
|
end
|
@@ -273,6 +286,7 @@ class MarkdownProcessor
|
|
273
286
|
decision = decide_execution(file_enum)
|
274
287
|
|
275
288
|
if decision[:execute]
|
289
|
+
# If we consumed lines for rerun, don't add them to output (they'll be replaced)
|
276
290
|
execute_and_add_result(decision[:blank_line])
|
277
291
|
else
|
278
292
|
skip_and_pass_through_result(decision[:lines_to_pass_through], file_enum)
|
@@ -286,13 +300,28 @@ class MarkdownProcessor
|
|
286
300
|
expected_header_regex = result_block_regex(@current_block_lang)
|
287
301
|
|
288
302
|
if line_matches_pattern?(peek1, expected_header_regex)
|
289
|
-
|
303
|
+
# If rerun=true, execute even if result block exists
|
304
|
+
if @current_block_rerun
|
305
|
+
# Consume the existing result block and execute
|
306
|
+
consumed_lines = [file_enum.next]
|
307
|
+
consume_existing_result_block(file_enum, consumed_lines)
|
308
|
+
return { execute: true, consumed_lines: consumed_lines }
|
309
|
+
else
|
310
|
+
return { execute: false, lines_to_pass_through: [file_enum.next] }
|
311
|
+
end
|
290
312
|
elsif is_blank_line?(peek1)
|
291
313
|
consumed_blank_line = file_enum.next
|
292
314
|
peek2 = peek_next_line(file_enum)
|
293
315
|
|
294
316
|
if line_matches_pattern?(peek2, expected_header_regex)
|
295
|
-
|
317
|
+
if @current_block_rerun
|
318
|
+
# Consume the blank line and existing result block, then execute
|
319
|
+
consumed_lines = [consumed_blank_line, file_enum.next]
|
320
|
+
consume_existing_result_block(file_enum, consumed_lines)
|
321
|
+
return { execute: true, consumed_lines: consumed_lines, blank_line: consumed_blank_line }
|
322
|
+
else
|
323
|
+
return { execute: false, lines_to_pass_through: [consumed_blank_line, file_enum.next] }
|
324
|
+
end
|
296
325
|
else
|
297
326
|
return { execute: true, blank_line: consumed_blank_line }
|
298
327
|
end
|
@@ -334,9 +363,22 @@ class MarkdownProcessor
|
|
334
363
|
end
|
335
364
|
end
|
336
365
|
|
366
|
+
def consume_existing_result_block(file_enum, consumed_lines)
|
367
|
+
begin
|
368
|
+
loop do
|
369
|
+
result_block_line = file_enum.next
|
370
|
+
consumed_lines << result_block_line
|
371
|
+
break if is_block_end?(result_block_line)
|
372
|
+
end
|
373
|
+
rescue StopIteration
|
374
|
+
warn "Warning: End of file reached while consuming existing result block for rerun."
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
337
378
|
def reset_code_block_state
|
338
379
|
@state = :outside_code_block
|
339
380
|
@current_code_content = ""
|
381
|
+
@current_block_rerun = false
|
340
382
|
end
|
341
383
|
end
|
342
384
|
|
data/lib/markdown/run/version.rb
CHANGED
data/test_markdown_exec.rb
CHANGED
@@ -131,4 +131,74 @@ class TestMarkdownExec < Minitest::Test
|
|
131
131
|
assert file_content.include?("```RESULT\n"), "RESULT block should be created for aliased language"
|
132
132
|
assert file_content.include?("aliased to psql"), "Output should contain the expected result"
|
133
133
|
end
|
134
|
+
|
135
|
+
def test_rerun_functionality
|
136
|
+
# Test 1: Default behavior (no rerun option) should skip existing result
|
137
|
+
md_content_with_result = <<~MARKDOWN
|
138
|
+
```ruby
|
139
|
+
puts "Should not change: \#{Time.now.to_i}"
|
140
|
+
```
|
141
|
+
|
142
|
+
```ruby RESULT
|
143
|
+
Should not change: 999999999
|
144
|
+
```
|
145
|
+
MARKDOWN
|
146
|
+
create_md_file(md_content_with_result)
|
147
|
+
process_markdown_file_main(@test_md_file_path)
|
148
|
+
|
149
|
+
file_content = read_md_file
|
150
|
+
assert file_content.include?("Should not change: 999999999"), "Default behavior should preserve existing result"
|
151
|
+
refute file_content.match?(/Should not change: (?!999999999)\d+/), "Default behavior should not generate new timestamp"
|
152
|
+
|
153
|
+
# Test 2: rerun=false should skip existing result
|
154
|
+
md_content_rerun_false = <<~MARKDOWN
|
155
|
+
```ruby rerun=false
|
156
|
+
puts "Should not change either: \#{Time.now.to_i}"
|
157
|
+
```
|
158
|
+
|
159
|
+
```ruby RESULT
|
160
|
+
Should not change either: 888888888
|
161
|
+
```
|
162
|
+
MARKDOWN
|
163
|
+
create_md_file(md_content_rerun_false)
|
164
|
+
process_markdown_file_main(@test_md_file_path)
|
165
|
+
|
166
|
+
file_content = read_md_file
|
167
|
+
assert file_content.include?("Should not change either: 888888888"), "rerun=false should preserve existing result"
|
168
|
+
refute file_content.match?(/Should not change either: (?!888888888)\d+/), "rerun=false should not generate new timestamp"
|
169
|
+
|
170
|
+
# Test 3: rerun=true should replace existing result
|
171
|
+
md_content_rerun_true = <<~MARKDOWN
|
172
|
+
```ruby rerun=true
|
173
|
+
puts "Should change: \#{Time.now.to_i}"
|
174
|
+
```
|
175
|
+
|
176
|
+
```ruby RESULT
|
177
|
+
Should change: 777777777
|
178
|
+
```
|
179
|
+
MARKDOWN
|
180
|
+
create_md_file(md_content_rerun_true)
|
181
|
+
process_markdown_file_main(@test_md_file_path)
|
182
|
+
|
183
|
+
file_content = read_md_file
|
184
|
+
refute file_content.include?("Should change: 777777777"), "rerun=true should replace existing result"
|
185
|
+
assert file_content.match?(/Should change: \d+/), "rerun=true should generate new result with actual timestamp"
|
186
|
+
|
187
|
+
# Test 4: rerun=true with blank line before result block
|
188
|
+
md_content_rerun_true_blank = <<~MARKDOWN
|
189
|
+
```ruby rerun=true
|
190
|
+
puts "Should also change: \#{Time.now.to_i}"
|
191
|
+
```
|
192
|
+
|
193
|
+
```ruby RESULT
|
194
|
+
Should also change: 666666666
|
195
|
+
```
|
196
|
+
MARKDOWN
|
197
|
+
create_md_file(md_content_rerun_true_blank)
|
198
|
+
process_markdown_file_main(@test_md_file_path)
|
199
|
+
|
200
|
+
file_content = read_md_file
|
201
|
+
refute file_content.include?("Should also change: 666666666"), "rerun=true with blank line should replace existing result"
|
202
|
+
assert file_content.match?(/Should also change: \d+/), "rerun=true with blank line should generate new result"
|
203
|
+
end
|
134
204
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: markdown-run
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aurélien Bottazini
|
@@ -57,11 +57,11 @@ files:
|
|
57
57
|
- lib/markdown/run/version.rb
|
58
58
|
- markdown-run-sample.md
|
59
59
|
- test_markdown_exec.rb
|
60
|
-
homepage: https://
|
60
|
+
homepage: https://github.com/aurelienbottazini/markdown-run
|
61
61
|
licenses:
|
62
62
|
- MIT
|
63
63
|
metadata:
|
64
|
-
homepage_uri: https://
|
64
|
+
homepage_uri: https://github.com/aurelienbottazini/markdown-run
|
65
65
|
source_code_uri: https://github.com/aurelienbottazini/markdown-run
|
66
66
|
changelog_uri: https://github.com/aurelienbottazini/markdown-run/blob/main/CHANGELOG.md
|
67
67
|
post_install_message:
|