runeblog 0.2.94 → 0.3.01

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/bin/blog +16 -12
  3. data/data/features.txt +18 -0
  4. data/data/global.lt3 +6 -21
  5. data/data/universal.lt3 +2 -5
  6. data/{lib → empty_view/config}/exper/2svg.lt3 +0 -0
  7. data/{lib → empty_view/config}/exper/gen_svg.rb +0 -0
  8. data/empty_view/config/exper/meta.html +10 -0
  9. data/{lib → empty_view/config}/exper/s2.html +0 -0
  10. data/{lib → empty_view/config}/exper/varmint.rb +0 -0
  11. data/empty_view/config/facebook/credentials.txt +7 -0
  12. data/empty_view/config/facebook/facebook.rb +42 -0
  13. data/empty_view/config/facebook/fb.html +10 -0
  14. data/empty_view/config/facebook/fb.js.lt3 +15 -0
  15. data/empty_view/config/reddit/credentials.txt +6 -0
  16. data/empty_view/config/reddit/notes.txt +4 -0
  17. data/empty_view/config/reddit/reddit_post_url.py +34 -0
  18. data/empty_view/config/reddit/redpost.rb +43 -0
  19. data/empty_view/config/reddit/the-graffiti-wall.html +91 -0
  20. data/empty_view/config/twitter/credentials.txt +3 -0
  21. data/empty_view/config/twitter/tw.html +12 -0
  22. data/empty_view/config/twitter/tw.js +5 -0
  23. data/{lib/exper/fbtw.rb → empty_view/config/twitter/twitter.rb} +4 -26
  24. data/empty_view/settings/features.txt +18 -0
  25. data/empty_view/settings/publish.txt +5 -0
  26. data/empty_view/settings/recent.txt +6 -0
  27. data/empty_view/settings/view.txt +4 -0
  28. data/empty_view/themes/standard/banner/top.lt3 +2 -2
  29. data/empty_view/themes/standard/blog/post_entry.lt3 +1 -1
  30. data/empty_view/themes/standard/etc/blog.css.lt3 +12 -12
  31. data/empty_view/themes/standard/post/generate.lt3 +3 -3
  32. data/empty_view/themes/standard/post/permalink.lt3 +1 -1
  33. data/lib/helpers-blog.rb +25 -16
  34. data/lib/liveblog.rb +57 -14
  35. data/lib/processing.rb +12 -2
  36. data/lib/publish.rb +11 -10
  37. data/lib/repl.rb +66 -4
  38. data/lib/runeblog.rb +106 -51
  39. data/lib/runeblog_version.rb +1 -1
  40. data/lib/view.rb +2 -0
  41. data/test/austin.rb +9 -11
  42. metadata +25 -10
  43. data/empty_view/themes/standard/global.lt3 +0 -35
  44. data/lib/exper/callout.js +0 -10
  45. data/lib/exper/fbtw-js +0 -48
@@ -1,18 +1,6 @@
1
-
2
1
  class Livetext::Functions
3
2
 
4
- def facebook_init
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 facebook_likes
29
- <<~HTML
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 = "hal_fulton" # FIXME
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)
@@ -0,0 +1,5 @@
1
+ user root
2
+ server SITE
3
+ docroot /var/www/html
4
+ path VIEW_NAME # can be different
5
+ proto https
@@ -0,0 +1,6 @@
1
+ title.color #010101
2
+ title.size 28px
3
+ text.color #0101a1
4
+ text.size 22px
5
+ date.color #9a9a9a
6
+ date.size 15px
@@ -0,0 +1,4 @@
1
+ author VIEW_AUTHOR
2
+ title VIEW_TITLE
3
+ subtitle VIEW_SUBTITLE
4
+ site VIEW_SITE
@@ -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>$blog</text>
19
- <text x="45" y="98" class=small>$blog.desc</text>
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="post-title-text"><a href="#{url}" style="margin-top: -5px">#{title}</a></span>
13
+ <span class="recent-title-text"><a href="#{url}" style="margin-top: -5px">#{title}</a></span>
14
14
  <b>#{teaser_text}</b>&nbsp;&nbsp;
15
15
  <a style="text-decoration: none" href="#{url}"><small>Keep&nbsp;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 themes/standard/global.lt3
6
+ .seek global.lt3
7
7
 
8
8
  body { font-family: $font.family }
9
9
 
10
- \.post-title a {
11
- color: $post.title.color;
10
+ \.recent-title a {
11
+ color: $recent.title.color;
12
12
  font-family: $font.family;
13
- font-size: $post.title.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
- \.post-title a:hover {
20
+ \.recent-title a:hover {
21
21
  text-decoration: none;
22
22
  }
23
23
 
24
- \.post-title-text a {
25
- color: $post.text.color;
24
+ \.recent-title-text a {
25
+ color: $recent.text.color;
26
26
  font-family: $font.family;
27
- font-size: $post.text.size;
27
+ font-size: $recent.text.size;
28
28
  display: block;
29
29
  text-decoration: none;
30
30
  }
31
31
 
32
- \.post-title-text a:hover {
32
+ \.recent-title-text a:hover {
33
33
  text-decoration: none;
34
34
  }
35
35
 
36
- \.post-date {
37
- color: $post.date.color;
36
+ \.recent-date {
37
+ color: $recent.date.color;
38
38
  font-family: $font.family;
39
- font-size: $post.date.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="entry-content">
25
+ <div class="recent-content">
26
26
  <table border=0 width=100%><tr>
27
- <td align=left valign=bottom><h2 class="post-title">$title</h2></td>
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>
@@ -21,7 +21,7 @@ description $teaser
21
21
  .end
22
22
 
23
23
  <section class="post">
24
- <div class="entry-content">
24
+ <div class="recent-content">
25
25
  $.copy guts.html
26
26
  </div>
27
27
  </section>
@@ -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 = RuneBlog::Path + "/../data" # files kept inside gem
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; files = %w[ROOT VIEW EDITOR universal.lt3 global.lt3]
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
- hash[key] = val
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)
@@ -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
- if tags.empty?
54
- taglist = ""
55
- else
56
- taglist = "Tags: #{tags}"
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[:blog]} </text>
209
- <text text-anchor="#{align2}" x="#{x2}" y="#{y2}" class="subtitle">#{Livetext::Vars["blog.desc"]} </text>
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(:blog)} | #{_var("blog.desc")}\n </title>],
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(:blog)}">],
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("blog.desc")}">],
411
- "og:description" => %[<meta property="og:description" content="#{_var("blog.desc")}">],
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(:blog)}">],
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(:blog)}">],
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(:blog)
692
+ title = _var("view.title")
650
693
 
651
694
  if orient == :horiz
652
695
  name = "navbar.html"
@@ -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: (strip = true; File.basename(src).sub(/.lt3$/,"")),
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
- dst += ".html" unless (dst.end_with?(".html") || strip)
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
@@ -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
- gfile = @blog.root/:views/view/"themes/standard/global.lt3"
18
- data = File.readlines(gfile)
19
- # Please refactor the Hal out of this
20
- grab = ->(var) { data.grep(/^#{var} /).first.chomp.split(" ", 2)[1] }
21
- @user = grab.call("publish.user")
22
- @server = grab.call("publish.server")
23
- @docroot = grab.call("publish.docroot")
24
- @path = grab.call("publish.path")
25
- @proto = grab.call("publish.proto")
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