runeblog 0.3.02
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.lt3 +279 -0
- data/README.md +312 -0
- data/bin/blog +200 -0
- data/bin/mkwidget +164 -0
- data/data/EDITOR +1 -0
- data/data/ROOT +1 -0
- data/data/VIEW +1 -0
- data/data/features.txt +18 -0
- data/data/global.lt3 +20 -0
- data/data/universal.lt3 +18 -0
- data/empty_view/assets/austin-pano.jpg +0 -0
- data/empty_view/assets/sky2.jpg +0 -0
- data/empty_view/config/exper/2svg.lt3 +38 -0
- data/empty_view/config/exper/gen_svg.rb +60 -0
- data/empty_view/config/exper/meta.html +10 -0
- data/empty_view/config/exper/s2.html +25 -0
- data/empty_view/config/exper/varmint.rb +50 -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/empty_view/config/twitter/twitter.rb +35 -0
- data/empty_view/posts/GIT_IS_DUMB +1 -0
- data/empty_view/remote/assets/GIT_IS_DUMB +1 -0
- data/empty_view/remote/banner/navbar/GIT_IS_DUMB +0 -0
- data/empty_view/remote/etc/GIT_IS_DUMB +1 -0
- data/empty_view/remote/permalink/GIT_IS_DUMB +1 -0
- data/empty_view/remote/widgets/ad/GIT_IS_DUMB +2 -0
- data/empty_view/remote/widgets/links/GIT_IS_DUMB +2 -0
- data/empty_view/remote/widgets/news/GIT_IS_DUMB +2 -0
- data/empty_view/remote/widgets/pages/GIT_IS_DUMB +2 -0
- data/empty_view/remote/widgets/pinned/GIT_IS_DUMB +2 -0
- 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/README +59 -0
- data/empty_view/themes/standard/banner/banner.lt3 +5 -0
- data/empty_view/themes/standard/banner/navbar/about.lt3 +18 -0
- data/empty_view/themes/standard/banner/navbar/contact.lt3 +18 -0
- data/empty_view/themes/standard/banner/navbar/faq.lt3 +1 -0
- data/empty_view/themes/standard/banner/navbar/list.data +3 -0
- data/empty_view/themes/standard/banner/top.lt3 +20 -0
- data/empty_view/themes/standard/blog/generate.lt3 +21 -0
- data/empty_view/themes/standard/blog/head.lt3 +16 -0
- data/empty_view/themes/standard/blog/index.lt3 +17 -0
- data/empty_view/themes/standard/blog/post_entry.lt3 +21 -0
- data/empty_view/themes/standard/etc/blog.css.lt3 +62 -0
- data/empty_view/themes/standard/etc/externals.lt3 +24 -0
- data/empty_view/themes/standard/etc/favicon.ico +0 -0
- data/empty_view/themes/standard/etc/misc.js +20 -0
- data/empty_view/themes/standard/post/generate.lt3 +38 -0
- data/empty_view/themes/standard/post/head.lt3 +7 -0
- data/empty_view/themes/standard/post/index.lt3 +24 -0
- data/empty_view/themes/standard/post/permalink.lt3 +32 -0
- data/empty_view/themes/standard/widgets/README +4 -0
- data/empty_view/themes/standard/widgets/ad/ad.lt3 +22 -0
- data/empty_view/themes/standard/widgets/ad/ad1.png +0 -0
- data/empty_view/themes/standard/widgets/ad/ad2.png +0 -0
- data/empty_view/themes/standard/widgets/ad/ad3.png +0 -0
- data/empty_view/themes/standard/widgets/ad/ad4.png +0 -0
- data/empty_view/themes/standard/widgets/bydates/README +2 -0
- data/empty_view/themes/standard/widgets/bydates/bydates.rb +18 -0
- data/empty_view/themes/standard/widgets/bydates/card.css +1 -0
- data/empty_view/themes/standard/widgets/bydates/custom.rb +1 -0
- data/empty_view/themes/standard/widgets/bydates/main.css +2 -0
- data/empty_view/themes/standard/widgets/links/README +2 -0
- data/empty_view/themes/standard/widgets/links/card.css +1 -0
- data/empty_view/themes/standard/widgets/links/custom.rb +1 -0
- data/empty_view/themes/standard/widgets/links/links.rb +90 -0
- data/empty_view/themes/standard/widgets/links/list.data +3 -0
- data/empty_view/themes/standard/widgets/links/main.css +2 -0
- data/empty_view/themes/standard/widgets/news/README +2 -0
- data/empty_view/themes/standard/widgets/news/card.css +1 -0
- data/empty_view/themes/standard/widgets/news/custom.rb +1 -0
- data/empty_view/themes/standard/widgets/news/list.data +4 -0
- data/empty_view/themes/standard/widgets/news/main.css +2 -0
- data/empty_view/themes/standard/widgets/news/news.rb +88 -0
- data/empty_view/themes/standard/widgets/pages/README +2 -0
- data/empty_view/themes/standard/widgets/pages/card.css +1 -0
- data/empty_view/themes/standard/widgets/pages/custom.rb +1 -0
- data/empty_view/themes/standard/widgets/pages/disclaim.lt3 +10 -0
- data/empty_view/themes/standard/widgets/pages/faq.lt3 +40 -0
- data/empty_view/themes/standard/widgets/pages/like-dislike.lt3 +11 -0
- data/empty_view/themes/standard/widgets/pages/list.data +4 -0
- data/empty_view/themes/standard/widgets/pages/local.rb +0 -0
- data/empty_view/themes/standard/widgets/pages/main.css +2 -0
- data/empty_view/themes/standard/widgets/pages/other-stuff.lt3 +10 -0
- data/empty_view/themes/standard/widgets/pages/pages.rb +95 -0
- data/empty_view/themes/standard/widgets/pinned/README +2 -0
- data/empty_view/themes/standard/widgets/pinned/card.css +1 -0
- data/empty_view/themes/standard/widgets/pinned/custom.rb +1 -0
- data/empty_view/themes/standard/widgets/pinned/main.css +2 -0
- data/empty_view/themes/standard/widgets/pinned/pinned.rb +99 -0
- data/empty_view/themes/standard/widgets/search/README +2 -0
- data/empty_view/themes/standard/widgets/search/card.css +1 -0
- data/empty_view/themes/standard/widgets/search/custom.rb +1 -0
- data/empty_view/themes/standard/widgets/search/main.css +2 -0
- data/empty_view/themes/standard/widgets/search/search.rb +18 -0
- data/empty_view/themes/standard/widgets/sitemap/README +2 -0
- data/empty_view/themes/standard/widgets/sitemap/card.css +1 -0
- data/empty_view/themes/standard/widgets/sitemap/custom.rb +1 -0
- data/empty_view/themes/standard/widgets/sitemap/main.css +2 -0
- data/empty_view/themes/standard/widgets/sitemap/sitemap.rb +18 -0
- data/empty_view/themes/standard/widgets/tag-cloud/OLD-example.lt3 +12 -0
- data/empty_view/themes/standard/widgets/tag-cloud/README +2 -0
- data/empty_view/themes/standard/widgets/tag-cloud/card.css +1 -0
- data/empty_view/themes/standard/widgets/tag-cloud/custom.rb +1 -0
- data/empty_view/themes/standard/widgets/tag-cloud/main.css +2 -0
- data/empty_view/themes/standard/widgets/tag-cloud/tag-cloud.lt3 +3 -0
- data/empty_view/themes/standard/widgets/tag-cloud/tag-cloud.rb +18 -0
- data/lib/Javascript.stuff +69 -0
- data/lib/helpers-blog.rb +155 -0
- data/lib/helpers-repl.rb +201 -0
- data/lib/liveblog.rb +825 -0
- data/lib/logging.rb +44 -0
- data/lib/lowlevel.rb +73 -0
- data/lib/pathmagic.rb +14 -0
- data/lib/post.rb +211 -0
- data/lib/processing.rb +60 -0
- data/lib/publish.rb +73 -0
- data/lib/repl.rb +597 -0
- data/lib/runeblog.rb +773 -0
- data/lib/runeblog_version.rb +50 -0
- data/lib/view.rb +69 -0
- data/runeblog.gemspec +42 -0
- data/test/austin.rb +158 -0
- data/test/fakeimage.jpg +0 -0
- data/test/general_test.rb +304 -0
- data/test/make_blog.rb +196 -0
- data/test/test +3 -0
- metadata +242 -0
@@ -0,0 +1,50 @@
|
|
1
|
+
if !defined?(RuneBlog::Path)
|
2
|
+
|
3
|
+
# if ! (Object.constants.include?(:RuneBlog) && RuneBlog.constants.include?(:Path))
|
4
|
+
|
5
|
+
class RuneBlog
|
6
|
+
VERSION = "0.3.02"
|
7
|
+
|
8
|
+
path = Gem.find_files("runeblog").grep(/runeblog-/).first
|
9
|
+
Path = File.dirname(path)
|
10
|
+
end
|
11
|
+
|
12
|
+
# skeleton
|
13
|
+
|
14
|
+
class RuneBlog
|
15
|
+
module Helpers
|
16
|
+
end
|
17
|
+
|
18
|
+
class Default
|
19
|
+
end
|
20
|
+
|
21
|
+
class View
|
22
|
+
end
|
23
|
+
|
24
|
+
class Publishing
|
25
|
+
end
|
26
|
+
|
27
|
+
class Post
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Refactor, move stuff elsewhere?
|
32
|
+
|
33
|
+
def make_exception(sym, str)
|
34
|
+
log!(enter: __method__, args: [sym, str], level: 3)
|
35
|
+
return if Object.constants.include?(sym)
|
36
|
+
Object.const_set(sym, StandardError.dup)
|
37
|
+
define_method(sym) do |*args|
|
38
|
+
msg = str
|
39
|
+
args.each.with_index {|arg, i| msg.sub!("$#{i+1}", arg) }
|
40
|
+
Object.class_eval(sym.to_s).new(msg)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def prefix(num)
|
45
|
+
log!(enter: __method__, args: [num], level: 3)
|
46
|
+
"#{'%04d' % num.to_i}"
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
end
|
data/lib/view.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'logging'
|
2
|
+
|
3
|
+
class RuneBlog::View
|
4
|
+
attr_reader :name, :state, :globals
|
5
|
+
attr_accessor :publisher
|
6
|
+
|
7
|
+
include RuneBlog::Helpers
|
8
|
+
|
9
|
+
def initialize(name)
|
10
|
+
log!(enter: __method__, args: [name], level: 3)
|
11
|
+
raise NoBlogAccessor if RuneBlog.blog.nil?
|
12
|
+
@blog = RuneBlog.blog
|
13
|
+
@name = name
|
14
|
+
@publisher = RuneBlog::Publishing.new(name)
|
15
|
+
@can_publish = true # FIXME
|
16
|
+
@blog.view = self
|
17
|
+
gfile = @blog.root/"views/#{name}/themes/standard/global.lt3"
|
18
|
+
return unless File.exist?(gfile) # Hackish!! how is View.new called from create_view??
|
19
|
+
|
20
|
+
live = Livetext.customize(call: ".nopara")
|
21
|
+
live.xform_file(gfile)
|
22
|
+
@globals = live.vars
|
23
|
+
end
|
24
|
+
|
25
|
+
def dir
|
26
|
+
@blog.root + "/views/#@name/"
|
27
|
+
end
|
28
|
+
|
29
|
+
def local_index
|
30
|
+
dir + "/remote/index.html"
|
31
|
+
end
|
32
|
+
|
33
|
+
def index
|
34
|
+
dir + "index.html"
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
@name
|
39
|
+
end
|
40
|
+
|
41
|
+
def publishable_files
|
42
|
+
log!(enter: __method__, level: 2)
|
43
|
+
vdir = dir()
|
44
|
+
remote = local_index()
|
45
|
+
files = [remote]
|
46
|
+
others = Dir.entries(vdir/:remote) - %w[. ..]
|
47
|
+
others.map! {|x| "#{vdir}/remote/#{x}" }
|
48
|
+
|
49
|
+
assets = Dir.entries("#{vdir}/assets") - %w[. ..]
|
50
|
+
assets.map! {|x| "#{vdir}/assets/#{x}" }
|
51
|
+
assets.reject! {|x| File.directory?(x) }
|
52
|
+
# assets.reject! {|x| ! recent?(x) }
|
53
|
+
files = files + others
|
54
|
+
all = files.dup
|
55
|
+
dirty = files.reject {|f| ! recent?(f) }
|
56
|
+
[dirty, all, assets]
|
57
|
+
end
|
58
|
+
|
59
|
+
def can_publish?
|
60
|
+
@can_publish
|
61
|
+
end
|
62
|
+
|
63
|
+
def recent?(file)
|
64
|
+
File.mtime(file) > File.mtime("#{self.dir()}/last_published")
|
65
|
+
rescue
|
66
|
+
true
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
data/runeblog.gemspec
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'find'
|
3
|
+
|
4
|
+
$LOAD_PATH << "lib"
|
5
|
+
|
6
|
+
require "runeblog_version"
|
7
|
+
|
8
|
+
Gem.post_install do |spec|
|
9
|
+
Dir.chdir(RuneBlog::Path)
|
10
|
+
system("livetext -i liveblog.rb")
|
11
|
+
end
|
12
|
+
|
13
|
+
spec = Gem::Specification.new do |s|
|
14
|
+
system("rm -f *.gem")
|
15
|
+
s.name = 'runeblog'
|
16
|
+
s.version = RuneBlog::VERSION
|
17
|
+
s.date = Date.today.strftime("%Y-%m-%d")
|
18
|
+
s.summary = "A command-line blogging system"
|
19
|
+
s.description = "A blog system based on Ruby and Livetext"
|
20
|
+
s.authors = ["Hal Fulton"]
|
21
|
+
s.email = 'rubyhacker@gmail.com'
|
22
|
+
s.executables << "blog"
|
23
|
+
s.add_runtime_dependency 'livetext', '~> 0.9', '>= 0.9.01'
|
24
|
+
s.add_runtime_dependency 'rubytext', '~> 0.1', '>= 0.1.20'
|
25
|
+
|
26
|
+
s.add_development_dependency 'minitest', '~> 5.10', '>= 5.10.0'
|
27
|
+
|
28
|
+
# Files...
|
29
|
+
main = Find.find("bin").to_a +
|
30
|
+
Find.find("lib").to_a
|
31
|
+
data = Find.find("data").to_a
|
32
|
+
test = Find.find("test").to_a
|
33
|
+
misc = %w[./README.lt3 ./README.md ./runeblog.gemspec]
|
34
|
+
empty_view = Find.find("empty_view").to_a
|
35
|
+
|
36
|
+
s.files = main + misc + data + test + empty_view
|
37
|
+
s.homepage = 'https://github.com/Hal9000/runeblog'
|
38
|
+
s.license = "Ruby"
|
39
|
+
s.post_install_message = "\n Success! Run 'blog' command and type h for help.\n "
|
40
|
+
end
|
41
|
+
|
42
|
+
spec
|
data/test/austin.rb
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
$LOAD_PATH << "./lib"
|
2
|
+
|
3
|
+
major, minor = RUBY_VERSION.split(".").values_at(0,1)
|
4
|
+
ver = major.to_i*10 + minor.to_i
|
5
|
+
abort "Need Ruby 2.4 or greater" unless ver >= 24
|
6
|
+
|
7
|
+
# Home = Dir.pwd
|
8
|
+
|
9
|
+
require 'date'
|
10
|
+
|
11
|
+
require 'runeblog'
|
12
|
+
require 'repl'
|
13
|
+
|
14
|
+
def bold(str)
|
15
|
+
"\e[1m#{str}\e[0m"
|
16
|
+
end
|
17
|
+
|
18
|
+
def getch
|
19
|
+
# sleep 5
|
20
|
+
end
|
21
|
+
|
22
|
+
def debug(str = "")
|
23
|
+
t = Time.now
|
24
|
+
time = t.to_f.to_s
|
25
|
+
n = time.index(".")
|
26
|
+
msec = time[n..(n+2)]
|
27
|
+
time = t.strftime("%H:%M:%S") + msec
|
28
|
+
STDERR.puts "#{'%-11s' % time} #{str}"
|
29
|
+
end
|
30
|
+
|
31
|
+
@fake_date = Date.today - 20
|
32
|
+
|
33
|
+
def make_post(x, title, teaser, body, views=[])
|
34
|
+
debug " make_post #{bold(title)}"
|
35
|
+
pubdate = @fake_date.strftime("%Y-%m-%d")
|
36
|
+
@fake_date += (rand(2) + 1)
|
37
|
+
x.create_new_post(title, true, teaser: teaser, body: body, views: views,
|
38
|
+
pubdate: pubdate)
|
39
|
+
end
|
40
|
+
|
41
|
+
def show_lines(text)
|
42
|
+
lines = text.split("\n")
|
43
|
+
str = "#{lines.size} lines\n"
|
44
|
+
lines.each {|line| str << " #{line.inspect}\n" }
|
45
|
+
str
|
46
|
+
end
|
47
|
+
|
48
|
+
# "Main"...
|
49
|
+
|
50
|
+
t0 = Time.now
|
51
|
+
|
52
|
+
puts
|
53
|
+
debug bold("Generating test blog...")
|
54
|
+
|
55
|
+
system("rm -rf .blogs")
|
56
|
+
RuneBlog.create_new_blog_repo(".blogs")
|
57
|
+
x = RuneBlog.new(".blogs")
|
58
|
+
|
59
|
+
debug("create_view: #{bold('around_austin')}")
|
60
|
+
x.create_view("around_austin") # FIXME remember view title!
|
61
|
+
|
62
|
+
#### FIXME
|
63
|
+
|
64
|
+
vars = <<-VARS
|
65
|
+
author Hal Fulton
|
66
|
+
title Around Austin
|
67
|
+
subtitle The view from downtown...
|
68
|
+
domain foo.com
|
69
|
+
VARS
|
70
|
+
vfile = ".blogs/views/around_austin/settings/view.txt"
|
71
|
+
File.open(vfile, "w") {|f| f.puts vars }
|
72
|
+
|
73
|
+
####
|
74
|
+
|
75
|
+
debug("-- change_view: #{bold('around_austin')}")
|
76
|
+
x.change_view("around_austin") # 1 2 7 8 9
|
77
|
+
|
78
|
+
make_post(x, "What's at Stubbs...", <<-EXCERPT, <<-BODY)
|
79
|
+
Stubbs has been around for longer than civilization.
|
80
|
+
EXCERPT
|
81
|
+
That's a good thing. But their music isn't always the greatest.
|
82
|
+
BODY
|
83
|
+
|
84
|
+
make_post(x, "The new amphitheatre is overrated", <<-EXCERPT, <<-BODY)
|
85
|
+
It used to be that all major concerts played the Erwin Center.
|
86
|
+
EXCERPT
|
87
|
+
.pin around_austin
|
88
|
+
Now, depending on what you consider "major," blah blah blah...
|
89
|
+
BODY
|
90
|
+
|
91
|
+
make_post(x, "The graffiti wall", <<-EXCERPT, <<-BODY)
|
92
|
+
RIP, Hope Gallery
|
93
|
+
EXCERPT
|
94
|
+
|
95
|
+
.dropcap It's been a while since I was there. They say it was torn down
|
96
|
+
while I wasn't looking. Never tagged anything there, of course, nor
|
97
|
+
anywhere else. Spraypainting public places isn't my thing, but in this
|
98
|
+
case I condoned it because it was sort of there for that purpose.
|
99
|
+
|
100
|
+
This fake entry is a long one so as to demonstrate both drop-caps
|
101
|
+
(above) and an inset quote. Blah blah blah. Lorem ipsum dolor and
|
102
|
+
a partridge in a pear tree.
|
103
|
+
|
104
|
+
.inset left 20
|
105
|
+
Wherever you go, there you are. Last night I saw upon the stair
|
106
|
+
a little man who was not there. He wasn't there again today; I
|
107
|
+
wish, I wish he'd go away. As far as we know, our computer has
|
108
|
+
never had an undetected error.
|
109
|
+
|On a clean disk, you can seek forever.
|
110
|
+
And never let it be denied that
|
111
|
+
pobbles are happier without their toes. And may your snark never
|
112
|
+
be a boojum. How do you know you aren't dreaming right now? When
|
113
|
+
you see a butterfly, think of Chuang Tzu.
|
114
|
+
.end
|
115
|
+
|
116
|
+
Contact light. Houston, this is Tranquility Base. The Eagle has
|
117
|
+
landed. That's one small step for (a) man, one giant leap for
|
118
|
+
mankind.
|
119
|
+
|
120
|
+
Here's the PDF of $$link["Ruby for the Old-Time C Programmer"|http://rubyhacker.com/blog2/rubydino.pdf]
|
121
|
+
|
122
|
+
Pity this busy monster, manunkind, not. Pity rather... Listen:
|
123
|
+
There's a hell of a universe next door; let's go.
|
124
|
+
BODY
|
125
|
+
|
126
|
+
make_post(x, "The Waller Creek project", <<-EXCERPT, <<-BODY)
|
127
|
+
Will it ever be finished?
|
128
|
+
EXCERPT
|
129
|
+
Blah blah Waller Creek blah blah...
|
130
|
+
BODY
|
131
|
+
|
132
|
+
make_post(x, "Life on Sabine Street", <<-EXCERPT, <<-BODY)
|
133
|
+
It's like Pooh Corner, except not.
|
134
|
+
EXCERPT
|
135
|
+
This is about Sabine St, blah blah lorem ipsum dolor...
|
136
|
+
BODY
|
137
|
+
|
138
|
+
make_post(x, "Remember Modest Mouse?", <<-EXCERPT, <<-BODY)
|
139
|
+
They date to the 90s or before.
|
140
|
+
EXCERPT
|
141
|
+
But I first heard of them
|
142
|
+
in 2005.
|
143
|
+
BODY
|
144
|
+
|
145
|
+
debug
|
146
|
+
debug "** generate_index #{bold("around_austin")}"
|
147
|
+
x.generate_index("around_austin")
|
148
|
+
|
149
|
+
debug("** generate_view: #{bold('around_austin')}")
|
150
|
+
x.generate_view("around_austin")
|
151
|
+
|
152
|
+
debug bold("...finished.\n")
|
153
|
+
|
154
|
+
t1 = Time.now
|
155
|
+
|
156
|
+
elapsed = t1 - t0
|
157
|
+
puts "Elapsed: #{'%3.2f' % elapsed} secs\n "
|
158
|
+
|
data/test/fakeimage.jpg
ADDED
Binary file
|
@@ -0,0 +1,304 @@
|
|
1
|
+
$LOAD_PATH << "."
|
2
|
+
# require "test_helper"
|
3
|
+
|
4
|
+
require "minitest/autorun"
|
5
|
+
# require "minitest/fail_fast"
|
6
|
+
|
7
|
+
require 'runeblog'
|
8
|
+
require 'lib/repl'
|
9
|
+
require 'rubytext'
|
10
|
+
|
11
|
+
major, minor = RUBY_VERSION.split(".").values_at(0,1)
|
12
|
+
ver = major.to_i*10 + minor.to_i
|
13
|
+
abort "Need Ruby 2.4 or greater" unless ver >= 24
|
14
|
+
|
15
|
+
RubyText.start
|
16
|
+
|
17
|
+
class TestREPL < Minitest::Test
|
18
|
+
include RuneBlog::REPL
|
19
|
+
|
20
|
+
def show_lines(text)
|
21
|
+
lines = text.split("\n")
|
22
|
+
str = "#{lines.size} lines\n"
|
23
|
+
lines.each {|line| str << " #{line.inspect}\n" }
|
24
|
+
str
|
25
|
+
end
|
26
|
+
|
27
|
+
def setup
|
28
|
+
# To be strictly correct in testing (though slower),
|
29
|
+
# run make_blog here.
|
30
|
+
system("ruby test/make_blog.rb") if ARGV.first == "new"
|
31
|
+
@blog = RuneBlog.new
|
32
|
+
end
|
33
|
+
|
34
|
+
# Note: "Bang" methods depend on the data subtree
|
35
|
+
|
36
|
+
def test_001_cmd_help
|
37
|
+
# puts __method__
|
38
|
+
out = cmd_help(nil, true)
|
39
|
+
assert out.is_a?(String), "Expected a string returned"
|
40
|
+
lines = out.split("\n").length
|
41
|
+
assert lines > 15, "Expecting lengthy help message"
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_002_cmd_version
|
45
|
+
# puts __method__
|
46
|
+
out = cmd_version(nil, true)
|
47
|
+
assert out.is_a?(String), "Expected a string returned"
|
48
|
+
lines = out
|
49
|
+
assert lines =~ /\d+\.\d+\.\d+/m,
|
50
|
+
"Couldn't find version number; found #{out.inspect}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_003_list_views!
|
54
|
+
# puts __method__
|
55
|
+
out = cmd_list_views(nil, true)
|
56
|
+
assert out.is_a?(String), "Expected a string returned"
|
57
|
+
lines = out.split("\n").length
|
58
|
+
assert lines >= 2, "Expecting at least 2 lines"
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_004_change_view!
|
62
|
+
# puts __method__
|
63
|
+
out = cmd_change_view(nil, true) # no param, but testing
|
64
|
+
assert out.is_a?(String), "Expected a string; got: #{out.inspect}"
|
65
|
+
assert out =~ /alpha_view/m, "Expecting 'alpha_view' as default; got: #{out.inspect}"
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_005_lsd!
|
69
|
+
# puts __method__
|
70
|
+
out = cmd_list_drafts(nil, true)
|
71
|
+
assert out.is_a?(String), "Expected a string returned"
|
72
|
+
nlines = out.split("\n").length
|
73
|
+
exp = 10
|
74
|
+
assert nlines == exp, "Expecting #{exp} lines, got #{nlines}; #{show_lines(out)}"
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_006_lsp!
|
78
|
+
# puts __method__
|
79
|
+
out = cmd_list_posts(nil, true)
|
80
|
+
assert out.is_a?(String), "Expected a string returned; got: #{out.inspect}"
|
81
|
+
lines = out.split("\n").length
|
82
|
+
assert lines == 6, "Expecting 6 lines; got #{lines.size}; #{show_lines(out)}"
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_007_parser
|
86
|
+
# puts __method__
|
87
|
+
parse_tests = {
|
88
|
+
# Loading/trailing blanks as well
|
89
|
+
"kill 81 82 83" => [:cmd_kill, "81 82 83"],
|
90
|
+
" kill 81 82 83" => [:cmd_kill, "81 82 83"],
|
91
|
+
"kill 81 82 83 " => [:cmd_kill, "81 82 83"],
|
92
|
+
" kill 81 82 83 " => [:cmd_kill, "81 82 83"],
|
93
|
+
"help" => [:cmd_help, nil],
|
94
|
+
"h" => [:cmd_help, nil],
|
95
|
+
"version" => [:cmd_version, nil],
|
96
|
+
"v" => [:cmd_version, nil],
|
97
|
+
"list views" => [:cmd_list_views, nil],
|
98
|
+
"lsv" => [:cmd_list_views, nil],
|
99
|
+
"new view foobar" => [:cmd_new_view, "foobar"],
|
100
|
+
"new post" => [:cmd_new_post, nil],
|
101
|
+
"p" => [:cmd_new_post, nil],
|
102
|
+
"post" => [:cmd_new_post, nil],
|
103
|
+
"change view beta_view" => [:cmd_change_view, "beta_view"],
|
104
|
+
"cv" => [:cmd_change_view, nil], # 0-arity
|
105
|
+
"cv myview" => [:cmd_change_view, "myview"],
|
106
|
+
"list posts" => [:cmd_list_posts, nil],
|
107
|
+
"lsp" => [:cmd_list_posts, nil],
|
108
|
+
"list drafts" => [:cmd_list_drafts, nil],
|
109
|
+
"lsd" => [:cmd_list_drafts, nil],
|
110
|
+
"rm 999" => [:cmd_remove_post, "999"],
|
111
|
+
"kill 101 102 103" => [:cmd_kill, "101 102 103"],
|
112
|
+
"edit 104" => [:cmd_edit_post, "104"],
|
113
|
+
"ed 105" => [:cmd_edit_post, "105"],
|
114
|
+
"e 106" => [:cmd_edit_post, "106"],
|
115
|
+
"preview" => [:cmd_preview, nil],
|
116
|
+
"browse" => [:cmd_browse, nil],
|
117
|
+
"relink" => [:cmd_relink, nil],
|
118
|
+
"rebuild" => [:cmd_rebuild, nil],
|
119
|
+
"publish" => [:cmd_publish, nil],
|
120
|
+
"q" => [:cmd_quit, nil],
|
121
|
+
"quit" => [:cmd_quit, nil]
|
122
|
+
# Later: too many/few params
|
123
|
+
}
|
124
|
+
|
125
|
+
parse_tests.each_pair do |cmd, expected|
|
126
|
+
result = RuneBlog::REPL.choose_method(cmd)
|
127
|
+
assert result == expected, "Expected #{expected.inspect} but got #{result.inspect}"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_008_current_view!
|
132
|
+
# puts __method__
|
133
|
+
assert @blog.view.to_s == "alpha_view", "Current view wrong (#{@blog.view}, not alpha_view)"
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_009_change_view!
|
137
|
+
# puts __method__
|
138
|
+
assert @blog.change_view("beta_view")
|
139
|
+
assert @blog.view.to_s == "beta_view", "Current view wrong (#{@blog.view}, not beta_view)"
|
140
|
+
assert @blog.change_view("alpha_view")
|
141
|
+
assert @blog.view.to_s == "alpha_view", "Current view wrong (#{@blog.view}, not alpha_view)"
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_010_accessors!
|
145
|
+
# puts __method__
|
146
|
+
sorted_views = @blog.views.map(&:to_s).sort
|
147
|
+
assert sorted_views == ["alpha_view", "beta_view", "gamma_view", "test_view"],
|
148
|
+
"Got: #{sorted_views.inspect}"
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_011_create_delete_view!
|
152
|
+
# puts __method__
|
153
|
+
@blog.create_view("anotherview")
|
154
|
+
sorted_views = @blog.views.map(&:to_s).sort
|
155
|
+
assert sorted_views == ["alpha_view", "anotherview", "beta_view", "gamma_view", "test_view"],
|
156
|
+
"After create: #{sorted_views.inspect}"
|
157
|
+
@blog.delete_view("anotherview", true)
|
158
|
+
sorted_views = @blog.views.map(&:to_s).sort
|
159
|
+
assert sorted_views == ["alpha_view", "beta_view", "gamma_view", "test_view"],
|
160
|
+
"After delete: #{sorted_views.inspect}"
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_012_create_remove_post!
|
164
|
+
# puts __method__
|
165
|
+
@blog.change_view("beta_view")
|
166
|
+
assert @blog.view.to_s == "beta_view", "Expected beta_view"
|
167
|
+
nposts = @blog.posts.size
|
168
|
+
ndrafts = @blog.drafts.size
|
169
|
+
title = "Uninteresting title"
|
170
|
+
num = @blog.create_new_post(title, true)
|
171
|
+
|
172
|
+
assert @blog.posts.size == nposts + 1, "Don't see new post"
|
173
|
+
@blog.remove_post(num)
|
174
|
+
assert @blog.posts.size == nposts, "Failed to delete post"
|
175
|
+
|
176
|
+
assert @blog.drafts.size == ndrafts + 1, "Don't see new draft"
|
177
|
+
@blog.delete_draft(num)
|
178
|
+
assert @blog.drafts.size == ndrafts, "Failed to delete draft"
|
179
|
+
@blog.change_view("alpha_view")
|
180
|
+
end
|
181
|
+
|
182
|
+
def xtest_013_slug_tests
|
183
|
+
hash = { "abcxyz" => "abcxyz", # 0-based
|
184
|
+
"abc'xyz" => "abcxyz",
|
185
|
+
'abc"xyz' => "abcxyz",
|
186
|
+
'7%sol' => "7sol",
|
187
|
+
"only a test" => "only-a-test",
|
188
|
+
"abc xyz" => "abc--xyz", # change this behavior?
|
189
|
+
"ABCxyZ" => "abcxyz",
|
190
|
+
}
|
191
|
+
hash.each_pair.with_index do |keys, i|
|
192
|
+
real, fixed = *keys
|
193
|
+
meta = OpenStruct.new
|
194
|
+
meta.title = real
|
195
|
+
meta.num = 99
|
196
|
+
result = @blog.make_slug(meta)[5..-1] # Skip num (test_013...)
|
197
|
+
assert result == fixed, "Case #{i}: expected: #{fixed.inspect}, got #{result.inspect}"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def xtest_014_remove_nonexistent_post!
|
202
|
+
@blog.change_view("alpha_view")
|
203
|
+
out = cmd_remove_post(99, true)
|
204
|
+
assert out =~ /Post 99 not found/, "Expected error about nonexistent post, got: #{out}"
|
205
|
+
end
|
206
|
+
|
207
|
+
def xtest_015_kill_multiple_posts!
|
208
|
+
@blog.change_view("alpha_view")
|
209
|
+
out = cmd_list_posts(nil, true)
|
210
|
+
before = out.split("\n").length
|
211
|
+
cmd_kill("1 2 7", true)
|
212
|
+
out = cmd_list_posts(nil, true)
|
213
|
+
after = out.split("\n").length
|
214
|
+
expecting = before - 3
|
215
|
+
assert after == expecting, "list_posts saw #{before} posts, now #{after} (not #{expecting})"
|
216
|
+
@blog.undelete_post(1)
|
217
|
+
@blog.undelete_post(2)
|
218
|
+
@blog.undelete_post(7)
|
219
|
+
end
|
220
|
+
|
221
|
+
if File.exist?("testing.publish") # FIXME!!!
|
222
|
+
|
223
|
+
def xtest_016_can_publish
|
224
|
+
# puts __method__
|
225
|
+
x = OpenStruct.new
|
226
|
+
x.user, x.server, x.docroot, x.docroot, x.path, x.proto =
|
227
|
+
"root", "rubyhacker.com", "/var/www", "whatever", "http"
|
228
|
+
dep = RuneBlog::Publishing.new(x)
|
229
|
+
result = dep.remote_login?
|
230
|
+
assert result == true, "Valid login doesn't work"
|
231
|
+
result = dep.remote_permissions?
|
232
|
+
assert result == true, "Valid mkdir doesn't work"
|
233
|
+
end
|
234
|
+
|
235
|
+
def xtest_017_cannot_publish_wrong_user
|
236
|
+
# puts __method__
|
237
|
+
x = OpenStruct.new
|
238
|
+
x.user, x.server, x.docroot, x.docroot, x.path, x.proto =
|
239
|
+
"bad_user", "rubyhacker.com", "/var/www", "whatever", "http"
|
240
|
+
dep = RuneBlog::Publishing.new(x)
|
241
|
+
result = dep.remote_login?
|
242
|
+
assert result.nil?, "Expected to detect login error (bad user)"
|
243
|
+
end
|
244
|
+
|
245
|
+
def xtest_018_cannot_publish_bad_server
|
246
|
+
# puts __method__
|
247
|
+
x = OpenStruct.new
|
248
|
+
x.user, x.server, x.docroot, x.docroot, x.path, x.proto =
|
249
|
+
"root", "nonexistent123.com", "/var/www", "whatever", "http"
|
250
|
+
dep = RuneBlog::Publishing.new(x)
|
251
|
+
result = dep.remote_login?
|
252
|
+
assert result.nil?, "Expected to detect login error (bad server)"
|
253
|
+
end
|
254
|
+
|
255
|
+
end # conditional tests
|
256
|
+
|
257
|
+
def xtest_019_exception_existing_blog
|
258
|
+
# puts __method__
|
259
|
+
assert_raises(BlogAlreadyExists) { RuneBlog.create_new_blog_repo }
|
260
|
+
end
|
261
|
+
|
262
|
+
def xtest_020_exception_missing_blog_accessor
|
263
|
+
# puts __method__
|
264
|
+
save = RuneBlog.blog
|
265
|
+
RuneBlog.blog = nil
|
266
|
+
assert_raises(NoBlogAccessor) { RuneBlog::Post.load(1) }
|
267
|
+
RuneBlog.blog = save
|
268
|
+
end
|
269
|
+
|
270
|
+
def xtest_021_exception_cant_assign_view
|
271
|
+
# puts __method__
|
272
|
+
assert_raises(CantAssignView) { @blog.view = 99 }
|
273
|
+
end
|
274
|
+
|
275
|
+
def xtest_022_exception_no_such_view
|
276
|
+
# puts __method__
|
277
|
+
assert_raises(NoSuchView) { @blog.view = 'not_a_view_name' }
|
278
|
+
end
|
279
|
+
|
280
|
+
def xtest_023_exception_view_already_exists
|
281
|
+
# puts __method__
|
282
|
+
assert_raises(ViewAlreadyExists) { @blog.create_view('alpha_view') }
|
283
|
+
end
|
284
|
+
|
285
|
+
def xtest_024_exception_livetext_error # FIXME Doesn't work! Change Livetext
|
286
|
+
# puts __method__
|
287
|
+
testfile = "testfile.lt3"
|
288
|
+
path = @blog.root + "/drafts/" + testfile
|
289
|
+
cmd = "echo .no_such_command > #{path}"
|
290
|
+
system(cmd)
|
291
|
+
# system("ls -l #{path}")
|
292
|
+
save = STDERR
|
293
|
+
STDERR.reopen("/dev/null")
|
294
|
+
assert_raises(LivetextError) { @blog.process_post(testfile) }
|
295
|
+
STDERR.reopen(save)
|
296
|
+
File.rm(path)
|
297
|
+
end
|
298
|
+
|
299
|
+
# later tests...
|
300
|
+
# new view asks for publishing info and writes it
|
301
|
+
# (how to mimic user input? test some other way?)
|
302
|
+
|
303
|
+
end
|
304
|
+
|