runeblog 0.2.49 → 0.2.54

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 148dacf82516a20ba94f7ddf83e3160d717aacf156a88b23187bc5e891a80542
4
- data.tar.gz: 296c90e497e7efb780fb73c91caff732626bfbeb8f3400c866bdf156688ed059
3
+ metadata.gz: 6fe89e19a4aca1e7fe6d3ae97f9df2099a2b5fa71f859cf857cc7804eaf50ff2
4
+ data.tar.gz: 7a1df9174ea7d4c66c7cab14bdef90f0bcfa25ac942a8cabb7e55626a802cc90
5
5
  SHA512:
6
- metadata.gz: 58fca96171e5fd86d3c6fd207a481c6e957dcd6b777dbec7f7b9f588bed9a6a71c5ceee01ba78bffec3b4acb722df8f597dc397f1153f0517f7d5f9b205e154d
7
- data.tar.gz: 3d46a5f3720342d13e8b9d4665a40f92fb4f70418449dccbd71efdc3e2f96dc64785a6ae1b6d82adbe4022492eb23678c5aea15a4d88de900ef18cce0a9da737
6
+ metadata.gz: ab9912b9aa341458f348265ec533221945d928f4a4dc1528812e56c44eaaefc2387d82010613461b85476c81daca15bd2e12c95f650d2c140f95b8f563cc94fc
7
+ data.tar.gz: 40b9030124447ef0c6a3799bd046590d199b57130ffc8006f648685c8d90d2f986335fec2b81b44f9cb5e4bce760ad50579a8873cbea3d7d80ef6aa88c0e55d3
@@ -10,7 +10,8 @@
10
10
  .sidebar
11
11
  ad
12
12
  links
13
- news
13
+ pinned
14
14
  pages
15
+ news
15
16
  .end
16
17
 
@@ -9,7 +9,6 @@
9
9
  . --------------------------------------------------
10
10
 
11
11
  .navbar
12
- index Home
13
12
  about About
14
13
  contact Contact
15
14
  faq FAQ
@@ -12,22 +12,59 @@ class ::RuneBlog::Widget
12
12
 
13
13
  def build
14
14
  input = "list.data"
15
- lines = File.readlines(input)
16
- data = lines.map! {|x| x.chomp.split(/, */, 3) }
15
+ @lines = File.readlines(input)
16
+ write_main
17
+ write_card
18
+ end
19
+
20
+ def write_main
21
+ @data = @lines.map! {|x| x.chomp.split(/, */, 3) }
17
22
  css = "* { font-family: verdana }"
18
23
  card_title = "External Links" # FIXME
19
24
  File.open("#{Type}-main.html", "w") do |f|
20
25
  _html_body(f, css) do
21
26
  f.puts "<h1>#{card_title}</h1><br><hr>"
22
27
  url_ref = nil
23
- data.each do |url, frameable, title|
28
+ @data.each do |url, frameable, title|
24
29
  url_ref = (frameable == "yes") ? "href = '#{url}'" : _blank(url)
25
30
  css = "color: #8888FF; text-decoration: none; font-size: 21px" # ; font-family: verdana"
