runeblog 0.3.02

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. checksums.yaml +7 -0
  2. data/README.lt3 +279 -0
  3. data/README.md +312 -0
  4. data/bin/blog +200 -0
  5. data/bin/mkwidget +164 -0
  6. data/data/EDITOR +1 -0
  7. data/data/ROOT +1 -0
  8. data/data/VIEW +1 -0
  9. data/data/features.txt +18 -0
  10. data/data/global.lt3 +20 -0
  11. data/data/universal.lt3 +18 -0
  12. data/empty_view/assets/austin-pano.jpg +0 -0
  13. data/empty_view/assets/sky2.jpg +0 -0
  14. data/empty_view/config/exper/2svg.lt3 +38 -0
  15. data/empty_view/config/exper/gen_svg.rb +60 -0
  16. data/empty_view/config/exper/meta.html +10 -0
  17. data/empty_view/config/exper/s2.html +25 -0
  18. data/empty_view/config/exper/varmint.rb +50 -0
  19. data/empty_view/config/facebook/credentials.txt +7 -0
  20. data/empty_view/config/facebook/facebook.rb +42 -0
  21. data/empty_view/config/facebook/fb.html +10 -0
  22. data/empty_view/config/facebook/fb.js.lt3 +15 -0
  23. data/empty_view/config/reddit/credentials.txt +6 -0
  24. data/empty_view/config/reddit/notes.txt +4 -0
  25. data/empty_view/config/reddit/reddit_post_url.py +34 -0
  26. data/empty_view/config/reddit/redpost.rb +43 -0
  27. data/empty_view/config/reddit/the-graffiti-wall.html +91 -0
  28. data/empty_view/config/twitter/credentials.txt +3 -0
  29. data/empty_view/config/twitter/tw.html +12 -0
  30. data/empty_view/config/twitter/tw.js +5 -0
  31. data/empty_view/config/twitter/twitter.rb +35 -0
  32. data/empty_view/posts/GIT_IS_DUMB +1 -0
  33. data/empty_view/remote/assets/GIT_IS_DUMB +1 -0
  34. data/empty_view/remote/banner/navbar/GIT_IS_DUMB +0 -0
  35. data/empty_view/remote/etc/GIT_IS_DUMB +1 -0
  36. data/empty_view/remote/permalink/GIT_IS_DUMB +1 -0
  37. data/empty_view/remote/widgets/ad/GIT_IS_DUMB +2 -0
  38. data/empty_view/remote/widgets/links/GIT_IS_DUMB +2 -0
  39. data/empty_view/remote/widgets/news/GIT_IS_DUMB +2 -0
  40. data/empty_view/remote/widgets/pages/GIT_IS_DUMB +2 -0
  41. data/empty_view/remote/widgets/pinned/GIT_IS_DUMB +2 -0
  42. data/empty_view/settings/features.txt +18 -0
  43. data/empty_view/settings/publish.txt +5 -0
  44. data/empty_view/settings/recent.txt +6 -0
  45. data/empty_view/settings/view.txt +4 -0
  46. data/empty_view/themes/standard/README +59 -0
  47. data/empty_view/themes/standard/banner/banner.lt3 +5 -0
  48. data/empty_view/themes/standard/banner/navbar/about.lt3 +18 -0
  49. data/empty_view/themes/standard/banner/navbar/contact.lt3 +18 -0
  50. data/empty_view/themes/standard/banner/navbar/faq.lt3 +1 -0
  51. data/empty_view/themes/standard/banner/navbar/list.data +3 -0
  52. data/empty_view/themes/standard/banner/top.lt3 +20 -0
  53. data/empty_view/themes/standard/blog/generate.lt3 +21 -0
  54. data/empty_view/themes/standard/blog/head.lt3 +16 -0
  55. data/empty_view/themes/standard/blog/index.lt3 +17 -0
  56. data/empty_view/themes/standard/blog/post_entry.lt3 +21 -0
  57. data/empty_view/themes/standard/etc/blog.css.lt3 +62 -0
  58. data/empty_view/themes/standard/etc/externals.lt3 +24 -0
  59. data/empty_view/themes/standard/etc/favicon.ico +0 -0
  60. data/empty_view/themes/standard/etc/misc.js +20 -0
  61. data/empty_view/themes/standard/post/generate.lt3 +38 -0
  62. data/empty_view/themes/standard/post/head.lt3 +7 -0
  63. data/empty_view/themes/standard/post/index.lt3 +24 -0
  64. data/empty_view/themes/standard/post/permalink.lt3 +32 -0
  65. data/empty_view/themes/standard/widgets/README +4 -0
  66. data/empty_view/themes/standard/widgets/ad/ad.lt3 +22 -0
  67. data/empty_view/themes/standard/widgets/ad/ad1.png +0 -0
  68. data/empty_view/themes/standard/widgets/ad/ad2.png +0 -0
  69. data/empty_view/themes/standard/widgets/ad/ad3.png +0 -0
  70. data/empty_view/themes/standard/widgets/ad/ad4.png +0 -0
  71. data/empty_view/themes/standard/widgets/bydates/README +2 -0
  72. data/empty_view/themes/standard/widgets/bydates/bydates.rb +18 -0
  73. data/empty_view/themes/standard/widgets/bydates/card.css +1 -0
  74. data/empty_view/themes/standard/widgets/bydates/custom.rb +1 -0
  75. data/empty_view/themes/standard/widgets/bydates/main.css +2 -0
  76. data/empty_view/themes/standard/widgets/links/README +2 -0
  77. data/empty_view/themes/standard/widgets/links/card.css +1 -0
  78. data/empty_view/themes/standard/widgets/links/custom.rb +1 -0
  79. data/empty_view/themes/standard/widgets/links/links.rb +90 -0
  80. data/empty_view/themes/standard/widgets/links/list.data +3 -0
  81. data/empty_view/themes/standard/widgets/links/main.css +2 -0
  82. data/empty_view/themes/standard/widgets/news/README +2 -0
  83. data/empty_view/themes/standard/widgets/news/card.css +1 -0
  84. data/empty_view/themes/standard/widgets/news/custom.rb +1 -0
  85. data/empty_view/themes/standard/widgets/news/list.data +4 -0
  86. data/empty_view/themes/standard/widgets/news/main.css +2 -0
  87. data/empty_view/themes/standard/widgets/news/news.rb +88 -0
  88. data/empty_view/themes/standard/widgets/pages/README +2 -0
  89. data/empty_view/themes/standard/widgets/pages/card.css +1 -0
  90. data/empty_view/themes/standard/widgets/pages/custom.rb +1 -0
  91. data/empty_view/themes/standard/widgets/pages/disclaim.lt3 +10 -0
  92. data/empty_view/themes/standard/widgets/pages/faq.lt3 +40 -0
  93. data/empty_view/themes/standard/widgets/pages/like-dislike.lt3 +11 -0
  94. data/empty_view/themes/standard/widgets/pages/list.data +4 -0
  95. data/empty_view/themes/standard/widgets/pages/local.rb +0 -0
  96. data/empty_view/themes/standard/widgets/pages/main.css +2 -0
  97. data/empty_view/themes/standard/widgets/pages/other-stuff.lt3 +10 -0
  98. data/empty_view/themes/standard/widgets/pages/pages.rb +95 -0
  99. data/empty_view/themes/standard/widgets/pinned/README +2 -0
  100. data/empty_view/themes/standard/widgets/pinned/card.css +1 -0
  101. data/empty_view/themes/standard/widgets/pinned/custom.rb +1 -0
  102. data/empty_view/themes/standard/widgets/pinned/main.css +2 -0
  103. data/empty_view/themes/standard/widgets/pinned/pinned.rb +99 -0
  104. data/empty_view/themes/standard/widgets/search/README +2 -0
  105. data/empty_view/themes/standard/widgets/search/card.css +1 -0
  106. data/empty_view/themes/standard/widgets/search/custom.rb +1 -0
  107. data/empty_view/themes/standard/widgets/search/main.css +2 -0
  108. data/empty_view/themes/standard/widgets/search/search.rb +18 -0
  109. data/empty_view/themes/standard/widgets/sitemap/README +2 -0
  110. data/empty_view/themes/standard/widgets/sitemap/card.css +1 -0
  111. data/empty_view/themes/standard/widgets/sitemap/custom.rb +1 -0
  112. data/empty_view/themes/standard/widgets/sitemap/main.css +2 -0
  113. data/empty_view/themes/standard/widgets/sitemap/sitemap.rb +18 -0
  114. data/empty_view/themes/standard/widgets/tag-cloud/OLD-example.lt3 +12 -0
  115. data/empty_view/themes/standard/widgets/tag-cloud/README +2 -0
  116. data/empty_view/themes/standard/widgets/tag-cloud/card.css +1 -0
  117. data/empty_view/themes/standard/widgets/tag-cloud/custom.rb +1 -0
  118. data/empty_view/themes/standard/widgets/tag-cloud/main.css +2 -0
  119. data/empty_view/themes/standard/widgets/tag-cloud/tag-cloud.lt3 +3 -0
  120. data/empty_view/themes/standard/widgets/tag-cloud/tag-cloud.rb +18 -0
  121. data/lib/Javascript.stuff +69 -0
  122. data/lib/helpers-blog.rb +155 -0
  123. data/lib/helpers-repl.rb +201 -0
  124. data/lib/liveblog.rb +825 -0
  125. data/lib/logging.rb +44 -0
  126. data/lib/lowlevel.rb +73 -0
  127. data/lib/pathmagic.rb +14 -0
  128. data/lib/post.rb +211 -0
  129. data/lib/processing.rb +60 -0
  130. data/lib/publish.rb +73 -0
  131. data/lib/repl.rb +597 -0
  132. data/lib/runeblog.rb +773 -0
  133. data/lib/runeblog_version.rb +50 -0
  134. data/lib/view.rb +69 -0
  135. data/runeblog.gemspec +42 -0
  136. data/test/austin.rb +158 -0
  137. data/test/fakeimage.jpg +0 -0
  138. data/test/general_test.rb +304 -0
  139. data/test/make_blog.rb +196 -0
  140. data/test/test +3 -0
  141. 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
@@ -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
+
@@ -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
@@ -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
+
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
+