runeblog 0.2.94 → 0.3.01
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/blog +16 -12
- data/data/features.txt +18 -0
- data/data/global.lt3 +6 -21
- data/data/universal.lt3 +2 -5
- data/{lib → empty_view/config}/exper/2svg.lt3 +0 -0
- data/{lib → empty_view/config}/exper/gen_svg.rb +0 -0
- data/empty_view/config/exper/meta.html +10 -0
- data/{lib → empty_view/config}/exper/s2.html +0 -0
- data/{lib → empty_view/config}/exper/varmint.rb +0 -0
- data/empty_view/config/facebook/credentials.txt +7 -0
- data/empty_view/config/facebook/facebook.rb +42 -0
- data/empty_view/config/facebook/fb.html +10 -0
- data/empty_view/config/facebook/fb.js.lt3 +15 -0
- data/empty_view/config/reddit/credentials.txt +6 -0
- data/empty_view/config/reddit/notes.txt +4 -0
- data/empty_view/config/reddit/reddit_post_url.py +34 -0
- data/empty_view/config/reddit/redpost.rb +43 -0
- data/empty_view/config/reddit/the-graffiti-wall.html +91 -0
- data/empty_view/config/twitter/credentials.txt +3 -0
- data/empty_view/config/twitter/tw.html +12 -0
- data/empty_view/config/twitter/tw.js +5 -0
- data/{lib/exper/fbtw.rb → empty_view/config/twitter/twitter.rb} +4 -26
- data/empty_view/settings/features.txt +18 -0
- data/empty_view/settings/publish.txt +5 -0
- data/empty_view/settings/recent.txt +6 -0
- data/empty_view/settings/view.txt +4 -0
- data/empty_view/themes/standard/banner/top.lt3 +2 -2
- data/empty_view/themes/standard/blog/post_entry.lt3 +1 -1
- data/empty_view/themes/standard/etc/blog.css.lt3 +12 -12
- data/empty_view/themes/standard/post/generate.lt3 +3 -3
- data/empty_view/themes/standard/post/permalink.lt3 +1 -1
- data/lib/helpers-blog.rb +25 -16
- data/lib/liveblog.rb +57 -14
- data/lib/processing.rb +12 -2
- data/lib/publish.rb +11 -10
- data/lib/repl.rb +66 -4
- data/lib/runeblog.rb +106 -51
- data/lib/runeblog_version.rb +1 -1
- data/lib/view.rb +2 -0
- data/test/austin.rb +9 -11
- metadata +25 -10
- data/empty_view/themes/standard/global.lt3 +0 -35
- data/lib/exper/callout.js +0 -10
- data/lib/exper/fbtw-js +0 -48
@@ -1,18 +1,6 @@
|
|
1
|
-
|
2
1
|
class Livetext::Functions
|
3
2
|
|
4
|
-
|
5
|
-
fb_appid = _var("facebook.appid")
|
6
|
-
<<~HTML
|
7
|
-
window.fbAsyncInit = function() {
|
8
|
-
FB.init({
|
9
|
-
appId : '#{fb_appid}',
|
10
|
-
xfbml : true,
|
11
|
-
version : 'v2.4'
|
12
|
-
});
|
13
|
-
};
|
14
|
-
HTML
|
15
|
-
end
|
3
|
+
# Needed for Twitter??
|
16
4
|
|
17
5
|
=begin
|
18
6
|
<!-- Needed: btw what is 'content'?
|
@@ -25,18 +13,8 @@ class Livetext::Functions
|
|
25
13
|
-->
|
26
14
|
=end
|
27
15
|
|
28
|
-
def
|
29
|
-
|
30
|
-
<div class='fb-like'
|
31
|
-
data-share='true'
|
32
|
-
data-width='450'
|
33
|
-
data-show-faces='true'>
|
34
|
-
</div>
|
35
|
-
HTML
|
36
|
-
end
|
37
|
-
|
38
|
-
def twitter_share
|
39
|
-
name, title, url = "", "", "" # FIXME
|
16
|
+
def twitter_share(title, url)
|
17
|
+
name = _var("twitter.user")
|
40
18
|
<<~HTML
|
41
19
|
<a href='https://twitter.com/share'
|
42
20
|
class='twitter-share-button'
|
@@ -48,7 +26,7 @@ class Livetext::Functions
|
|
48
26
|
end
|
49
27
|
|
50
28
|
def twitter_follow
|
51
|
-
name = "
|
29
|
+
name = _var("twitter.user")
|
52
30
|
<<~HTML
|
53
31
|
<a href='https://twitter.com/#{name}' class='twitter-follow-button' data-show-count='false'>Follow @#{name}</a>
|
54
32
|
HTML
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# 0 = disabled (installed but disabled)
|
2
|
+
# 1 = enabled (implies installed)
|
3
|
+
# x = excluded (not installed; does it even exist?)
|
4
|
+
|
5
|
+
reddit 1 # autopost, embed thread after blog post
|
6
|
+
facebook 0 # reader-like, reader post, autopost?
|
7
|
+
twitter 0 # reader-tweet, reader-follow, autotweet?
|
8
|
+
|
9
|
+
links 1 # widget: external links
|
10
|
+
news 1 # widget: news (external)
|
11
|
+
pages 1 # widget: internal pages
|
12
|
+
pinned 1 # widget: pinned posts
|
13
|
+
|
14
|
+
ad x # widget: embed advertising
|
15
|
+
bydates x # widget: browse posts by date
|
16
|
+
search x # widget: search posts
|
17
|
+
sitemap x # widget: site map
|
18
|
+
tag_cloud x # widget: tag cloud (clickable)
|
@@ -15,6 +15,6 @@
|
|
15
15
|
|
16
16
|
<rect x="20" y="20" rx="15" ry="15" width="98%" height="100" fill="url(#grad1)"/>
|
17
17
|
|
18
|
-
<text x="45" y="70" class=heavy>$
|
19
|
-
<text x="45" y="98" class=small>$
|
18
|
+
<text x="45" y="70" class=heavy>$view.title</text>
|
19
|
+
<text x="45" y="98" class=small>$view.subtitle</text>
|
20
20
|
</svg>
|
@@ -10,7 +10,7 @@
|
|
10
10
|
<font size=-1>#{date}</font>
|
11
11
|
</td>
|
12
12
|
<td>
|
13
|
-
<span class="
|
13
|
+
<span class="recent-title-text"><a href="#{url}" style="margin-top: -5px">#{title}</a></span>
|
14
14
|
<b>#{teaser_text}</b>
|
15
15
|
<a style="text-decoration: none" href="#{url}"><small>Keep reading</small></a>
|
16
16
|
</td>
|
@@ -3,40 +3,40 @@
|
|
3
3
|
. Most of the global CSS goes here
|
4
4
|
. --------------------------------------------------
|
5
5
|
|
6
|
-
.seek
|
6
|
+
.seek global.lt3
|
7
7
|
|
8
8
|
body { font-family: $font.family }
|
9
9
|
|
10
|
-
\.
|
11
|
-
color: $
|
10
|
+
\.recent-title a {
|
11
|
+
color: $recent.title.color;
|
12
12
|
font-family: $font.family;
|
13
|
-
font-size: $
|
13
|
+
font-size: $recent.title.size;
|
14
14
|
float: right;
|
15
15
|
display: inline-block;
|
16
16
|
text-align: top;
|
17
17
|
text-decoration: none;
|
18
18
|
}
|
19
19
|
|
20
|
-
\.
|
20
|
+
\.recent-title a:hover {
|
21
21
|
text-decoration: none;
|
22
22
|
}
|
23
23
|
|
24
|
-
\.
|
25
|
-
color: $
|
24
|
+
\.recent-title-text a {
|
25
|
+
color: $recent.text.color;
|
26
26
|
font-family: $font.family;
|
27
|
-
font-size: $
|
27
|
+
font-size: $recent.text.size;
|
28
28
|
display: block;
|
29
29
|
text-decoration: none;
|
30
30
|
}
|
31
31
|
|
32
|
-
\.
|
32
|
+
\.recent-title-text a:hover {
|
33
33
|
text-decoration: none;
|
34
34
|
}
|
35
35
|
|
36
|
-
\.
|
37
|
-
color: $
|
36
|
+
\.recent-date {
|
37
|
+
color: $recent.date.color;
|
38
38
|
font-family: $font.family;
|
39
|
-
font-size: $
|
39
|
+
font-size: $recent.date.size;
|
40
40
|
display: block;
|
41
41
|
float: left;
|
42
42
|
text-align: top;
|
@@ -22,9 +22,9 @@ style blog.css
|
|
22
22
|
<body>
|
23
23
|
|
24
24
|
<section class="post">
|
25
|
-
<div class="
|
25
|
+
<div class="recent-content">
|
26
26
|
<table border=0 width=100%><tr>
|
27
|
-
<td align=left valign=bottom><h2 class="
|
27
|
+
<td align=left valign=bottom><h2 class="recent-title">$title</h2></td>
|
28
28
|
<td align=right valign=top><font size=-5><br></font>$longdate</td>
|
29
29
|
</tr></table><hr>
|
30
30
|
$.copy guts.html
|
@@ -33,6 +33,6 @@ style blog.css
|
|
33
33
|
|
34
34
|
<br>
|
35
35
|
<hr>
|
36
|
-
.post_trailer
|
36
|
+
.post_trailer
|
37
37
|
</body>
|
38
38
|
</html>
|
data/lib/helpers-blog.rb
CHANGED
@@ -14,6 +14,18 @@ module RuneBlog::Helpers
|
|
14
14
|
exit
|
15
15
|
end
|
16
16
|
|
17
|
+
def read_features
|
18
|
+
hash = {}
|
19
|
+
file = @root/self.view/"settings/features.txt"
|
20
|
+
lines = File.readlines(file)
|
21
|
+
lines.each do |line|
|
22
|
+
char, line = line[0], line[1..-1].chomp
|
23
|
+
name = line.strip
|
24
|
+
hash[name] = (char != "-")
|
25
|
+
end
|
26
|
+
@features = hash
|
27
|
+
end
|
28
|
+
|
17
29
|
def get_repo_config
|
18
30
|
log!(enter: __method__, level: 3)
|
19
31
|
@editor = File.read(".blogs/data/EDITOR").chomp
|
@@ -26,11 +38,16 @@ module RuneBlog::Helpers
|
|
26
38
|
end
|
27
39
|
|
28
40
|
def copy_data(tag, dest)
|
29
|
-
data
|
41
|
+
data = RuneBlog::Path + "/../data" # files kept inside gem
|
42
|
+
extra = RuneBlog::Path + "/../config" # files kept inside gem
|
43
|
+
# FIXME names are confusing
|
30
44
|
case tag
|
31
|
-
when :config
|
45
|
+
when :config
|
46
|
+
files = %w[ROOT VIEW EDITOR universal.lt3 global.lt3]
|
47
|
+
files.each {|file| copy(data + "/" + file, dest) }
|
48
|
+
when :extra # FIXME remove later
|
49
|
+
# copy!(extra, dest)
|
32
50
|
end
|
33
|
-
files.each {|file| copy(data + "/" + file, dest) }
|
34
51
|
end
|
35
52
|
|
36
53
|
def read_vars(file)
|
@@ -42,14 +59,15 @@ module RuneBlog::Helpers
|
|
42
59
|
line = line.strip
|
43
60
|
next if skip.include?(line[0])
|
44
61
|
key, val = line.split(" ", 2)
|
45
|
-
|
62
|
+
next if key.nil?
|
63
|
+
hash[key] = hash[key.to_sym] = val
|
46
64
|
end
|
47
65
|
hash
|
48
66
|
rescue => err
|
49
67
|
puts "Can't read vars file '#{file}': #{err}"
|
50
68
|
puts err.backtrace.join("\n")
|
51
69
|
puts "dir = #{Dir.pwd}"
|
52
|
-
stop_RubyText
|
70
|
+
stop_RubyText rescue nil
|
53
71
|
end
|
54
72
|
|
55
73
|
def read_config(file, *syms)
|
@@ -106,20 +124,11 @@ module RuneBlog::Helpers
|
|
106
124
|
File.write(root + "/data/EDITOR", editor + "\n")
|
107
125
|
end
|
108
126
|
|
109
|
-
# def new_dotfile(root: ".blogs", current_view: "test_view", editor: "vi")
|
110
|
-
# log!(enter: __method__, args: [root, current_view, editor], level: 3)
|
111
|
-
# root = Dir.pwd + "/" + root
|
112
|
-
# x = OpenStruct.new
|
113
|
-
# x.root, x.current_view, x.editor = root, current_view, editor
|
114
|
-
# write_config(x, root + "/" + RuneBlog::ConfigFile)
|
115
|
-
# write_repo_config
|
116
|
-
# end
|
117
|
-
|
118
127
|
def new_sequence
|
119
128
|
log!(enter: __method__, level: 3)
|
120
|
-
dump(0, "sequence")
|
129
|
+
dump(0, "data/sequence")
|
121
130
|
version_info = "#{RuneBlog::VERSION}\nBlog created: #{Time.now.to_s}"
|
122
|
-
dump(version_info, "VERSION")
|
131
|
+
dump(version_info, "data/VERSION")
|
123
132
|
end
|
124
133
|
|
125
134
|
def subdirs(dir)
|
data/lib/liveblog.rb
CHANGED
@@ -45,23 +45,59 @@ def post
|
|
45
45
|
_out " <!-- Post number #{@meta.num} -->\n "
|
46
46
|
end
|
47
47
|
|
48
|
+
def _got_python?
|
49
|
+
# Dumb - fix later - check up front as needed
|
50
|
+
# Should also check for praw lib
|
51
|
+
str = `which python3`
|
52
|
+
str.length > 0
|
53
|
+
end
|
54
|
+
|
55
|
+
def _reddit_post_url(vdir, title, url)
|
56
|
+
_got_python?
|
57
|
+
tmpfile = "/tmp/reddit-post-url.txt"
|
58
|
+
File.open(tmpfile, "w") do |tmp|
|
59
|
+
tmp.puts "[Post] " + title
|
60
|
+
tmp.puts url
|
61
|
+
end
|
62
|
+
rid = nil
|
63
|
+
Dir.chdir(vdir/:config) { rid = `python3 reddit/reddit_post_url.py` }
|
64
|
+
system("rm #{tmpfile}")
|
65
|
+
rid # returns reddit id
|
66
|
+
end
|
67
|
+
|
48
68
|
def post_trailer
|
49
69
|
perma = _var("publish.proto") + "://" + _var("publish.server") +
|
50
70
|
"/" + _var("publish.path") + "/" + _var("post.aslug") +
|
51
71
|
".html"
|
52
72
|
tags = _var("post.tags")
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
73
|
+
taglist = tags.empty? ? "" : "Tags: #{tags}"
|
74
|
+
|
75
|
+
reddit_enabled = @blog.features["reddit"] rescue nil
|
76
|
+
reddit_txt = ""
|
77
|
+
if reddit_enabled
|
78
|
+
vdir = @blog.root/:views/@blog.view
|
79
|
+
nslug = "#{_var("post.num")}-#{_var("post.aslug")}"
|
80
|
+
rid_file = vdir/:posts/nslug/"reddit.id"
|
81
|
+
rid = File.exist?(rid_file) ? File.read(rid_file).chomp : nil
|
82
|
+
if rid.nil?
|
83
|
+
title = _var("title")
|
84
|
+
rid = _reddit_post_url(vdir, title, perma)
|
85
|
+
dump(rid, rid_file)
|
86
|
+
end
|
87
|
+
reddit_txt = <<~HTML
|
88
|
+
<hr>
|
89
|
+
<script src='https://redditjs.com/post.js'
|
90
|
+
data-url="#{rid}" data-width=800 ></script>
|
91
|
+
HTML
|
92
|
+
# damned syntax highlighting </>
|
57
93
|
end
|
58
94
|
_out <<~HTML
|
59
95
|
<table width=100%><tr>
|
60
96
|
<td width=10%><a style="text-decoration: none" href="javascript:history.go(-1)">[Back]</a></td>
|
61
97
|
<td width=10%><a style="text-decoration: none" href="#{perma}"> [permalink] </a></td>
|
62
98
|
<td width=80% align=right><font size=-3>#{taglist}</font></td></tr></table>
|
99
|
+
#{reddit_txt}
|
63
100
|
HTML
|
64
|
-
# damned syntax highlighting
|
65
101
|
end
|
66
102
|
|
67
103
|
def faq
|
@@ -205,8 +241,8 @@ def _svg_title(*args)
|
|
205
241
|
.subtitle { font: #{style2} #{size2} #{font2}; fill: #{color2} }
|
206
242
|
</style>
|
207
243
|
<rect x="10" y="10" rx="10" ry="10" width="#{width}" height="#{height}" fill="url(#grad1)"/>
|
208
|
-
<text text-anchor="#{align}" x="#{x}" y="#{y}" class="title">#{Livetext::Vars[
|
209
|
-
<text text-anchor="#{align2}" x="#{x2}" y="#{y2}" class="subtitle">#{Livetext::Vars["
|
244
|
+
<text text-anchor="#{align}" x="#{x}" y="#{y}" class="title">#{Livetext::Vars["view.title"]} </text>
|
245
|
+
<text text-anchor="#{align2}" x="#{x2}" y="#{y2}" class="subtitle">#{Livetext::Vars["view.subtitle"]} </text>
|
210
246
|
</svg>
|
211
247
|
<!-- ^ how does syntax highlighting get messed up? </svg> -->
|
212
248
|
HTML
|
@@ -239,6 +275,13 @@ def h6; _passthru "
#{@_data}"; end |
|
239
275
|
|
240
276
|
def hr; _passthru "<hr>"; end
|
241
277
|
|
278
|
+
def nlist
|
279
|
+
_out "<ol>"
|
280
|
+
_body {|line| _out "<li>#{line}</li>" }
|
281
|
+
_out "</ol>"
|
282
|
+
_optional_blank_line
|
283
|
+
end
|
284
|
+
|
242
285
|
def list
|
243
286
|
_out "<ul>"
|
244
287
|
_body {|line| _out "<li>#{line}</li>" }
|
@@ -403,18 +446,18 @@ def head # Does NOT output tags
|
|
403
446
|
defaults = {}
|
404
447
|
defaults = { "charset" => %[<meta charset="utf-8">],
|
405
448
|
"http-equiv" => %[<meta http-equiv="X-UA-Compatible" content="IE=edge">],
|
406
|
-
"title" => %[<title>\n #{_var(
|
449
|
+
"title" => %[<title>\n #{_var("view.title")} | #{_var("view.subtitle")}\n </title>],
|
407
450
|
"generator" => %[<meta name="generator" content="Runeblog v #@version">],
|
408
|
-
"og:title" => %[<meta property="og:title" content="#{_var(
|
451
|
+
"og:title" => %[<meta property="og:title" content="#{_var("view.title")}">],
|
409
452
|
"og:locale" => %[<meta property="og:locale" content="#{_var(:locale)}">],
|
410
|
-
"description" => %[<meta name="description" content="#{_var("
|
411
|
-
"og:description" => %[<meta property="og:description" content="#{_var("
|
453
|
+
"description" => %[<meta name="description" content="#{_var("view.subtitle")}">],
|
454
|
+
"og:description" => %[<meta property="og:description" content="#{_var("view.subtitle")}">],
|
412
455
|
"linkc" => %[<link rel="canonical" href="#{_var(:host)}">],
|
413
456
|
"og:url" => %[<meta property="og:url" content="#{_var(:host)}">],
|
414
|
-
"og:site_name" => %[<meta property="og:site_name" content="#{_var(
|
457
|
+
"og:site_name" => %[<meta property="og:site_name" content="#{_var("view.title")}">],
|
415
458
|
# "style" => %[<link rel="stylesheet" href="etc/blog.css">],
|
416
459
|
# ^ FIXME
|
417
|
-
"feed" => %[<link type="application/atom+xml" rel="alternate" href="#{_var(:host)}/feed.xml" title="#{_var(
|
460
|
+
"feed" => %[<link type="application/atom+xml" rel="alternate" href="#{_var(:host)}/feed.xml" title="#{_var("view.title")}">],
|
418
461
|
"favicon" => %[<link rel="shortcut icon" type="image/x-icon" href="etc/favicon.ico">\n <link rel="apple-touch-icon" href="etc/favicon.ico">]
|
419
462
|
}
|
420
463
|
result = {}
|
@@ -646,7 +689,7 @@ end
|
|
646
689
|
|
647
690
|
def _make_navbar(orient = :horiz)
|
648
691
|
vdir = @root/:views/@blog.view
|
649
|
-
title = _var(
|
692
|
+
title = _var("view.title")
|
650
693
|
|
651
694
|
if orient == :horiz
|
652
695
|
name = "navbar.html"
|
data/lib/processing.rb
CHANGED
@@ -21,11 +21,15 @@ def stale?(src, dst, deps, force = false)
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def preprocess(cwd: Dir.pwd, src:,
|
24
|
-
dst:
|
24
|
+
dst: nil, strip: false,
|
25
25
|
deps: [], copy: nil, debug: false, force: false,
|
26
26
|
mix: [], call: [], vars: {})
|
27
27
|
src += LEXT unless src.end_with?(LEXT)
|
28
|
-
|
28
|
+
if strip
|
29
|
+
dst = File.basename(src).sub(/.lt3$/,"")
|
30
|
+
else
|
31
|
+
dst += ".html" unless dst.end_with?(".html")
|
32
|
+
end
|
29
33
|
sp = " "*12
|
30
34
|
Dir.chdir(cwd) do
|
31
35
|
if debug
|
@@ -47,4 +51,10 @@ def preprocess(cwd: Dir.pwd, src:,
|
|
47
51
|
end
|
48
52
|
end
|
49
53
|
|
54
|
+
def get_live_vars(src)
|
55
|
+
live = Livetext.customize(call: [".nopara"])
|
56
|
+
live.xform_file(src)
|
57
|
+
live
|
58
|
+
end
|
59
|
+
|
50
60
|
end
|
data/lib/publish.rb
CHANGED
@@ -3,26 +3,27 @@ if ! defined?(Already_publish)
|
|
3
3
|
Already_publish = nil
|
4
4
|
|
5
5
|
require 'pathmagic'
|
6
|
+
require 'processing'
|
6
7
|
|
7
8
|
class RuneBlog::Publishing
|
8
9
|
attr_reader :user, :server, :docroot, :path
|
9
10
|
|
10
|
-
|
11
11
|
BadRemoteLogin = Exception.new("Can't login remotely")
|
12
12
|
BadRemotePerms = Exception.new("Bad remote permissions")
|
13
13
|
|
14
14
|
def initialize(view)
|
15
15
|
log!(enter: __method__, args: [view.to_s])
|
16
16
|
@blog = RuneBlog.blog
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
@
|
23
|
-
@
|
24
|
-
@
|
25
|
-
@
|
17
|
+
dir = @blog.root/:views/view/"themes/standard/"
|
18
|
+
gfile = dir/"global.lt3"
|
19
|
+
return unless File.exist?(gfile) # FIXME Hackish as hell
|
20
|
+
|
21
|
+
live = get_live_vars(gfile)
|
22
|
+
@user = live.vars["publish.user"]
|
23
|
+
@server = live.vars["publish.server"]
|
24
|
+
@docroot = live.vars["publish.docroot"]
|
25
|
+
@path = live.vars["publish.path"]
|
26
|
+
@proto = live.vars["publish.proto"]
|
26
27
|
end
|
27
28
|
|
28
29
|
def to_h
|