runeblog 0.2.48 → 0.2.53
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/empty_view/themes/standard/banner/about.lt3 +18 -0
- data/empty_view/themes/standard/banner/blog-banner.jpg +0 -0
- data/empty_view/themes/standard/banner/contact.lt3 +18 -0
- data/empty_view/themes/standard/banner/faq.lt3 +1 -0
- data/empty_view/themes/standard/banner/navbar.lt3 +17 -0
- data/empty_view/themes/standard/navbar/navbar.lt3 +1 -1
- data/empty_view/themes/standard/widgets/pages/faq.lt3 +34 -3
- data/lib/helpers-repl.rb +3 -19
- data/lib/liveblog.rb +129 -3
- data/lib/post.rb +72 -4
- data/lib/repl.rb +163 -45
- data/lib/runeblog.rb +41 -20
- data/lib/runeblog_version.rb +1 -1
- data/lib/xlate.rb +12 -6
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c84711a690b4971d21429ef66c4db28266d341b114bf509d4960567bee4cf8e
|
4
|
+
data.tar.gz: c3b4d53efe40ba4dfe0e662b20d4bba52d965b11c42f9f580c2063ca92f50aa3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c883e358c02c48d38fb8dc647e6d70639d9f9fcc5362da5d672cb991a176c80cb1539bb41c839ce7894a438132e61e2ad50f2025c084dee3251329c6ad218676
|
7
|
+
data.tar.gz: 98e87ccae2538738ea5b43c0d1d8afbbd9069c8dea0502d24687b9a73b59f6da3ebb86878a1b86b07ba40b4fd921e9b816c2627dad2a140877ba0396ee5824f2
|
@@ -0,0 +1,18 @@
|
|
1
|
+
. --------------------------------------------------
|
2
|
+
. This is a sample file typical of page referenced
|
3
|
+
. directly from the navigation bar.
|
4
|
+
. It is like a special case of a page in the "pages"
|
5
|
+
. widget.
|
6
|
+
. --------------------------------------------------
|
7
|
+
|
8
|
+
.set this.title="About me"
|
9
|
+
. make this better later
|
10
|
+
<html><body>
|
11
|
+
<div class="content container-fluid mt-4">
|
12
|
+
<div class="row">
|
13
|
+
<h1>$this.title</h1>
|
14
|
+
. content starts here...
|
15
|
+
Blah blah blah...
|
16
|
+
</div>
|
17
|
+
</div>
|
18
|
+
</body></html>
|
Binary file
|
@@ -0,0 +1,18 @@
|
|
1
|
+
. --------------------------------------------------
|
2
|
+
. This is a sample file typical of page referenced
|
3
|
+
. directly from the navigation bar.
|
4
|
+
. It is like a special case of a page in the "pages"
|
5
|
+
. widget.
|
6
|
+
. --------------------------------------------------
|
7
|
+
|
8
|
+
.set this.title="Contact"
|
9
|
+
. make this better later
|
10
|
+
<html><body>
|
11
|
+
<div class="content container-fluid mt-4">
|
12
|
+
<div class="row">
|
13
|
+
<h1>$this.title</h1>
|
14
|
+
. content starts here...
|
15
|
+
How to contact me by email, smoke signals, ICBM, seance, ...
|
16
|
+
</div>
|
17
|
+
</div>
|
18
|
+
</body></html>
|
@@ -0,0 +1 @@
|
|
1
|
+
.include ../widgets/pages/faq.lt3
|
@@ -0,0 +1,17 @@
|
|
1
|
+
. --------------------------------------------------
|
2
|
+
. This defines the content of the navigation bar.
|
3
|
+
. The first one is a special case.
|
4
|
+
. The others are understood to refer to .lt3 files
|
5
|
+
. such as navbar/about.lt3 (which is processed into
|
6
|
+
. HTML).
|
7
|
+
. The title may be more than one word. Quotes are
|
8
|
+
. not needed.
|
9
|
+
. --------------------------------------------------
|
10
|
+
|
11
|
+
.navbar2
|
12
|
+
index Home
|
13
|
+
about About
|
14
|
+
contact Contact
|
15
|
+
faq FAQ
|
16
|
+
.end
|
17
|
+
|
@@ -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
|
-
|
6
|
-
|
7
|
-
|
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>
|
data/lib/helpers-repl.rb
CHANGED
@@ -30,6 +30,9 @@ module RuneBlog::REPL
|
|
30
30
|
"cv" => :cmd_change_view, # 0-arity must come second
|
31
31
|
|
32
32
|
"config" => :cmd_config,
|
33
|
+
"manage $widget" => :cmd_manage,
|
34
|
+
|
35
|
+
"legacy" => :cmd_legacy,
|
33
36
|
|
34
37
|
"list posts" => :cmd_list_posts,
|
35
38
|
"lsp" => :cmd_list_posts,
|
@@ -186,25 +189,6 @@ module RuneBlog::REPL
|
|
186
189
|
slug[0..3] + slug[4..-1]
|
187
190
|
end
|
188
191
|
|
189
|
-
def import(arg = nil)
|
190
|
-
raise "Not implemented at present..."
|
191
|
-
arg = nil if arg == ""
|
192
|
-
arg ||= ask("Filename: ") # check validity later
|
193
|
-
name = arg
|
194
|
-
grep = `grep ^.title #{name}`
|
195
|
-
@title = grep.sub(/^.title /, "")
|
196
|
-
@slug = @blog.make_slug(@title) # import (not impl)
|
197
|
-
@fname = @slug + ".lt3"
|
198
|
-
result = system!("cp #{name} #@root/drafts/#@fname")
|
199
|
-
raise CantCopy(name, "#@root/drafts/#@fname") unless result
|
200
|
-
|
201
|
-
edit_initial_post(@fname)
|
202
|
-
process_post(@fname)
|
203
|
-
link_post_all_views(@meta)
|
204
|
-
rescue => err
|
205
|
-
error(err)
|
206
|
-
end
|
207
|
-
|
208
192
|
def tags_for_view(vname = @blog.view)
|
209
193
|
Dir.chdir(vname) do
|
210
194
|
fname = "tagpool"
|
data/lib/liveblog.rb
CHANGED
@@ -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'
|
@@ -64,10 +65,61 @@ def post_trailer
|
|
64
65
|
# damned syntax highlighting
|
65
66
|
end
|
66
67
|
|
68
|
+
def faq
|
69
|
+
@faq_count ||= 0
|
70
|
+
_out "<br>" if @faq_count == 0
|
71
|
+
@faq_count += 1
|
72
|
+
ques = _data.chomp
|
73
|
+
ans = _body_text
|
74
|
+
id = "faq#@faq_count"
|
75
|
+
# _out %[ <a class="btn btn-default btn-xs" data-toggle="collapse" href="##{id}" role="button" aria-expanded="false" aria-controls="collapseExample">+</a>]
|
76
|
+
_out %[ <a data-toggle="collapse" href="##{id}" role="button" aria-expanded="false" aria-controls="collapseExample"><font size=+3>⌄</font></a>]
|
77
|
+
_out %[ <b>#{ques}</b>]
|
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> #{ans}</font></div>\n]
|
81
|
+
_out "<br>" unless @faq_count == 1
|
82
|
+
_optional_blank_line
|
83
|
+
end
|
84
|
+
|
67
85
|
def backlink
|
68
86
|
_out %[<br><a href="javascript:history.go(-1)">[Back]</a>]
|
69
87
|
end
|
70
88
|
|
89
|
+
def banner # still experimental
|
90
|
+
_out "<table>"
|
91
|
+
_body do |line|
|
92
|
+
pieces = line.split
|
93
|
+
cols = pieces.size
|
94
|
+
span = cols == 2 ? 1 : 2 # whaaat?
|
95
|
+
_out " <tr>"
|
96
|
+
pieces.each do |piece|
|
97
|
+
_out " <td colspan=#{span}>"
|
98
|
+
case
|
99
|
+
when piece.start_with?("hnav")
|
100
|
+
# horizontal navbar
|
101
|
+
# _out "<center>hnav1 hnav2 hnav3 hnav4</center>"
|
102
|
+
when piece.start_with?("vnav")
|
103
|
+
# vertical navbar
|
104
|
+
# _out "vnav1<br>vnav2<br>vnav3<br>vnav4<br>"
|
105
|
+
when piece.start_with?("text")
|
106
|
+
file = piece.split(":")[1]
|
107
|
+
file ||= "banner/text.html"
|
108
|
+
_out File.read(file)
|
109
|
+
when piece.start_with?("image")
|
110
|
+
image = piece.split(":")[1]
|
111
|
+
image ||= "banner/banner.jpg"
|
112
|
+
_out " <img src=#{image} height=100></img>"
|
113
|
+
else
|
114
|
+
_out " '#{piece}' isn't known"
|
115
|
+
end
|
116
|
+
_out " </td>"
|
117
|
+
end
|
118
|
+
_out " </tr>"
|
119
|
+
end
|
120
|
+
_out "</table>"
|
121
|
+
end
|
122
|
+
|
71
123
|
def quote
|
72
124
|
_passthru "<blockquote>"
|
73
125
|
_passthru _body.join(" ")
|
@@ -219,6 +271,18 @@ def pin
|
|
219
271
|
_debug "data = #{_args}"
|
220
272
|
# verify only already-specified views?
|
221
273
|
@meta.pinned = _args.dup
|
274
|
+
dir = @blog.view.dir/"themes/standard/widgets/pinned/"
|
275
|
+
datafile = dir/"list.data"
|
276
|
+
pins = File.readlines(datafile) rescue []
|
277
|
+
damn = File.new("/tmp/dammit", "w")
|
278
|
+
pins << "#{@meta.num} #{@meta.title}\n"
|
279
|
+
damn.puts pins
|
280
|
+
pins.uniq!
|
281
|
+
damn.puts pins
|
282
|
+
damn.close
|
283
|
+
File.open(datafile, "w") do
|
284
|
+
pins.each {|pin| File.puts pin }
|
285
|
+
end
|
222
286
|
_optional_blank_line
|
223
287
|
end
|
224
288
|
|
@@ -402,7 +466,12 @@ def sidebar
|
|
402
466
|
end
|
403
467
|
end
|
404
468
|
|
405
|
-
|
469
|
+
depend = %w[card.css main.css custom.rb local.rb]
|
470
|
+
depend += ["#{wtag}.lt3", "#{wtag}.rb"]
|
471
|
+
depend += %w[pieces/card-head.lt3 pieces/card-tail.lt3]
|
472
|
+
depend += %w[pieces/main-head.lt3 pieces/main-tail.lt3]
|
473
|
+
depend.map! {|x| @blog.view.dir/"themes/standard/widgets"/wtag/x }
|
474
|
+
xlate cwd: wtag, src: tag, dst: tcard, force: true, deps: depend , debug: (tag == "ad")
|
406
475
|
_include_file wtag/tcard
|
407
476
|
end
|
408
477
|
_out %[</div>]
|
@@ -412,6 +481,26 @@ rescue => err
|
|
412
481
|
exit
|
413
482
|
end
|
414
483
|
|
484
|
+
=begin
|
485
|
+
ets/widgets/pages//card.css
|
486
|
+
ets/widgets/pages//custom.rb
|
487
|
+
ets/widgets/pages//disclaim.lt3
|
488
|
+
ets/widgets/pages//faq.lt3
|
489
|
+
ets/widgets/pages//like-dislike.lt3
|
490
|
+
ets/widgets/pages//list.data
|
491
|
+
ets/widgets/pages//local-vars.lt3
|
492
|
+
ets/widgets/pages//local.rb
|
493
|
+
ets/widgets/pages//main.css
|
494
|
+
ets/widgets/pages//other-stuff.lt3
|
495
|
+
ets/widgets/pages//pages.lt3
|
496
|
+
ets/widgets/pages//pages.rb
|
497
|
+
ets/widgets/pages//pieces
|
498
|
+
ets/widgets/pages//pieces/card-head.lt3
|
499
|
+
ets/widgets/pages//pieces/card-tail.lt3
|
500
|
+
ets/widgets/pages//pieces/main-head.lt3
|
501
|
+
ets/widgets/pages//pieces/main-tail.lt3
|
502
|
+
=end
|
503
|
+
|
415
504
|
def stylesheet
|
416
505
|
lines = _body
|
417
506
|
url = lines[0]
|
@@ -556,6 +645,42 @@ def tag_cloud
|
|
556
645
|
_out close
|
557
646
|
end
|
558
647
|
|
648
|
+
def vnavbar
|
649
|
+
end
|
650
|
+
|
651
|
+
def navbar2
|
652
|
+
vdir = @blog.view.dir
|
653
|
+
title = _var(:blog)
|
654
|
+
|
655
|
+
open = <<-HTML
|
656
|
+
<nav class="navbar navbar-light bg-light">
|
657
|
+
<a class="navbar-brand" href="index.html">#{title}</a>
|
658
|
+
<ul class="navbar-nav mr-auto">
|
659
|
+
HTML
|
660
|
+
close = <<-HTML
|
661
|
+
</ul>
|
662
|
+
</div>
|
663
|
+
</nav>
|
664
|
+
HTML
|
665
|
+
|
666
|
+
first = true
|
667
|
+
_out open
|
668
|
+
lines = _body
|
669
|
+
lines.each do |line|
|
670
|
+
basename, cdata = line.chomp.strip.split(" ", 2)
|
671
|
+
full = :navbar/basename+".html"
|
672
|
+
href_main = _main(full)
|
673
|
+
if first
|
674
|
+
first = false # hardcode this part??
|
675
|
+
_out %[<li class="nav-item active"> <a class="nav-link" href="index.html">#{cdata}<span class="sr-only">(current)</span></a> </li>]
|
676
|
+
else
|
677
|
+
xlate cwd: "navbar", src: basename, dst: vdir/"remote/navbar"/basename+".html" # , debug: true
|
678
|
+
_out %[<li class="nav-item"> <a class="nav-link" #{href_main}>#{cdata}</a> </li>]
|
679
|
+
end
|
680
|
+
end
|
681
|
+
_out close
|
682
|
+
end
|
683
|
+
|
559
684
|
def navbar
|
560
685
|
vdir = @blog.view.dir
|
561
686
|
title = _var(:blog)
|
@@ -593,7 +718,8 @@ def navbar
|
|
593
718
|
first = false # hardcode this part??
|
594
719
|
_out %[<li class="nav-item active"> <a class="nav-link" href="index.html">#{cdata}<span class="sr-only">(current)</span></a> </li>]
|
595
720
|
else
|
596
|
-
|
721
|
+
depend = Find.find(@blog.root/:views/@blog.view.to_s/"themes/standard/navbar/").to_a
|
722
|
+
xlate cwd: "navbar", src: basename, dst: vdir/"remote/navbar"/basename+".html", deps: depend # , debug: true
|
597
723
|
_out %[<li class="nav-item"> <a class="nav-link" #{href_main}>#{cdata}</a> </li>]
|
598
724
|
end
|
599
725
|
end
|
@@ -753,7 +879,7 @@ end
|
|
753
879
|
|
754
880
|
def _write_metadata
|
755
881
|
File.write("teaser.txt", @meta.teaser)
|
756
|
-
fields = [:num, :title, :date, :pubdate, :views, :tags]
|
882
|
+
fields = [:num, :title, :date, :pubdate, :views, :tags, :pinned]
|
757
883
|
fname2 = "metadata.txt"
|
758
884
|
f2 = File.open(fname2, "w") do |f2|
|
759
885
|
fields.each {|fld| f2.puts "#{fld}: #{@meta.send(fld)}" }
|
data/lib/post.rb
CHANGED
@@ -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.
|
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
|
-
|
116
|
-
|
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"
|
data/lib/repl.rb
CHANGED
@@ -37,7 +37,77 @@ module RuneBlog::REPL
|
|
37
37
|
@out
|
38
38
|
end
|
39
39
|
|
40
|
-
def
|
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"]
|
45
|
+
name = ["global.lt3", "blog/generate.lt3", "blog/head.lt3", "blog/index.lt3",
|
46
|
+
"blog/post_entry.lt3", "etc/blog.css.lt3", "blog/externals.lt3",
|
47
|
+
"post/generate.lt3", "post/head.lt3", "post/index.lt3",
|
48
|
+
"post/permalink.lt3"]
|
49
|
+
dir = @blog.view.dir/"themes/standard/"
|
50
|
+
num, str = STDSCR.menu(title: "Edit file:", items: list)
|
51
|
+
target = name[num]
|
52
|
+
edit_file(dir/target)
|
53
|
+
end
|
54
|
+
|
55
|
+
def cmd_manage(arg, testing = false)
|
56
|
+
case arg
|
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??
|
61
|
+
else
|
62
|
+
puts "#{arg} is unknown"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def _manage_pinned(arg, testing = false) # cloned from manage_links
|
67
|
+
check_empty(arg)
|
68
|
+
dir = @blog.view.dir/"themes/standard/widgets/pinned"
|
69
|
+
data = dir/"list.data"
|
70
|
+
edit_file(data)
|
71
|
+
end
|
72
|
+
|
73
|
+
def _manage_navbar(arg, testing = false) # cloned from manage_pages
|
74
|
+
puts "Got to #{__method__}"
|
75
|
+
check_empty(arg)
|
76
|
+
dir = @blog.view.dir/"themes/standard/navbar"
|
77
|
+
files = Dir.entries(dir) - %w[. .. navbar.lt3]
|
78
|
+
new_item = " [New item] "
|
79
|
+
main_file = "[ navbar.lt3 ]"
|
80
|
+
files = [main_file] + files + [new_item]
|
81
|
+
num, fname = STDSCR.menu(title: "Edit navbar:", items: files)
|
82
|
+
return if fname.nil?
|
83
|
+
case fname
|
84
|
+
when new_item
|
85
|
+
print "Page title: "
|
86
|
+
title = RubyText.gets
|
87
|
+
title.chomp!
|
88
|
+
print "File name (.lt3): "
|
89
|
+
fname = RubyText.gets
|
90
|
+
fname << ".lt3" unless fname.end_with?(".lt3")
|
91
|
+
new_file = dir/fname
|
92
|
+
File.open(new_file, "w") do |f|
|
93
|
+
f.puts "<h1>#{title}</h1>\n\n\n "
|
94
|
+
f.puts ".backlink"
|
95
|
+
end
|
96
|
+
edit_file(new_file)
|
97
|
+
when main_file
|
98
|
+
edit_file(main_file[2..-3])
|
99
|
+
else
|
100
|
+
edit_file(dir/fname)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def _manage_links(arg, testing = false)
|
105
|
+
dir = @blog.view.dir/"themes/standard/widgets/links"
|
106
|
+
data = dir/"list.data"
|
107
|
+
edit_file(data)
|
108
|
+
end
|
109
|
+
|
110
|
+
def _manage_pages(arg, testing = false)
|
41
111
|
check_empty(arg)
|
42
112
|
dir = @blog.view.dir/"themes/standard/widgets/pages"
|
43
113
|
# Assume child files already generated (and list.data??)
|
@@ -195,6 +265,10 @@ module RuneBlog::REPL
|
|
195
265
|
|
196
266
|
def cmd_new_view(arg, testing = false)
|
197
267
|
reset_output
|
268
|
+
if arg.nil?
|
269
|
+
arg = ask("\nFilename: ")
|
270
|
+
puts
|
271
|
+
end
|
198
272
|
@blog.create_view(arg)
|
199
273
|
edit_file(@blog.view.dir/"themes/standard/global.lt3")
|
200
274
|
@blog.change_view(arg)
|
@@ -213,6 +287,10 @@ module RuneBlog::REPL
|
|
213
287
|
def cmd_new_post(arg, testing = false)
|
214
288
|
reset_output
|
215
289
|
check_empty(arg)
|
290
|
+
if @blog.views.empty?
|
291
|
+
puts "\n Create a view before creating the first post!\n "
|
292
|
+
return
|
293
|
+
end
|
216
294
|
title = ask("\nTitle: ")
|
217
295
|
puts
|
218
296
|
@blog.create_new_post(title)
|
@@ -267,7 +345,7 @@ module RuneBlog::REPL
|
|
267
345
|
end
|
268
346
|
|
269
347
|
file = files.first
|
270
|
-
draft = "#{
|
348
|
+
draft = "#{file}" # FIXME ?
|
271
349
|
result = edit_file(draft)
|
272
350
|
@blog.generate_post(draft)
|
273
351
|
rescue => err
|
@@ -374,54 +452,94 @@ module RuneBlog::REPL
|
|
374
452
|
@out
|
375
453
|
end
|
376
454
|
|
455
|
+
def cmd_legacy(arg = nil)
|
456
|
+
# dir = ask("Dir = ")
|
457
|
+
dir = "sources/computing"
|
458
|
+
puts "Importing from: #{dir}"
|
459
|
+
files = Dir[dir/"**"]
|
460
|
+
files.each do |fname|
|
461
|
+
name = fname
|
462
|
+
cmd = "grep ^.title #{name}"
|
463
|
+
grep = `#{cmd}` # find .title
|
464
|
+
@title = grep.sub(/^.title /, "")
|
465
|
+
num = `grep ^.post #{name}`.sub(/^.post /, "").to_i
|
466
|
+
seq = @blog.get_sequence
|
467
|
+
tnum = File.basename(fname).to_i
|
468
|
+
|
469
|
+
raise "num != seq + 1" if num != seq + 1
|
470
|
+
raise "num != tnum" if num != tnum
|
471
|
+
seq = @blog.next_sequence
|
472
|
+
raise "num != seq" if num != seq
|
473
|
+
|
474
|
+
label = '%04d' % num
|
475
|
+
slug0 = @title.downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, '')
|
476
|
+
@slug = "#{label}-#{slug0}"
|
477
|
+
@fname = @slug + ".lt3"
|
478
|
+
cmd = "cp #{name} #{@blog.root}/drafts/#@fname"
|
479
|
+
result = system!(cmd)
|
480
|
+
raise CantCopy(name, "#{@blog.root}/drafts/#@fname") unless result
|
481
|
+
puts(`ls -l #{@blog.root}/drafts`)
|
482
|
+
puts "@fname = #@fname"
|
483
|
+
puts "Pause..."
|
484
|
+
gets
|
485
|
+
# post = Post.load(@slug)
|
486
|
+
draft = "#{@blog.root}/drafts/#@fname"
|
487
|
+
@meta = @blog.generate_post(draft)
|
488
|
+
puts
|
489
|
+
sleep 2
|
490
|
+
end
|
491
|
+
rescue => err
|
492
|
+
error(err)
|
493
|
+
end
|
494
|
+
|
495
|
+
Help = <<-EOS
|
496
|
+
|
497
|
+
{Basics:} {Views:}
|
498
|
+
------------------------------------------- -------------------------------------------
|
499
|
+
{h, help} This message {change view VIEW} Change current view
|
500
|
+
{q, quit} Exit the program {cv VIEW} Change current view
|
501
|
+
{v, version} Print version information {new view} Create a new view
|
502
|
+
{list views} List all views available
|
503
|
+
{lsv} Same as: list views
|
504
|
+
|
505
|
+
{Posts:} {Advanced:}
|
506
|
+
------------------------------------------- -------------------------------------------
|
507
|
+
{p, post} Create a new post {config} Edit various system files
|
508
|
+
{new post} Same as p, post {customize} (BUGGY) Change set of tags, extra views
|
509
|
+
{lsp, list posts} List posts in current view {preview} Look at current (local) view in browser
|
510
|
+
{lsd, list drafts} List all drafts (all views) {browse} Look at current (published) view in browser
|
511
|
+
{delete ID [ID...]} Remove multiple posts {rebuild} Regenerate all posts and relink
|
512
|
+
{undelete ID} Undelete a post {publish} Publish (current view)
|
513
|
+
{edit ID} Edit a post {ssh} Login to remote server
|
514
|
+
{import ASSETS} Import assets (images, etc.) {manage WIDGET} Manage content/layout of a widget
|
515
|
+
EOS
|
516
|
+
|
377
517
|
def cmd_help(arg, testing = false)
|
378
518
|
reset_output
|
379
519
|
check_empty(arg)
|
380
|
-
msg =
|
381
|
-
|
382
|
-
Commands:
|
383
|
-
|
384
|
-
h, help This message
|
385
|
-
q, quit Exit the program
|
386
|
-
v, version Print version information
|
387
|
-
|
388
|
-
change view VIEW Change current view
|
389
|
-
cv VIEW Change current view
|
390
|
-
|
391
|
-
new view Create a new view
|
392
|
-
|
393
|
-
list views List all views available
|
394
|
-
lsv Same as: list views
|
395
|
-
|
396
|
-
* config Edit the publish file or the templates
|
397
|
-
* customize (BUGGY) Change set of tags, extra views
|
398
|
-
|
399
|
-
p, post Create a new post
|
400
|
-
new post Same as post (create a post)
|
401
|
-
|
402
|
-
* import ASSETS Import assets (images, etc.)
|
403
|
-
|
404
|
-
lsp, list posts List posts in current view
|
405
|
-
|
406
|
-
lsd, list drafts List all posts regardless of view
|
407
|
-
|
408
|
-
delete ID [ID...] Remove multiple posts
|
409
|
-
undelete ID Undelete a post
|
410
|
-
edit ID Edit a post
|
411
|
-
|
412
|
-
preview Look at current (local) view in browser
|
413
|
-
browse Look at current (published) view in browser
|
414
|
-
rebuild Regenerate all posts and relink
|
415
|
-
publish Publish (current view)
|
416
|
-
ssh Login to remote server
|
417
|
-
EOS
|
520
|
+
msg = Help
|
418
521
|
output msg
|
419
522
|
msg.each_line do |line|
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
523
|
+
e = line.each_char
|
524
|
+
first = true
|
525
|
+
loop do
|
526
|
+
s1 = ""
|
527
|
+
c = e.next
|
528
|
+
if c == "{"
|
529
|
+
s2 = first ? "" : " "
|
530
|
+
first = false
|
531
|
+
loop do
|
532
|
+
c = e.next
|
533
|
+
break if c == "}"
|
534
|
+
s2 << c
|
535
|
+
end
|
536
|
+
print fx(s2, :bold)
|
537
|
+
s2 = ""
|
538
|
+
else
|
539
|
+
s1 << c
|
540
|
+
end
|
541
|
+
print s1
|
542
|
+
end
|
425
543
|
end
|
426
544
|
puts unless testing
|
427
545
|
@out
|
data/lib/runeblog.rb
CHANGED
@@ -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,16 @@ 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
|
120
|
+
views.each do |v|
|
121
|
+
puts "VIEW = #{v} dir = #{dir}"
|
122
|
+
unless self.view?(v)
|
123
|
+
puts "#{fx("Warning:", :red)} #{fx(v, :bold)} is not a view"
|
124
|
+
next
|
125
|
+
end
|
126
|
+
puts "pwd = #{Dir.pwd}"
|
127
|
+
puts "cp *html #@root/views/#{v}/remote"
|
128
|
+
system!("cp *html #@root/views/#{v}/remote", show: true)
|
129
|
+
end
|
120
130
|
end
|
121
131
|
rescue => err
|
122
132
|
_tmp_error(err)
|
@@ -148,11 +158,16 @@ class RuneBlog
|
|
148
158
|
end
|
149
159
|
|
150
160
|
def process_post(sourcefile)
|
151
|
-
log!(enter: __method__, args: [
|
161
|
+
log!(enter: __method__, args: [sourcefile], level: 2)
|
152
162
|
nslug = sourcefile.sub(/.lt3/, "")
|
153
163
|
dir = @root/:posts/nslug
|
154
|
-
|
155
|
-
|
164
|
+
# puts "sourcefile = #{sourcefile}"
|
165
|
+
puts "-- dir = #{dir}\n pwd = #{Dir.pwd}\n @root = #@root"
|
166
|
+
gets
|
167
|
+
create_dirs(dir)
|
168
|
+
# FIXME dependencies?
|
169
|
+
xlate cwd: dir, src: @root/:drafts/sourcefile # , debug: true
|
170
|
+
# puts `ls -l #{dir}`
|
156
171
|
_deploy_local(dir)
|
157
172
|
rescue => err
|
158
173
|
_tmp_error(err)
|
@@ -323,7 +338,8 @@ class RuneBlog
|
|
323
338
|
text = nil
|
324
339
|
@theme = @view.dir/"themes/standard"
|
325
340
|
post_entry_name = @theme/"blog/post_entry.lt3"
|
326
|
-
|
341
|
+
depend = [post_entry_name]
|
342
|
+
xlate src: post_entry_name, dst: "/tmp/post_entry.html", deps: depend # , debug: true
|
327
343
|
@_post_entry ||= File.read("/tmp/post_entry.html")
|
328
344
|
vp = post_lookup(id)
|
329
345
|
nslug, aslug, title, date, teaser_text =
|
@@ -379,7 +395,7 @@ class RuneBlog
|
|
379
395
|
meta = nil
|
380
396
|
views = views + [self.view.to_s]
|
381
397
|
views.uniq!
|
382
|
-
Dir.chdir(@root
|
398
|
+
Dir.chdir(@root/"posts") do
|
383
399
|
post = Post.create(title: title, teaser: teaser, body: body, pubdate: pubdate, views: views)
|
384
400
|
post.edit unless testing
|
385
401
|
post.build
|
@@ -390,15 +406,7 @@ class RuneBlog
|
|
390
406
|
_tmp_error(err)
|
391
407
|
end
|
392
408
|
|
393
|
-
def
|
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)
|
409
|
+
def import_legacy_post(file, oldfile, testing = false)
|
402
410
|
end
|
403
411
|
|
404
412
|
def posts
|
@@ -436,9 +444,12 @@ class RuneBlog
|
|
436
444
|
log!(enter: __method__, args: [view])
|
437
445
|
vdir = @root/:views/view
|
438
446
|
@theme = @root/:views/view/:themes/:standard
|
439
|
-
|
447
|
+
depend = [vdir/"remote/etc/blog.css", @theme/"global.lt3",
|
448
|
+
@theme/"blog/head.lt3", @theme/"navbar/navbar.lt3",
|
449
|
+
@theme/"blog/index.lt3"] # FIXME what about assets?
|
450
|
+
xlate cwd: vdir/"themes/standard/etc", deps: depend,
|
440
451
|
src: "blog.css.lt3", copy: vdir/"remote/etc/blog.css" # , debug: true
|
441
|
-
xlate cwd: vdir/"themes/standard",
|
452
|
+
xlate cwd: vdir/"themes/standard", deps: depend,
|
442
453
|
src: "blog/generate.lt3", dst: vdir/:remote/"index.html"
|
443
454
|
copy("#{vdir}/assets/*", "#{vdir}/remote/assets/")
|
444
455
|
rescue => err
|
@@ -448,6 +459,7 @@ class RuneBlog
|
|
448
459
|
def _get_views(draft)
|
449
460
|
log!(enter: __method__, args: [draft], level: 2)
|
450
461
|
# FIXME dumb code
|
462
|
+
# view_line = File.readlines(self.root/:drafts/draft).grep(/^.views /)
|
451
463
|
view_line = File.readlines(draft).grep(/^.views /)
|
452
464
|
raise "More than one .views call!" if view_line.size > 1
|
453
465
|
raise "No .views call!" if view_line.size < 1
|
@@ -543,7 +555,8 @@ class RuneBlog
|
|
543
555
|
@theme = @root/:views/view_name/:themes/:standard
|
544
556
|
# Step 1...
|
545
557
|
create_dirs(pdraft)
|
546
|
-
|
558
|
+
# FIXME dependencies?
|
559
|
+
xlate cwd: pdraft, src: draft, dst: "guts.html" # , debug: true
|
547
560
|
_post_metadata(draft, pdraft)
|
548
561
|
# Step 2...
|
549
562
|
vposts = @root/:views/view_name/:posts
|
@@ -552,8 +565,10 @@ class RuneBlog
|
|
552
565
|
copy(pdraft/"guts.html", @theme/:post)
|
553
566
|
copy(pdraft/"vars.lt3", @theme/:post)
|
554
567
|
# Step 4...
|
568
|
+
# FIXME dependencies?
|
555
569
|
xlate cwd: @theme/:post, src: "generate.lt3", force: true,
|
556
|
-
dst: remote/ahtml, copy: @theme/:post, debug: true
|
570
|
+
dst: remote/ahtml, copy: @theme/:post # , debug: true
|
571
|
+
# FIXME dependencies?
|
557
572
|
xlate cwd: @theme/:post, src: "permalink.lt3",
|
558
573
|
dst: remote/:permalink/ahtml # , debug: true
|
559
574
|
copy_widget_html(view_name)
|
@@ -564,7 +579,13 @@ class RuneBlog
|
|
564
579
|
def generate_post(draft)
|
565
580
|
log!(enter: __method__, args: [draft], level: 1)
|
566
581
|
views = _get_views(draft)
|
567
|
-
views.each
|
582
|
+
views.each do |view|
|
583
|
+
unless self.view?(view)
|
584
|
+
puts "Warning: '#{view}' is not a view"
|
585
|
+
next
|
586
|
+
end
|
587
|
+
_handle_post(draft, view)
|
588
|
+
end
|
568
589
|
rescue => err
|
569
590
|
_tmp_error(err)
|
570
591
|
end
|
data/lib/runeblog_version.rb
CHANGED
data/lib/xlate.rb
CHANGED
@@ -1,21 +1,26 @@
|
|
1
1
|
|
2
2
|
LEXT = ".lt3"
|
3
3
|
|
4
|
-
def
|
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
|
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
|
@@ -24,7 +29,8 @@ def xlate(cwd: Dir.pwd, src:,
|
|
24
29
|
STDERR.puts "#{indent} from: #{caller[0]}"
|
25
30
|
STDERR.puts "#{indent} copy: #{copy}" if copy
|
26
31
|
end
|
27
|
-
stale = stale?(src, dst, force)
|
32
|
+
stale = stale?(src, dst, deps, force)
|
33
|
+
# puts "stale? src = #{src}\n dst = #{dst}\n #{stale}"
|
28
34
|
if stale
|
29
35
|
rc = system("livetext #{src} >#{dst}")
|
30
36
|
STDERR.puts "...completed (shell returned #{rc})" if debug
|
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.
|
4
|
+
version: 0.2.53
|
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-
|
11
|
+
date: 2019-10-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: livetext
|
@@ -69,6 +69,11 @@ files:
|
|
69
69
|
- empty_view/remote/navbar/GIT_IS_DUMB
|
70
70
|
- empty_view/remote/permalink/GIT_IS_DUMB
|
71
71
|
- empty_view/themes/standard/README
|
72
|
+
- empty_view/themes/standard/banner/about.lt3
|
73
|
+
- empty_view/themes/standard/banner/blog-banner.jpg
|
74
|
+
- empty_view/themes/standard/banner/contact.lt3
|
75
|
+
- empty_view/themes/standard/banner/faq.lt3
|
76
|
+
- empty_view/themes/standard/banner/navbar.lt3
|
72
77
|
- empty_view/themes/standard/blog/generate.lt3
|
73
78
|
- empty_view/themes/standard/blog/head.lt3
|
74
79
|
- empty_view/themes/standard/blog/index.lt3
|