26
31
  f.puts %[<a style="#{css}" #{url_ref}>#{title}</a> <br>]
27
32
  end
28
33
  end
29
34
  end
30
- # remember -card also
35
+ end
36
+
37
+ def write_card
38
+ tag = "links"
39
+ url = :widgets/tag/tag+"-main.html"
40
+ card_title = "External links" # FIXME
41
+ cardfile = "#@self-card"
42
+ File.open("#{cardfile}.html", "w") do |f|
43
+ f.puts <<-EOS
44
+ <div class="card mb-3">
45
+ <div class="card-body">
46
+ <h5 class="card-title">
47
+ <button type="button" class="btn btn-primary" data-toggle="collapse" data-target="##{tag}">+</button>
48
+ <a href="javascript: void(0)"
49
+ onclick="javascript:open_main('#{url}')"
50
+ style="text-decoration: none; color: black"> #{card_title}</a>
51
+ </h5>
52
+ <div class="collapse" id="#{tag}">
53
+ EOS
54
+ @data.each do |url2, frameable, title|
55
+ main_ref = %[href="javascript: void(0)" onclick="javascript:open_main('#{url2}')"]
56
+ tab_ref = %[href="#{url2}"]
57
+ url_ref = (frameable == "yes") ? main_ref : tab_ref
58
+ anchor = %[<a #{url_ref}>#{title}</a>]
59
+ wrapper = %[<li class="list-group-item">#{anchor}</li>]
60
+ f.puts wrapper
61
+ end
62
+ f.puts <<-EOS
63
+ </div>
64
+ </div>
65
+ </div>
66
+ EOS
67
+ end
31
68
  end
32
69
 
33
70
  def edit_menu
@@ -1,9 +1,40 @@
1
1
  .mixin liveblog
2
2
 
3
+ <html>
4
+ <head>
5
+
6
+ <style>
7
+ * { font-family: verdana }
8
+ </style>
9
+
10
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
11
+ <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"></link>
12
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap-theme.min.css"></link>
13
+ <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
14
+
15
+ </head>
16
+
17
+ <body>
18
+
3
19
  <h2>Frequently Asked Questions</h2>
4
20
 
5
- This is
6
- just a
7
- FAAAAAQ....
21
+ .faq Are you a rabbit?
22
+ Yes, I am.
23
+ .end
24
+
25
+ .faq Are you a frog?
26
+ Don't be stupid. I just told you I was a rabbit.
27
+ .end
28
+
29
+ .faq Why do you answer a question with a question?
30
+ *Do I in fact answer a question with a question?
31
+ .end
32
+
33
+ .faq Are you serious?
34
+ No, I'm a rabbit.
35
+ .end
8
36
 
9
37
  .backlink
38
+
39
+ </body>
40
+ </html>
@@ -4,9 +4,89 @@ class ::RuneBlog::Widget
4
4
  class Pinned
5
5
  def initialize(repo)
6
6
  @blog = repo
7
+ @self = "pinned"
7
8
  end
8
9
 
10
+ def _html_body(file, css = nil) # FIXME
11
+ file.puts "<html>"
12
+ if css
13
+ file.puts " <head>"
14
+ file.puts " <style>\n#{css}\n </style>"
15
+ file.puts " </head>"
16
+ end
17
+ file.puts " <body>"
18
+ yield
19
+ file.puts " </body>\n</html>"
20
+ end
21
+
9
22
  def build
23
+ @tmp = File.new("/tmp/debug-out", "w")
24
+ posts = nil
25
+ Dir.chdir(@blog.root/:posts) { posts = Dir["*"] }
26
+ lines = File.readlines("list.data")
27
+ hash = {}
28
+ @links = []
29
+ lines.each do |x|
30
+ num, title = x.chomp.split(" ", 2)
31
+ hash[num] = title
32
+ pre = '%04d' % num
33
+ nslug = posts.grep(/#{pre}-/).first
34
+ name = nslug[5..-1]
35
+ link = name+".html"
36
+ @links << [title, link]
37
+ end
38
+ write_main
39
+ write_card
40
+ end
41
+
42
+ def write_main
43
+ tag = "pinned"
44
+ card_title = "Pinned posts" # FIXME
45
+ # setvar "card.title", card_title
46
+ css = "* { font-family: verdana }"
47
+ mainfile = "#@self-main"
48
+ File.open("#{mainfile}.html", "w") do |f|
49
+ _html_body(f, css) do
50
+ f.puts "<h1>#{card_title}</h1><br><hr>"
51
+ @links.each do |title, file|
52
+ title = title.gsub(/\\/, "") # kludge
53
+ css = "color: #8888FF; text-decoration: none; font-size: 21px"
54
+ f.puts %[<a style="#{css}" href="../../#{file}">#{title}</a> <br>]
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ def write_card
61
+ tag = "pinned"
62
+ url = :widgets/tag/tag+"-main.html"
63
+ card_title = "Pinned posts" # FIXME
64
+ cardfile = "#@self-card"
65
+ File.open("#{cardfile}.html", "w") do |f|
66
+ f.puts <<-EOS
67
+ <div class="card mb-3">
68
+ <div class="card-body">
69
+ <h5 class="card-title">
70
+ <button type="button" class="btn btn-primary" data-toggle="collapse" data-target="##{tag}">+</button>
71
+ <a href="javascript: void(0)"
72
+ onclick="javascript:open_main('#{url}')"
73
+ style="text-decoration: none; color: black"> #{card_title}</a>
74
+ </h5>
75
+ <div class="collapse" id="#{tag}">
76
+ EOS
77
+ @links.each do |title, file|
78
+ url2 = file
79
+ url_ref = %[href="javascript: void(0)" onclick="javascript:open_main('#{url2}')"]
80
+ anchor = %[<a #{url_ref}>#{title}</a>]
81
+ wrapper = %[<li class="list-group-item">#{anchor}</li>]
82
+ f.puts wrapper
83
+ end
84
+ f.puts <<-EOS
85
+ </div>
86
+ </div>
87
+ </div>
88
+ EOS
89
+ end
10
90
  end
11
91
 
12
92
  def edit_menu
@@ -15,6 +15,7 @@ module RuneBlog::REPL
15
15
  "v" => :cmd_version,
16
16
  "list views" => :cmd_list_views,
17
17
  "lsv" => :cmd_list_views,
18
+ "clear" => :cmd_clear,
18
19
 
19
20
  "new view $name" => :cmd_new_view,
20
21
 
@@ -30,7 +31,9 @@ module RuneBlog::REPL
30
31
  "cv" => :cmd_change_view, # 0-arity must come second
31
32
 
32
33
  "config" => :cmd_config,
33
- "manage" => :cmd_manage,
34
+ "manage $widget" => :cmd_manage,
35
+
36
+ "legacy" => :cmd_legacy,
34
37
 
35
38
  "list posts" => :cmd_list_posts,
36
39
  "lsp" => :cmd_list_posts,
@@ -187,25 +190,6 @@ module RuneBlog::REPL
187
190
  slug[0..3] + slug[4..-1]
188
191
  end
189
192
 
190
- def import(arg = nil)
191
- raise "Not implemented at present..."
192
- arg = nil if arg == ""
193
- arg ||= ask("Filename: ") # check validity later
194
- name = arg
195
- grep = `grep ^.title #{name}`
196
- @title = grep.sub(/^.title /, "")
197
- @slug = @blog.make_slug(@title) # import (not impl)
198
- @fname = @slug + ".lt3"
199
- result = system!("cp #{name} #@root/drafts/#@fname")
200
- raise CantCopy(name, "#@root/drafts/#@fname") unless result
201
-
202
- edit_initial_post(@fname)
203
- process_post(@fname)
204
- link_post_all_views(@meta)
205
- rescue => err
206
- error(err)
207
- end
208
-
209
193
  def tags_for_view(vname = @blog.view)
210
194
  Dir.chdir(vname) do
211
195
  fname = "tagpool"
@@ -1,6 +1,7 @@
1
1
  require 'ostruct'
2
2
  require 'pp'
3
3
  require 'date'
4
+ require 'find'
4
5
 
5
6
  require 'runeblog'
6
7
  require 'pathmagic'
@@ -18,7 +19,7 @@ def init_liveblog # FIXME - a lot of this logic sucks
18
19
  @root = @blog.root
19
20
  @view = @blog.view
20
21
  @view_name = @blog.view.name unless @view.nil?
21
- @vdir = @blog.view.dir
22
+ @vdir = @blog.view.dir rescue "NONAME"
22
23
  @version = RuneBlog::VERSION
23
24
  @theme = @vdir/:themes/:standard
24
25
  end
@@ -66,13 +67,18 @@ end
66
67
 
67
68
  def faq
68
69
  @faq_count ||= 0
70
+ _out "<br>" if @faq_count == 0
69
71
  @faq_count += 1
70
72
  ques = _data.chomp
71
73
  ans = _body_text
72
74
  id = "faq#@faq_count"
73
- _out %[&nbsp;<a class="btn btn-default btn-xs" data-toggle="collapse" href="##{id}" role="button" aria-expanded="false" aria-controls="collapseExample">+</a>]
75
+ # _out %[&nbsp;<a class="btn btn-default btn-xs" data-toggle="collapse" href="##{id}" role="button" aria-expanded="false" aria-controls="collapseExample">+</a>]
76
+ _out %[&nbsp;<a data-toggle="collapse" href="##{id}" role="button" aria-expanded="false" aria-controls="collapseExample"><font size=+3>&#8964;</font></a>]
74
77
  _out %[&nbsp;<b>#{ques}</b>]
75
- _out %[<div class="collapse" id="#{id}"><br><font size=+1>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#{ans}</font></div><br><br>\n]
78
+ # _out "<font size=-2><br></font>" if @faq_count == 1
79
+ # _out "<br>" unless @faq_count == 1
80
+ _out %[<div class="collapse" id="#{id}"><br><font size=+1>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#{ans}</font></div>\n]
81
+ _out "<br>" unless @faq_count == 1
76
82
  _optional_blank_line
77
83
  end
78
84
 
@@ -90,16 +96,17 @@ def banner # still experimental
90
96
  pieces.each do |piece|
91
97
  _out " <td colspan=#{span}>"
92
98
  case
93
- when piece.start_with?("hnav")
94
- _out "<center>hnav1 hnav2 hnav3 hnav4</center>"
95
- when piece.start_with?("vnav")
96
- _out "vnav1<br>vnav2<br>vnav3<br>vnav4<br>"
99
+ when piece.start_with?("navbar")
100
+ file = "navbar/navbar.html"
101
+ _out File.read(file)
97
102
  when piece.start_with?("text")
98
103
  file = piece.split(":")[1]
104
+ file ||= "banner/text.html"
99
105
  _out File.read(file)
100
106
  when piece.start_with?("image")
101
- file = piece.split(":")[1]
102
- _out " <img src=#{file} height=100></img>"
107
+ image = piece.split(":")[1]
108
+ image ||= "banner/banner.jpg"
109
+ _out " <img src=#{image} height=100></img>"
103
110
  else
104
111
  _out " '#{piece}' isn't known"
105
112
  end
@@ -258,10 +265,30 @@ end
258
265
 
259
266
  def pin
260
267
  raise "'post' was not called" unless @meta
261
- _debug "data = #{_args}"
262
- # verify only already-specified views?
263
- @meta.pinned = _args.dup
268
+ _debug "data = #{_args}" # verify only valid views?
269
+ pinned = @_args
270
+ @meta.pinned = pinned
271
+ pinned.each do |pinview|
272
+ dir = @blog.root/:views/pinview/"themes/standard/widgets/pinned/"
273
+ datafile = dir/"list.data"
274
+ if File.exist?(datafile)
275
+ pins = File.readlines(datafile)
276
+ else
277
+ pins = []
278
+ end
279
+ pins << "#{@meta.num} #{@meta.title}\n"
280
+ pins.uniq!
281
+ outfile = File.new(datafile, "w")
282
+ pins.each do |pin|
283
+ outfile.puts pin
284
+ end
285
+ outfile.close
286
+ end
264
287
  _optional_blank_line
288
+ rescue => err
289
+ puts "err = #{err}"
290
+ puts err.backtrace.join("\n")
291
+ gets
265
292
  end
266
293
 
267
294
  def write_post
@@ -412,12 +439,16 @@ rescue => err
412
439
  end
413
440
 
414
441
  def sidebar
442
+ _debug "--- handling sidebar\r"
415
443
  if _args.include? "off"
416
444
  _body { } # iterate, do nothing
417
445
  return
418
446
  end
419
447
 
420
448
  _out %[<div class="col-lg-3 col-md-3 col-sm-3 col-xs-12">]
449
+
450
+ standard = %w[pinned pages links]
451
+
421
452
  _body do |token|
422
453
  tag = token.chomp.strip.downcase
423
454
  wtag = :widgets/tag
@@ -426,12 +457,14 @@ def sidebar
426
457
 
427
458
  code = _load_local(tag)
428
459
  if code
429
- if ["pages", "links"].include? tag
460
+ if ["pages", "links", "pinned"].include? tag
430
461
  Dir.chdir(wtag) do
431
462
  widget = code.new(@blog)
432
463
  widget.build
433
464
  end
434
465
  end
466
+ _include_file wtag/tcard
467
+ next
435
468
  end
436
469
 
437
470
  if tag == "ad"
@@ -444,7 +477,13 @@ def sidebar
444
477
  end
445
478
  end
446
479
 
447
- xlate cwd: wtag, src: tag, dst: tcard # , debug: (tag == "ad")
480
+ depend = %w[card.css main.css custom.rb local.rb]
481
+ depend += ["#{wtag}.lt3", "#{wtag}.rb"]
482
+ depend += %w[pieces/card-head.lt3 pieces/card-tail.lt3]
483
+ depend += %w[pieces/main-head.lt3 pieces/main-tail.lt3]
484
+ depend.map! {|x| @blog.view.dir/"themes/standard/widgets"/wtag/x }
485
+ _debug "--- call xlate #{tag} src = #{tag} dst = #{tcard}\r"
486
+ xlate cwd: wtag, src: tag, dst: tcard, force: true, deps: depend # , debug: true
448
487
  _include_file wtag/tcard
449
488
  end
450
489
  _out %[</div>]
@@ -599,42 +638,53 @@ def tag_cloud
599
638
  end
600
639
 
601
640
  def vnavbar
641
+ _custom_navbar(:vert)
602
642
  end
603
643
 
604
- def navbar2
644
+ def hnavbar
645
+ _custom_navbar # horiz is default
646
+ end
647
+
648
+ def navbar
649
+ _custom_navbar # horiz is default
650
+ end
651
+
652
+ def _custom_navbar(orient = :horiz)
605
653
  vdir = @blog.view.dir
606
654
  title = _var(:blog)
607
655
 
656
+ extra = ""
657
+ extra = "navbar-expand-lg" if orient == :horiz
658
+
608
659
  open = <<-HTML
609
- <nav class="navbar navbar-light bg-light">
610
- <a class="navbar-brand" href="index.html">#{title}</a>
611
- <ul class="navbar-nav mr-auto">
660
+ <nav class="navbar #{extra} navbar-light bg-light">
661
+ <ul class="navbar-nav mr-auto">
612
662
  HTML
613
663
  close = <<-HTML
614
- </ul>
615
- </div>
664
+ </ul>
616
665
  </nav>
617
666
  HTML
618
667
 
619
- first = true
620
- _out open
668
+ html_file = @blog.root/:views/@blog.view/:themes/:standard/:navbar/"navbar.html"
669
+ output = File.new(@blog.root/:views/@blog.view/:themes/:standard/:navbar/"navbar.html", "w")
670
+ output.puts open
621
671
  lines = _body
672
+ lines = [" index Home"] + lines unless _args.include?("nohome")
622
673
  lines.each do |line|
623
674
  basename, cdata = line.chomp.strip.split(" ", 2)
624
675
  full = :navbar/basename+".html"
625
676
  href_main = _main(full)
626
- if first
627
- first = false # hardcode this part??
628
- _out %[<li class="nav-item active"> <a class="nav-link" href="index.html">#{cdata}<span class="sr-only">(current)</span></a> </li>]
677
+ if basename == "index" # special case
678
+ output.puts %[<li class="nav-item active"> <a class="nav-link" href="index.html">#{cdata}<span class="sr-only">(current)</span></a> </li>]
629
679
  else
630
680
  xlate cwd: "navbar", src: basename, dst: vdir/"remote/navbar"/basename+".html" # , debug: true
631
- _out %[<li class="nav-item"> <a class="nav-link" #{href_main}>#{cdata}</a> </li>]
681
+ output.puts %[<li class="nav-item"> <a class="nav-link" #{href_main}>#{cdata}</a> </li>]
632
682
  end
633
683
  end
634
- _out close
684
+ output.puts close
635
685
  end
636
686
 
637
- def navbar
687
+ def _old_navbar
638
688
  vdir = @blog.view.dir
639
689
  title = _var(:blog)
640
690
 
@@ -671,7 +721,8 @@ def navbar
671
721
  first = false # hardcode this part??
672
722
  _out %[<li class="nav-item active"> <a class="nav-link" href="index.html">#{cdata}<span class="sr-only">(current)</span></a> </li>]
673
723
  else
674
- xlate cwd: "navbar", src: basename, dst: vdir/"remote/navbar"/basename+".html" # , debug: true
724
+ depend = Find.find(@blog.root/:views/@blog.view.to_s/"themes/standard/navbar/").to_a
725
+ xlate cwd: "navbar", src: basename, dst: vdir/"remote/navbar"/basename+".html", deps: depend # , debug: true
675
726
  _out %[<li class="nav-item"> <a class="nav-link" #{href_main}>#{cdata}</a> </li>]
676
727
  end
677
728
  end
@@ -724,7 +775,7 @@ def _write_card(cardfile, mainfile, pairs, card_title, tag)
724
775
  wrapper = %[<li class="list-group-item">#{anchor}</li>]
725
776
  f.puts wrapper
726
777
  end
727
- _include_file cardfile+".html"
778
+ _include_file cardfile+".html"
728
779
  f.puts <<-EOS
729
780
  </div>
730
781
  </div>
@@ -831,7 +882,7 @@ end
831
882
 
832
883
  def _write_metadata
833
884
  File.write("teaser.txt", @meta.teaser)
834
- fields = [:num, :title, :date, :pubdate, :views, :tags]
885
+ fields = [:num, :title, :date, :pubdate, :views, :tags, :pinned]
835
886
  fname2 = "metadata.txt"
836
887
  f2 = File.open(fname2, "w") do |f2|
837
888
  fields.each {|fld| f2.puts "#{fld}: #{@meta.send(fld)}" }
@@ -21,7 +21,8 @@ class RuneBlog::Post
21
21
  raise "Doesn't work right now"
22
22
  raise NoBlogAccessor if RuneBlog.blog.nil?
23
23
  # "post" is a slug
24
- pdir = RuneBlog.blog.view.dir/post
24
+ pdir = RuneBlog.blog.root/:drafts/post
25
+ puts "-- load: opening #{pdir}"
25
26
  meta = nil
26
27
  Dir.chdir(pdir) do
27
28
  meta = read_config("metadata.txt")
@@ -112,9 +113,76 @@ class RuneBlog::Post
112
113
  end
113
114
 
114
115
  class RuneBlog::ViewPost
115
- attr_reader :path, :nslug, :aslug, :title, :date,
116
- :teaser_text
116
+ attr_accessor :nslug, :aslug, :num, :view, :blog
117
+ attr_accessor :path, :title, :date, :teaser_text
118
+
119
+ def self.make(blog:, view:, nslug:)
120
+ raise "No numeric prefix on #{nslug}" unless nslug =~ /^\d{4}-/
121
+ raise "Not expecting an extension" if nslug.end_with?(".lt3") || nslug.end_with?(".html")
122
+ view = view.to_s
123
+ view.define_singleton_method :path do |subdir = ""|
124
+ str = blog.root/:views/view
125
+ str << "/#{subdir}" unless subdir.empty?
126
+ str
127
+ end
128
+ view.define_singleton_method :standard do |subdir = ""|
129
+ str = blog.root/:views/view/:themes/:standard
130
+ str << "/#{subdir}" unless subdir.empty?
131
+ str
132
+ end
133
+ view.define_singleton_method :postdir do |file = ""|
134
+ file = file.to_s
135
+ str = blog.root/:views/view/:posts/nslug
136
+ str = str/file unless file.empty?
137
+ str
138
+ end
139
+ view.define_singleton_method :remote do |dir: "", file: ""|
140
+ subdir = subdir.to_s
141
+ file = file.to_s
142
+ str = blog.root/:views/view/:remote
143
+ str = str/subdir unless subdir.empty?
144
+ str = str/file unless file.empty?
145
+ str
146
+ end
147
+ obj = RuneBlog::ViewPost.new(view, nslug)
148
+ obj.blog = blog
149
+ obj.view = view
150
+ obj.nslug = nslug
151
+ obj.aslug = nslug[5..-1]
152
+ obj.num = nslug[0..3]
153
+ obj
154
+ end
155
+
156
+ def repo(subdir = "")
157
+ subdir = subdir.to_s
158
+ unless subdir.empty?
159
+ raise "Expected 'posts' or 'drafts'" unless %w[posts drafts].include?(subdir)
160
+ end
161
+ str = blog.root
162
+ str = str/subdir unless subdir.empty?
163
+ str
164
+ end
165
+
166
+ alias root repo
167
+
168
+ def slug(num = true, ext = "")
169
+ ext = ext.to_s
170
+ str = ""
171
+ str << @num << "-" if num
172
+ str << @aslug
173
+ str << ext
174
+ str
175
+ end
117
176
 
177
+ =begin
178
+ aslug this-is-a-post
179
+ aslug_live this-is-a-post.lt3
180
+ aslug_html this-is-a-post.lt3
181
+ nslug 0001-this-is-a-post
182
+
183
+ slug(:num, ext = "")
184
+ =end
185
+
118
186
  def initialize(view, postdir)
119
187
  log!(enter: __method__, args: [view, postdir], level: 3)
120
188
  # Assumes already parsed/processed
@@ -122,7 +190,7 @@ class RuneBlog::ViewPost
122
190
  @path = postdir.dup
123
191
  @nslug = @path.split("/").last
124
192
  @aslug = @nslug[5..-1]
125
- fname = "#{postdir}/teaser.txt"
193
+ fname = "#{postdir}/teaser.txt" # ???
126
194
  @teaser_text = File.read(fname).chomp
127
195
  # FIXME dumb hacks...
128
196
  mdfile = postdir/"metadata.txt"
@@ -38,10 +38,10 @@ module RuneBlog::REPL
38
38
  end
39
39
 
40
40
  def cmd_config(arg, testing = false)
41
- list = ["global.lt3", "blog/generate.lt3", " head.lt3", " index.lt3",
42
- " post_entry.lt3", "etc/blog.css.lt3", " externals.lt3",
43
- "post/generate.lt3", " head.lt3", " index.lt3",
44
- " permalink.lt3"]
41
+ list = ["global.lt3", "blog/generate.lt3", ".... head.lt3", ".... index.lt3",
42
+ ".... post_entry.lt3", "etc/blog.css.lt3", "... externals.lt3",
43
+ "post/generate.lt3", ".... head.lt3", ".... index.lt3",
44
+ ".... permalink.lt3"]
45
45
  name = ["global.lt3", "blog/generate.lt3", "blog/head.lt3", "blog/index.lt3",
46
46
  "blog/post_entry.lt3", "etc/blog.css.lt3", "blog/externals.lt3",
47
47
  "post/generate.lt3", "post/head.lt3", "post/index.lt3",
@@ -53,12 +53,11 @@ module RuneBlog::REPL
53
53
  end
54
54
 
55
55
  def cmd_manage(arg, testing = false)
56
- puts "Arg = #{arg.inspect}"
57
56
  case arg
58
- when "pages"; _manage_pages(arg, testing = false)
59
- when "links"; _manage_links(arg, testing = false)
60
- when "navbar"; _manage_navbar(arg, testing = false)
61
- # when "pinned"; _manage_pinned(arg, testing = false) # ditch this??
57
+ when "pages"; _manage_pages(nil, testing = false)
58
+ when "links"; _manage_links(nil, testing = false)
59
+ when "navbar"; _manage_navbar(nil, testing = false)
60
+ # when "pinned"; _manage_pinned(nil, testing = false) # ditch this??
62
61
  else
63
62
  puts "#{arg} is unknown"
64
63
  end
@@ -72,7 +71,6 @@ puts "Arg = #{arg.inspect}"
72
71
  end
73
72
 
74
73
  def _manage_navbar(arg, testing = false) # cloned from manage_pages
75
- puts "Got to #{__method__}"
76
74
  check_empty(arg)
77
75
  dir = @blog.view.dir/"themes/standard/navbar"
78
76
  files = Dir.entries(dir) - %w[. .. navbar.lt3]
@@ -266,6 +264,10 @@ puts "Got to #{__method__}"
266
264
 
267
265
  def cmd_new_view(arg, testing = false)
268
266
  reset_output
267
+ if arg.nil?
268
+ arg = ask("\nFilename: ")
269
+ puts
270
+ end
269
271
  @blog.create_view(arg)
270
272
  edit_file(@blog.view.dir/"themes/standard/global.lt3")
271
273
  @blog.change_view(arg)
@@ -284,6 +286,10 @@ puts "Got to #{__method__}"
284
286
  def cmd_new_post(arg, testing = false)
285
287
  reset_output
286
288
  check_empty(arg)
289
+ if @blog.views.empty?
290
+ puts "\n Create a view before creating the first post!\n "
291
+ return
292
+ end
287
293
  title = ask("\nTitle: ")
288
294
  puts
289
295
  @blog.create_new_post(title)
@@ -321,7 +327,7 @@ puts "Got to #{__method__}"
321
327
  id = get_integer(arg)
322
328
  # Simplify this
323
329
  tag = "#{'%04d' % id}"
324
- files = ::Find.find(@blog.root+"/drafts").to_a
330
+ files = ::Find.find(@blog.root/:drafts).to_a
325
331
  files = files.grep(/#{tag}-.*lt3/)
326
332
  files = files.map {|f| File.basename(f) }
327
333
  if files.size > 1
@@ -338,7 +344,7 @@ puts "Got to #{__method__}"
338
344
  end
339
345
 
340
346
  file = files.first
341
- draft = "#{@blog.root}/drafts/#{file}"
347
+ draft = @blog.root/:drafts/file
342
348
  result = edit_file(draft)
343
349
  @blog.generate_post(draft)
344
350
  rescue => err
@@ -445,54 +451,91 @@ puts "Got to #{__method__}"
445
451
  @out
446
452
  end
447
453
 
454
+ def cmd_legacy(arg = nil)
455
+ # dir = ask("Dir = ")
456
+ dir = "sources/computing"
457
+ puts "Importing from: #{dir}"
458
+ files = Dir[dir/"**"]
459
+ files.each do |fname|
460
+ name = fname
461
+ cmd = "grep ^.title #{name}"
462
+ grep = `#{cmd}` # find .title
463
+ @title = grep.sub(/^.title /, "")
464
+ num = `grep ^.post #{name}`.sub(/^.post /, "").to_i
465
+ seq = @blog.get_sequence
466
+ tnum = File.basename(fname).to_i
467
+
468
+ raise "num != seq + 1" if num != seq + 1
469
+ raise "num != tnum" if num != tnum
470
+ seq = @blog.next_sequence
471
+ raise "num != seq" if num != seq
472
+
473
+ label = '%04d' % num
474
+ slug0 = @title.downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, '')
475
+ @slug = "#{label}-#{slug0}"
476
+ @fname = @slug + ".lt3"
477
+ cmd = "cp #{name} #{@blog.root}/drafts/#@fname"
478
+ result = system!(cmd)
479
+ raise CantCopy(name, "#{@blog.root}/drafts/#@fname") unless result
480
+ # post = Post.load(@slug)
481
+ draft = "#{@blog.root}/drafts/#@fname"
482
+ @meta = @blog.generate_post(draft)
483
+ puts
484
+ sleep 2
485
+ end
486
+ rescue => err
487
+ error(err)
488
+ end
489
+
490
+ Help = <<-EOS
491
+
492
+ {Basics:} {Views:}
493
+ ------------------------------------------- -------------------------------------------
494
+ {h, help} This message {change view VIEW} Change current view
495
+ {q, quit} Exit the program {cv VIEW} Change current view
496
+ {v, version} Print version information {new view} Create a new view
497
+ {clear} Clear screen {list views} List all views available
498
+ {lsv} Same as: list views
499
+
500
+
501
+ {Posts:} {Advanced:}
502
+ ------------------------------------------- -------------------------------------------
503
+ {p, post} Create a new post {config} Edit various system files
504
+ {new post} Same as p, post {customize} (BUGGY) Change set of tags, extra views
505
+ {lsp, list posts} List posts in current view {preview} Look at current (local) view in browser
506
+ {lsd, list drafts} List all drafts (all views) {browse} Look at current (published) view in browser
507
+ {delete ID [ID...]} Remove multiple posts {rebuild} Regenerate all posts and relink
508
+ {undelete ID} Undelete a post {publish} Publish (current view)
509
+ {edit ID} Edit a post {ssh} Login to remote server
510
+ {import ASSETS} Import assets (images, etc.) {manage WIDGET} Manage content/layout of a widget
511
+ EOS
512
+
448
513
  def cmd_help(arg, testing = false)
449
514
  reset_output
450
515
  check_empty(arg)
451
- msg = <<-EOS
452
-
453
- Commands:
454
-
455
- h, help This message
456
- q, quit Exit the program
457
- v, version Print version information
458
-
459
- change view VIEW Change current view
460
- cv VIEW Change current view
461
-
462
- new view Create a new view
463
-
464
- list views List all views available
465
- lsv Same as: list views
466
-
467
- config Edit various system files
468
- * customize (BUGGY) Change set of tags, extra views
469
-
470
- p, post Create a new post
471
- new post Same as post (create a post)
472
-
473
- * import ASSETS Import assets (images, etc.)
474
-
475
- lsp, list posts List posts in current view
476
-
477
- lsd, list drafts List all posts regardless of view
478
-
479
- delete ID [ID...] Remove multiple posts
480
- undelete ID Undelete a post
481
- edit ID Edit a post
482
-
483
- preview Look at current (local) view in browser
484
- browse Look at current (published) view in browser
485
- rebuild Regenerate all posts and relink
486
- publish Publish (current view)
487
- ssh Login to remote server
488
- EOS
516
+ msg = Help
489
517
  output msg
490
518
  msg.each_line do |line|
491
- next if testing
492
- line.chomp!
493
- s1, s2 = line[0..22], line[23..-1]
494
- print fx(s1, :bold)
495
- puts s2
519
+ e = line.each_char
520
+ first = true
521
+ loop do
522
+ s1 = ""
523
+ c = e.next
524
+ if c == "{"
525
+ s2 = first ? "" : " "
526
+ first = false
527
+ loop do
528
+ c = e.next
529
+ break if c == "}"
530
+ s2 << c
531
+ end
532
+ print fx(s2, :bold)
533
+ s2 = ""
534
+ else
535
+ s1 << c
536
+ end
537
+ print s1
538
+ end
496
539
  end
497
540
  puts unless testing
498
541
  @out
@@ -1,5 +1,6 @@
1
1
  require 'date'
2
2
  require 'find'
3
+ require 'ostruct'
3
4
 
4
5
  require 'logging'
5
6
 
@@ -116,7 +117,13 @@ class RuneBlog
116
117
  log!(enter: __method__, args: [dir], level: 1)
117
118
  Dir.chdir(dir) do
118
119
  views = _retrieve_metadata(:views)
119
- views.each {|v| system!("cp *html #@root/views/#{v}/remote") }
120
+ views.each do |v|
121
+ unless self.view?(v)
122
+ puts "#{fx("Warning:", :red)} #{fx(v, :bold)} is not a view"
123
+ next
124
+ end
125
+ system!("cp *html #@root/views/#{v}/remote", show: true)
126
+ end
120
127
  end
121
128
  rescue => err
122
129
  _tmp_error(err)
@@ -148,11 +155,12 @@ class RuneBlog
148
155
  end
149
156
 
150
157
  def process_post(sourcefile)
151
- log!(enter: __method__, args: [dir], level: 2)
158
+ log!(enter: __method__, args: [sourcefile], level: 2)
152
159
  nslug = sourcefile.sub(/.lt3/, "")
153
160
  dir = @root/:posts/nslug
154
- create_dir(dir)
155
- xlate cwd: dir, src: sourcefile # , debug: true
161
+ create_dirs(dir)
162
+ # FIXME dependencies?
163
+ xlate cwd: dir, src: @root/:drafts/sourcefile # , debug: true
156
164
  _deploy_local(dir)
157
165
  rescue => err
158
166
  _tmp_error(err)
@@ -323,14 +331,14 @@ class RuneBlog
323
331
  text = nil
324
332
  @theme = @view.dir/"themes/standard"
325
333
  post_entry_name = @theme/"blog/post_entry.lt3"
326
- xlate src: post_entry_name, dst: "/tmp/post_entry.html" # , debug: true
334
+ depend = [post_entry_name]
335
+ xlate src: post_entry_name, dst: "/tmp/post_entry.html", deps: depend # , debug: true
327
336
  @_post_entry ||= File.read("/tmp/post_entry.html")
328
337
  vp = post_lookup(id)
329
338
  nslug, aslug, title, date, teaser_text =
330
339
  vp.nslug, vp.aslug, vp.title, vp.date, vp.teaser_text
331
340
  path = vp.path
332
341
  url = aslug + ".html"
333
- # puts "--- vp = #{[vp.nslug, vp.aslug, vp.title, vp.date, vp.teaser_text].inspect}"; gets
334
342
  date = ::Date.parse(date)
335
343
  date = date.strftime("%B %e<br><div style='float: right'>%Y</div>")
336
344
  text = interpolate(@_post_entry, binding)
@@ -379,7 +387,7 @@ class RuneBlog
379
387
  meta = nil
380
388
  views = views + [self.view.to_s]
381
389
  views.uniq!
382
- Dir.chdir(@root/:posts) do
390
+ Dir.chdir(@root/"posts") do
383
391
  post = Post.create(title: title, teaser: teaser, body: body, pubdate: pubdate, views: views)
384
392
  post.edit unless testing
385
393
  post.build
@@ -390,15 +398,7 @@ class RuneBlog
390
398
  _tmp_error(err)
391
399
  end
392
400
 
393
- def edit_initial_post(file, testing = false)
394
- log!(enter: __method__, args: [file, testing], level: 3)
395
- debug "=== edit_initial_post #{file.inspect} => #{sourcefile}"
396
- result = system!("#@editor #{sourcefile} +8") unless testing
397
- raise EditorProblem(sourcefile) unless result
398
- process_post(sourcefile)
399
- nil
400
- rescue => err
401
- error(err)
401
+ def import_legacy_post(file, oldfile, testing = false)
402
402
  end
403
403
 
404
404
  def posts
@@ -436,11 +436,15 @@ class RuneBlog
436
436
  log!(enter: __method__, args: [view])
437
437
  vdir = @root/:views/view
438
438
  @theme = @root/:views/view/:themes/:standard
439
- xlate cwd: vdir/"themes/standard/etc",
439
+ depend = [vdir/"remote/etc/blog.css", @theme/"global.lt3",
440
+ @theme/"blog/head.lt3", @theme/"navbar/navbar.lt3",
441
+ @theme/"blog/index.lt3"] # FIXME what about assets?
442
+ xlate cwd: vdir/"themes/standard/etc", deps: depend,
440
443
  src: "blog.css.lt3", copy: vdir/"remote/etc/blog.css" # , debug: true
441
- xlate cwd: vdir/"themes/standard", force: true,
444
+ xlate cwd: vdir/"themes/standard", deps: depend, force: true,
442
445
  src: "blog/generate.lt3", dst: vdir/:remote/"index.html"
443
446
  copy("#{vdir}/assets/*", "#{vdir}/remote/assets/")
447
+ copy_widget_html(view)
444
448
  rescue => err
445
449
  _tmp_error(err)
446
450
  end
@@ -543,7 +547,8 @@ class RuneBlog
543
547
  @theme = @root/:views/view_name/:themes/:standard
544
548
  # Step 1...
545
549
  create_dirs(pdraft)
546
- xlate cwd: pdraft, src: draft, dst: "guts.html", debug: true
550
+ # FIXME dependencies?
551
+ xlate cwd: pdraft, src: draft, dst: "guts.html" # , debug: true
547
552
  _post_metadata(draft, pdraft)
548
553
  # Step 2...
549
554
  vposts = @root/:views/view_name/:posts
@@ -552,8 +557,10 @@ class RuneBlog
552
557
  copy(pdraft/"guts.html", @theme/:post)
553
558
  copy(pdraft/"vars.lt3", @theme/:post)
554
559
  # Step 4...
560
+ # FIXME dependencies?
555
561
  xlate cwd: @theme/:post, src: "generate.lt3", force: true,
556
- dst: remote/ahtml, copy: @theme/:post, debug: true
562
+ dst: remote/ahtml, copy: @theme/:post # , debug: true
563
+ # FIXME dependencies?
557
564
  xlate cwd: @theme/:post, src: "permalink.lt3",
558
565
  dst: remote/:permalink/ahtml # , debug: true
559
566
  copy_widget_html(view_name)
@@ -564,7 +571,13 @@ class RuneBlog
564
571
  def generate_post(draft)
565
572
  log!(enter: __method__, args: [draft], level: 1)
566
573
  views = _get_views(draft)
567
- views.each {|view| _handle_post(draft, view) }
574
+ views.each do |view|
575
+ unless self.view?(view)
576
+ puts "Warning: '#{view}' is not a view"
577
+ next
578
+ end
579
+ _handle_post(draft, view)
580
+ end
568
581
  rescue => err
569
582
  _tmp_error(err)
570
583
  end
@@ -2,7 +2,7 @@
2
2
  if ! (Object.constants.include?(:RuneBlog) && RuneBlog.constants.include?(:Path))
3
3
 
4
4
  class RuneBlog
5
- VERSION = "0.2.49"
5
+ VERSION = "0.2.54"
6
6
 
7
7
  path = Gem.find_files("runeblog").grep(/runeblog-/).first
8
8
  Path = File.dirname(path)
@@ -1,36 +1,41 @@
1
1
 
2
2
  LEXT = ".lt3"
3
3
 
4
- def stale?(src, dst, force = false)
4
+ def newer?(f1, f2)
5
+ File.mtime(f1) > File.mtime(f2)
6
+ end
7
+
8
+ def stale?(src, dst, deps, force = false)
5
9
  meh = File.new("/tmp/dammit-#{src.gsub(/\//, "-")}", "w")
6
10
  log!(enter: __method__, args: [src, dst], level: 3)
7
11
  raise "Source #{src} not found in #{Dir.pwd}" unless File.exist?(src)
8
12
  return true if force
9
13
  return true unless File.exist?(dst)
10
- return true if File.mtime(src) > File.mtime(dst)
14
+ return true if newer?(src, dst)
15
+ deps.each {|dep| return true if newer?(dep, dst) }
11
16
  return false
12
17
  end
13
18
 
14
19
  def xlate(cwd: Dir.pwd, src:,
15
- dst: (strip = true; src.sub(/.lt3$/,"")),
16
- copy: nil, debug: false, force: false)
20
+ dst: (strip = true; File.basename(src).sub(/.lt3$/,"")),
21
+ deps: [], copy: nil, debug: false, force: false)
17
22
  src += LEXT unless src.end_with?(LEXT)
18
- dst += ".html" unless dst.end_with?(".html") || strip
23
+ dst += ".html" unless (dst.end_with?(".html")) # || strip)
19
24
  indent = " "*12
20
25
  Dir.chdir(cwd) do
21
26
  if debug
22
- STDERR.puts "#{indent} -- xlate #{src} >#{dst}"
23
- STDERR.puts "#{indent} in: #{Dir.pwd}"
24
- STDERR.puts "#{indent} from: #{caller[0]}"
25
- STDERR.puts "#{indent} copy: #{copy}" if copy
27
+ puts "#{indent} -- xlate #{src} >#{dst}"
28
+ puts "#{indent} in: #{Dir.pwd}"
29
+ puts "#{indent} from: #{caller[0]}"
30
+ puts "#{indent} copy: #{copy}" if copy
26
31
  end
27
- stale = stale?(src, dst, force)
32
+ stale = stale?(src, dst, deps, force)
28
33
  if stale
29
34
  rc = system("livetext #{src} >#{dst}")
30
- STDERR.puts "...completed (shell returned #{rc})" if debug
35
+ puts "...completed (shell returned #{rc})" if debug
31
36
  system!("cp #{dst} #{copy}") if copy
32
37
  else
33
- STDERR.puts "#{indent} -- ^ Already up to date!" if debug
38
+ puts "#{indent} -- ^ Already up to date!" if debug
34
39
  return
35
40
  end
36
41
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: runeblog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.49
4
+ version: 0.2.54
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hal Fulton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-21 00:00:00.000000000 Z
11
+ date: 2019-10-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: livetext