Class: Scriptorium::API
Instance Attribute Summary collapse
Instance Method Summary
collapse
-
#apply_theme(theme) ⇒ Object
-
#create_draft(title: nil, body: nil, views: nil, tags: nil, blurb: nil) ⇒ Object
-
#create_post(title, body, views: nil, tags: nil, blurb: nil) ⇒ Object
Post creation with convenience defaults.
-
#create_repo(path) ⇒ Object
-
#create_view(name, title, subtitle = "", theme: "standard") ⇒ Object
-
#define_invariants ⇒ Object
-
#delete_draft(draft_path) ⇒ Object
-
#delete_post(id) ⇒ Object
-
#draft(title: nil, body: nil, views: nil, tags: nil, blurb: nil) ⇒ Object
-
#drafts ⇒ Object
-
#edit_config(view = nil) ⇒ Object
-
#edit_deploy_config ⇒ Object
-
#edit_file(path) ⇒ Object
-
#edit_layout(view = nil) ⇒ Object
Convenience file editing methods.
-
#edit_post(post_id) ⇒ Object
-
#edit_repo_config ⇒ Object
-
#edit_widget_data(view = nil, widget) ⇒ Object
-
#finish_draft(draft_path) ⇒ Object
-
#generate_front_page(view = nil) ⇒ Object
-
#generate_post(post_id) ⇒ Object
-
#generate_post_index(view = nil) ⇒ Object
-
#generate_view(view = nil) ⇒ Object
-
#generate_widget(widget_name) ⇒ Object
-
#get_published_posts(view = nil) ⇒ Object
-
#initialize(testmode: false) ⇒ API
constructor
-
#link_post(id, view = nil) ⇒ Object
-
#lookup_view(view_name) ⇒ Object
-
#open_repo(path) ⇒ Object
-
#post(id) ⇒ Object
-
#post_add_tag(id, tag) ⇒ Object
-
#post_add_view(id, view) ⇒ Object
-
#post_attrs(post_id, *keys) ⇒ Object
-
#post_published?(num) ⇒ Boolean
-
#post_remove_tag(id, tag) ⇒ Object
-
#post_remove_view(id, view) ⇒ Object
-
#posts(view = nil) ⇒ Object
-
#publish_post(num) ⇒ Object
-
#repo_exists?(path) ⇒ Boolean
-
#root ⇒ Object
-
#search_posts(**criteria) ⇒ Object
-
#select_posts(&block) ⇒ Object
Post selection and search.
-
#themes_available ⇒ Object
-
#undelete_post(id) ⇒ Object
-
#unlink_post(id, view = nil) ⇒ Object
-
#update_post(id, fields) ⇒ Object
-
#version ⇒ Object
-
#view(name = nil) ⇒ Object
-
#views ⇒ Object
-
#views_for(post_or_id) ⇒ Object
-
#widgets_available ⇒ Object
Methods included from Contract
#assume, #check_invariants, enabled?, #invariant, #verify
Methods included from Helpers
#cf_time, #change_config, #clean_slugify, #copy_gem_asset_to_user, #copy_to_clipboard, #d4, #escape_html, #generate_missing_asset_svg, #get_asset_path, #get_from_clipboard, #getvars, #list_gem_assets, #make_dir, #make_tree, #need, #read_commented_file, #read_file, #see, #see_file, #slugify, #substitute, #system!, #view_dir, #write_file, #write_file!, #ymdhms
Methods included from Exceptions
#make_exception
Constructor Details
#initialize(testmode: false) ⇒ API
Returns a new instance of API.
14
15
16
17
18
19
20
21
22
23
|
# File 'lib/scriptorium/api.rb', line 14
def initialize(testmode: false)
assume { [true, false].include?(testmode) }
@testing = testmode
@repo = nil
define_invariants
verify { @testing == testmode }
check_invariants
end
|
Instance Attribute Details
#current_view ⇒ Object
Returns the value of attribute current_view.
6
7
8
|
# File 'lib/scriptorium/api.rb', line 6
def current_view
@current_view
end
|
#repo ⇒ Object
Returns the value of attribute repo.
6
7
8
|
# File 'lib/scriptorium/api.rb', line 6
def repo
@repo
end
|
Instance Method Details
#apply_theme(theme) ⇒ Object
79
80
81
|
# File 'lib/scriptorium/api.rb', line 79
def apply_theme(theme)
@repo.view.apply_theme(theme)
end
|
#create_draft(title: nil, body: nil, views: nil, tags: nil, blurb: nil) ⇒ Object
146
147
148
149
150
151
152
153
154
155
156
157
|
# File 'lib/scriptorium/api.rb', line 146
def create_draft(title: nil, body: nil, views: nil, tags: nil, blurb: nil)
views ||= @repo.current_view&.name
raise "No view specified and no current view set" if views.nil?
@repo.create_draft(
title: title,
body: body,
views: views,
tags: tags,
blurb: blurb
)
end
|
#create_post(title, body, views: nil, tags: nil, blurb: nil) ⇒ Object
Post creation with convenience defaults
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
# File 'lib/scriptorium/api.rb', line 107
def create_post(title, body, views: nil, tags: nil, blurb: nil)
check_invariants
assume { title.is_a?(String) }
assume { body.is_a?(String) }
assume { views.nil? || views.is_a?(String) || views.is_a?(Array) }
assume { tags.nil? || tags.is_a?(String) || tags.is_a?(Array) }
assume { blurb.nil? || blurb.is_a?(String) }
assume { @repo.is_a?(Scriptorium::Repo) }
views ||= @repo.current_view&.name
raise "No view specified and no current view set" if views.nil?
post = @repo.create_post(
title: title,
body: body,
views: views,
tags: tags,
blurb: blurb
)
verify { post.is_a?(Scriptorium::Post) }
check_invariants
post
end
|
#create_repo(path) ⇒ Object
29
30
31
32
33
34
35
36
37
38
39
|
# File 'lib/scriptorium/api.rb', line 29
def create_repo(path)
check_invariants
assume { path.is_a?(String) && !path.empty? }
raise RepoDirAlreadyExists if repo_exists?(path)
Scriptorium::Repo.create(path)
@repo = Scriptorium::Repo.open(path)
verify { @repo.is_a?(Scriptorium::Repo) }
check_invariants
end
|
#create_view(name, title, subtitle = "", theme: "standard") ⇒ Object
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
# File 'lib/scriptorium/api.rb', line 52
def create_view(name, title, subtitle = "", theme: "standard")
check_invariants
assume { name.is_a?(String) }
assume { title.is_a?(String) }
assume { subtitle.is_a?(String) }
assume { theme.is_a?(String) }
assume { @repo.is_a?(Scriptorium::Repo) }
@repo.create_view(name, title, subtitle, theme: theme)
verify { @repo.is_a?(Scriptorium::Repo) }
check_invariants
self
end
|
#define_invariants ⇒ Object
9
10
11
12
|
# File 'lib/scriptorium/api.rb', line 9
def define_invariants
invariant { [true, false].include?(@testing) }
invariant { @repo.nil? || @repo.is_a?(Scriptorium::Repo) }
end
|
#delete_draft(draft_path) ⇒ Object
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
|
# File 'lib/scriptorium/api.rb', line 526
def delete_draft(draft_path)
raise "Draft path cannot be nil" if draft_path.nil?
raise "Draft path cannot be empty" if draft_path.to_s.strip.empty?
unless draft_path.to_s.end_with?('-draft.lt3')
raise "Not a valid draft file: #{draft_path}"
end
unless File.exist?(draft_path)
raise "Draft file not found: #{draft_path}"
end
File.delete(draft_path)
true
end
|
#delete_post(id) ⇒ Object
235
236
237
238
239
240
241
242
243
244
|
# File 'lib/scriptorium/api.rb', line 235
def delete_post(id)
post = @repo.post(id)
old_path = @repo.root/:posts/post.num
new_path = @repo.root/:posts/"_#{post.num}"
FileUtils.mv(old_path, new_path)
post.meta["post.deleted"] = "true"
post.save_metadata
end
|
#draft(title: nil, body: nil, views: nil, tags: nil, blurb: nil) ⇒ Object
133
134
135
136
137
138
139
140
141
142
143
144
|
# File 'lib/scriptorium/api.rb', line 133
def draft(title: nil, body: nil, views: nil, tags: nil, blurb: nil)
views ||= @repo.current_view&.name
raise "No view specified and no current view set" if views.nil?
@repo.create_draft(
title: title,
body: body,
views: views,
tags: tags,
blurb: blurb
)
end
|
#drafts ⇒ Object
513
514
515
516
517
518
519
520
521
522
523
524
|
# File 'lib/scriptorium/api.rb', line 513
def drafts
drafts_dir = @repo.root/:drafts
return [] unless Dir.exist?(drafts_dir)
draft_files = Dir.children(drafts_dir).select { |f| f.end_with?('-draft.lt3') }
draft_files.map do |filename|
path = drafts_dir/filename
title = (path)
{ path: path, title: title }
end
end
|
#edit_config(view = nil) ⇒ Object
402
403
404
405
406
|
# File 'lib/scriptorium/api.rb', line 402
def edit_config(view = nil)
view ||= @repo.current_view&.name
raise "No view specified and no current view set" if view.nil?
edit_file("views/#{view}/config.txt")
end
|
#edit_deploy_config ⇒ Object
419
420
421
|
# File 'lib/scriptorium/api.rb', line 419
def edit_deploy_config
edit_file("config/deploy.txt")
end
|
#edit_file(path) ⇒ Object
437
438
439
440
441
442
443
444
|
# File 'lib/scriptorium/api.rb', line 437
def edit_file(path)
raise CannotEditFilePathNil if path.nil?
raise CannotEditFilePathEmpty if path.to_s.strip.empty?
editor = ENV['EDITOR'] || 'vim'
system!(editor, path)
end
|
#edit_layout(view = nil) ⇒ Object
Convenience file editing methods
396
397
398
399
400
|
# File 'lib/scriptorium/api.rb', line 396
def edit_layout(view = nil)
view ||= @repo.current_view&.name
raise "No view specified and no current view set" if view.nil?
edit_file("views/#{view}/layout.txt")
end
|
#edit_post(post_id) ⇒ Object
423
424
425
426
427
428
429
430
431
432
433
|
# File 'lib/scriptorium/api.rb', line 423
def edit_post(post_id)
post = @repo.post(post_id)
source_path = "posts/#{post.num}/source.lt3"
body_path = "posts/#{post.num}/body.html"
if File.exist?(source_path)
edit_file(source_path)
else
edit_file(body_path)
end
end
|
#edit_repo_config ⇒ Object
415
416
417
|
# File 'lib/scriptorium/api.rb', line 415
def edit_repo_config
edit_file("config/repo.txt")
end
|
408
409
410
411
412
413
|
# File 'lib/scriptorium/api.rb', line 408
def edit_widget_data(view = nil, widget)
view ||= @repo.current_view&.name
raise "No view specified and no current view set" if view.nil?
raise "Widget name cannot be nil" if widget.nil?
edit_file("views/#{view}/widgets/#{widget}/list.txt")
end
|
#finish_draft(draft_path) ⇒ Object
159
160
161
|
# File 'lib/scriptorium/api.rb', line 159
def finish_draft(draft_path)
@repo.finish_draft(draft_path)
end
|
#generate_front_page(view = nil) ⇒ Object
164
165
166
167
168
169
|
# File 'lib/scriptorium/api.rb', line 164
def generate_front_page(view = nil)
view ||= @repo.current_view&.name
raise "No view specified and no current view set" if view.nil?
@repo.generate_front_page(view)
end
|
#generate_post(post_id) ⇒ Object
178
179
180
181
182
183
184
185
186
187
188
189
190
191
|
# File 'lib/scriptorium/api.rb', line 178
def generate_post(post_id)
post_dir = @repo.root/:posts/d4(post_id)
if Dir.exist?(post_dir)
@repo.generate_post(post_id)
else
post = @repo.post(post_id)
raise "Post not found" if post.nil?
@repo.generate_post(post_id)
end
end
|
#generate_post_index(view = nil) ⇒ Object
171
172
173
174
175
176
|
# File 'lib/scriptorium/api.rb', line 171
def generate_post_index(view = nil)
view ||= @repo.current_view&.name
raise "No view specified and no current view set" if view.nil?
@repo.generate_post_index(view)
end
|
#generate_view(view = nil) ⇒ Object
502
503
504
505
506
507
508
|
# File 'lib/scriptorium/api.rb', line 502
def generate_view(view = nil)
view ||= @repo.current_view&.name
raise "No view specified and no current view set" if view.nil?
@repo.generate_front_page(view)
true
end
|
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
|
# File 'lib/scriptorium/api.rb', line 363
def generate_widget(widget_name)
raise "No current view set" if @repo.current_view.nil?
raise "Widget name cannot be nil" if widget_name.nil?
raise "Widget name cannot be empty" if widget_name.to_s.strip.empty?
unless widget_name.to_s.match?(/^[a-zA-Z0-9_]+$/)
raise "Invalid widget name: #{widget_name} (must be alphanumeric and underscore only)"
end
widget_class_name = widget_name.to_s.capitalize
begin
widget_class = eval("Scriptorium::Widget::#{widget_class_name}")
rescue NameError
raise "Widget class not found: Scriptorium::Widget::#{widget_class_name}"
end
widget = widget_class.new(@repo, @repo.current_view)
widget.generate
true
end
|
#get_published_posts(view = nil) ⇒ Object
214
215
216
217
|
# File 'lib/scriptorium/api.rb', line 214
def get_published_posts(view = nil)
view ||= @repo.current_view&.name
@repo.get_published_posts(view)
end
|
#link_post(id, view = nil) ⇒ Object
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
|
# File 'lib/scriptorium/api.rb', line 280
def link_post(id, view = nil)
view ||= @repo.current_view&.name
raise "No view specified and no current view set" if view.nil?
post = @repo.post(id)
raise "Post not found" if post.nil?
current_views = post.views.strip.split(/\s+/)
new_views = current_views.include?(view) ? current_views : current_views + [view]
result = update_post(id, {views: new_views})
@repo.generate_post(id) if result
result
end
|
#lookup_view(view_name) ⇒ Object
97
98
99
|
# File 'lib/scriptorium/api.rb', line 97
def lookup_view(target)
@repo&.lookup_view(target)
end
|
#open_repo(path) ⇒ Object
41
42
43
44
45
46
47
48
49
|
# File 'lib/scriptorium/api.rb', line 41
def open_repo(path)
check_invariants
assume { path.is_a?(String) && !path.empty? }
@repo = Scriptorium::Repo.open(path)
verify { @repo.is_a?(Scriptorium::Repo) }
check_invariants
end
|
#post(id) ⇒ Object
230
231
232
|
# File 'lib/scriptorium/api.rb', line 230
def post(id)
@repo.post(id)
end
|
#post_add_tag(id, tag) ⇒ Object
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
|
# File 'lib/scriptorium/api.rb', line 309
def post_add_tag(id, tag)
post = @repo.post(id)
raise "Post not found" if post.nil?
current_tags = post.tags.strip.split(/,\s*/)
new_tags = current_tags.include?(tag) ? current_tags : current_tags + [tag]
result = update_post(id, {tags: new_tags})
@repo.generate_post(id) if result
result
end
|
#post_add_view(id, view) ⇒ Object
297
298
299
300
301
|
# File 'lib/scriptorium/api.rb', line 297
def post_add_view(id, view)
view_name = view.is_a?(String) ? view : view.name
link_post(id, view_name)
end
|
#post_attrs(post_id, *keys) ⇒ Object
225
226
227
228
|
# File 'lib/scriptorium/api.rb', line 225
def post_attrs(post_id, *keys)
post = post_id.is_a?(Integer) ? @repo.post(post_id) : post_id
post.attrs(*keys)
end
|
#post_published?(num) ⇒ Boolean
210
211
212
|
# File 'lib/scriptorium/api.rb', line 210
def post_published?(num)
@repo.post_published?(num)
end
|
#post_remove_tag(id, tag) ⇒ Object
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
|
# File 'lib/scriptorium/api.rb', line 329
def post_remove_tag(id, tag)
post = @repo.post(id)
raise "Post not found" if post.nil?
current_tags = post.tags.strip.split(/,\s*/)
new_tags = current_tags - [tag]
result = update_post(id, {tags: new_tags})
@repo.generate_post(id) if result
result
end
|
#post_remove_view(id, view) ⇒ Object
303
304
305
306
307
|
# File 'lib/scriptorium/api.rb', line 303
def post_remove_view(id, view)
view_name = view.is_a?(String) ? view : view.name
unlink_post(id, view_name)
end
|
#posts(view = nil) ⇒ Object
220
221
222
223
|
# File 'lib/scriptorium/api.rb', line 220
def posts(view = nil)
view ||= @repo.current_view&.name
@repo.all_posts(view)
end
|
#publish_post(num) ⇒ Object
198
199
200
201
202
203
204
205
206
207
208
|
# File 'lib/scriptorium/api.rb', line 198
def publish_post(num)
check_invariants
assume { num.is_a?(Integer) }
assume { @repo.is_a?(Scriptorium::Repo) }
post = @repo.publish_post(num)
verify { post.is_a?(Scriptorium::Post) }
check_invariants
post
end
|
#repo_exists?(path) ⇒ Boolean
25
26
27
|
# File 'lib/scriptorium/api.rb', line 25
def repo_exists?(path)
Dir.exist?(path)
end
|
#root ⇒ Object
71
72
73
|
# File 'lib/scriptorium/api.rb', line 71
def root
@repo.root
end
|
#search_posts(**criteria) ⇒ Object
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
|
# File 'lib/scriptorium/api.rb', line 456
def search_posts(**criteria)
all_posts = @repo.all_posts
matching_posts = []
all_posts.each do |post|
matches_all_criteria = true
criteria.each do |field, pattern|
field_value = case field
when :title
post.title
when :body
body_file = post.dir/"body.html"
File.exist?(body_file) ? read_file(body_file) : ""
when :tags
post.tags
when :blurb
post.blurb
else
raise "Unknown search field: #{field}"
end
if pattern.is_a?(Regexp)
matches_all_criteria = false unless field_value.match?(pattern)
else
matches_all_criteria = false unless field_value.include?(pattern.to_s)
end
break unless matches_all_criteria
end
matching_posts << post if matches_all_criteria
end
matching_posts
end
|
#select_posts(&block) ⇒ Object
Post selection and search
447
448
449
450
451
452
453
454
|
# File 'lib/scriptorium/api.rb', line 447
def select_posts(&block)
all_posts = @repo.all_posts
all_posts.select(&block)
end
|
#themes_available ⇒ Object
350
351
352
353
354
|
# File 'lib/scriptorium/api.rb', line 350
def themes_available
themes_dir = @repo.root/:themes
return [] unless Dir.exist?(themes_dir)
Dir.children(themes_dir).select { |d| Dir.exist?(themes_dir/d) }
end
|
#undelete_post(id) ⇒ Object
246
247
248
249
250
251
252
253
254
255
|
# File 'lib/scriptorium/api.rb', line 246
def undelete_post(id)
post = @repo.post(id)
old_path = @repo.root/:posts/"_#{post.num}"
new_path = @repo.root/:posts/post.num
FileUtils.mv(old_path, new_path)
post.meta["post.deleted"] = "false"
post.save_metadata
end
|
#unlink_post(id, view = nil) ⇒ Object
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
|
# File 'lib/scriptorium/api.rb', line 257
def unlink_post(id, view = nil)
view ||= @repo.current_view&.name
raise "No view specified and no current view set" if view.nil?
post = @repo.post(id)
raise "Post not found" if post.nil?
current_views = post.views.strip.split(/\s+/)
new_views = current_views - [view]
result = update_post(id, {views: new_views})
@repo.generate_post(id) if result
result
end
|
#update_post(id, fields) ⇒ Object
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
|
# File 'lib/scriptorium/api.rb', line 561
def update_post(id, fields)
post = @repo.post(id)
source_file = post.dir/"source.lt3"
return false unless File.exist?(source_file)
lines = read_file(source_file, lines: true, chomp: false)
updated = false
fields.each do |field, value|
value_array = Array(value)
case field
when :tags
new_value = value_array.join(", ")
else
new_value = value_array.join(' ')
end
lines.map! do |line|
if line.strip.start_with?(".#{field}")
= line.match(/(\s+#.*)$/)
= ? [1] : ""
timestamp = Time.now.strftime("%Y/%m/%d %H:%M:%S")
= " # updated #{field} #{timestamp}"
updated = true
".#{field} #{new_value}#{}#{}\n"
else
line
end
end
end
return false unless updated
write_file(source_file, lines.join)
true
end
|
#view(name = nil) ⇒ Object
84
85
86
87
88
89
90
91
|
# File 'lib/scriptorium/api.rb', line 84
def view(name = nil)
if name.nil?
@repo.current_view
else
result = @repo.view(name)
result
end
end
|
#views ⇒ Object
93
94
95
|
# File 'lib/scriptorium/api.rb', line 93
def views
@repo&.views || []
end
|
#views_for(post_or_id) ⇒ Object
101
102
103
104
|
# File 'lib/scriptorium/api.rb', line 101
def views_for(post_or_id)
post = post_or_id.is_a?(Integer) ? @repo.post(post_or_id) : post_or_id
post.views&.split(/\s+/) || []
end
|
357
358
359
360
361
|
# File 'lib/scriptorium/api.rb', line 357
def widgets_available
widgets_file = @repo.root/:config/"widgets.txt"
return [] unless File.exist?(widgets_file)
read_file(widgets_file, lines: true, chomp: true)
end
|